Spring Data JPA 多对多实现多表关联查询

    技术2024-11-03  31

    需求介绍

    角色与用户关系,一个用户可能拥有多个角色,一个角色也能对应多个用户。

    主要存在三张表,sys_user(用户表),sys_role(角色表),sys_user_role(用户角色关联表)

    功能实现

    实现查询所有用户及所包含的角色权限。

    实体类

    用户SysUser

    import javax.persistence.*; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.GenericGenerator; /** * @Description: 用户 * @Author: hk * @Date: 2020-06-23 22:37:58 */ @Getter @Setter @Entity @Table(name = "sys_user") public class SysUser extends AbstractAuditable implements Serializable { @Id @GenericGenerator(name = "genericGenerator", strategy = "uuid") @GeneratedValue(generator = "genericGenerator") private Integer id; @Column(name = "name") private String name; @Column(name = "password") private String password; //单向多对多 @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "sys_user_role" ,joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "id") ,inverseJoinColumns = @JoinColumn(name = "role_id",referencedColumnName = "id")) private List<SysRole> roles = new ArrayList<>(); }

    注: @ManyToMany 需要和@JoinTable表结合使用,ManyToMany总是使用中间关系连接表来存储关系。

    mappedBy:若关系是双向的则需要使用到。JoinTablce和JoinColumn一般定义在拥有关系的这一端,而mappedBy一定是定义在关系的被拥有方,属性值为中间关联表对应的实体。cascade: CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法 CascadeType.REMOVE:级联删除,当调用remove()方法删除Order实体时会先级联删除OrderItem的相关数据 CascadeType.MERGE:级联更新,当调用了Merge()方法,如果Order中的数据改变了会相应的更新OrderItem中的数据 CascadeType.ALL:包含以上所有级联属性 CascadeType.PERSIST:级联保存,当调用了Persist() 方法,会级联保存相应的数据

    @JoinTable 如果对象与对象之间有一个关联关系表的时候,就会用到@JoinTable

    角色SysRole

    import javax.persistence.*; import java.io.Serializable; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.GenericGenerator; /** * @Description: 角色 * @Author: hk * @Date: 2020-06-23 22:37:57 */ @Getter @Setter @Entity @Table(name = "sys_role") public class SysRole extends AbstractAuditable implements Serializable { @Id @GenericGenerator(name = "genericGenerator", strategy = "uuid") @GeneratedValue(generator = "genericGenerator") private Integer id; @Column(name = "name") private String name; }

    用户角色关联SysUserRole

    /** * @Description: 用户角色关联 * @Author: hk * @Date: 2020-06-23 22:37:58 */ @Getter @Setter @Entity @IdClass(value = SysUserRoleKey.class) @Table(name = "sys_user_role") public class SysUserRole extends AbstractAuditable implements Serializable { @Id @Column(name = "user_id") private String userId; @Id @Column(name = "role_id") private String roleId; }

    联合主键SysUserRoleKey

    import lombok.Getter; import lombok.Setter; import java.io.Serializable; /** * @Description: 用户角色联合主键 * @Author: hk * @Date: 2020-06-23 23:02 */ @Getter @Setter public class SysUserRoleKey implements Serializable { private String userId; private String roleId; public SysUserRoleKey(String userId, String roleId) { this.userId = userId; this.roleId = roleId; } public SysUserRoleKey() { } }

    这边只是简单查询所用用户及具备的角色权限。所以省略server层与dao层

    Controller 层

    import com.hk.entity.SysUser; import com.hk.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @Description: * @Author: hk * @Date: 2020-06-23 22:37:58 */ @RestController @RequestMapping("sysUser") public class SysUserController { private SysUserService sysUserService; @Autowired public SysUserController(SysUserService sysUserService) { this.sysUserService = sysUserService; } @RequestMapping(value = "/all") public List<SysUser> findAll() { return sysUserService.findAll(); } }

    查询效果

    Processed: 0.015, SQL: 9