Spring Data Jpa多表关联查询

Laughing
2021-07-21 / 0 评论 / 1,374 阅读 / 搜一下 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年03月17日,已超过386天没有更新,若内容或图片失效,请留言反馈。

在权限表中,我们一般会设计用户表、部门表、角色表,一般情况下,一个用户只能属于一个部门,但是一个用户能拥有多个角色,一个角色也可能对应多个部门。
Spring Data Jpa中提供了多个注解,用于处理表之间的关联管理。

常见注解

@OneToOne

@OneToOne代表一对一的关联关系,需要配合@JoinColumn一起使用。注意:可以双向关联,也可以只配置一方,需要视实际需求而定。
@OneToOne注释五个属性:targetEntitycascadefetchoptionalmappedBy

  1. fetch属性默认值是FetchType.EAGER。
  2. optional = true设置属性可以为null;
  3. targetEntity属性:Class类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义;
  4. cascade属性:CascadeType[]类型。该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。cascade的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表示选择全部四项。

@OneToMany、@ManyToOne

@OneToMany@ManyToOne代表一对多和多对一的关系,需要配合@JoinColumn一起使用。比如我们下面例子的用户与部门表,一个用户只属于一个部门,一个部门可以包含多个用户。

@ManyToMany

@ManyToMany代表多对多的关系。例如我们用于与角色的关联表,一般我们会设计一个用户、角色关联表的对应关系,配合@JoinTable一起使用。

示例

创建表

部门表

create table sys_dept
(
    dept_id     bigint auto_increment comment '部门id'
        primary key,
    parent_id   bigint      default 0   null comment '父部门id',
    ancestors   varchar(50) default ''  null comment '祖级列表',
    dept_name   varchar(30) default ''  null comment '部门名称',
    order_num   int         default 0   null comment '显示顺序',
    leader      varchar(20)             null comment '负责人',
    phone       varchar(11)             null comment '联系电话',
    email       varchar(50)             null comment '邮箱',
    status      char        default '0' null comment '部门状态(0正常 1停用)',
    del_flag    char        default '0' null comment '删除标志(0代表存在 2代表删除)',
    create_by   varchar(64) default ''  null comment '创建者',
    create_time datetime                null comment '创建时间',
    update_by   varchar(64) default ''  null comment '更新者',
    update_time datetime                null comment '更新时间'
)
    comment '部门表';

用户表

create table sys_user
(
    user_id                bigint auto_increment comment '用户ID'
        primary key,
    dept_id                bigint                       null comment '部门ID',
    user_name              varchar(30)                  not null comment '用户账号',
    nick_name              varchar(30)                  not null comment '用户昵称',
    user_type              varchar(2)   default '00'    null comment '用户类型(00系统用户)',
    email                  varchar(50)  default ''      null comment '用户邮箱',
    phonenumber            varchar(11)  default ''      null comment '手机号码',
    sex                    char         default '0'     null comment '用户性别(0男 1女 2未知)',
    avatar                 varchar(100) default ''      null comment '头像地址',
    password               varchar(100) default ''      null comment '密码',
    status                 varchar(5)   default 'start' null comment '帐号状态(0正常 1停用)',
    del_flag               char         default '0'     null comment '删除标志(0代表存在 2代表删除)',
    login_ip               varchar(50)  default ''      null comment '最后登录IP',
    login_date             datetime                     null comment '最后登录时间',
    create_by              varchar(64)  default ''      null comment '创建者',
    create_time            datetime                     null comment '创建时间',
    update_by              varchar(64)  default ''      null comment '更新者',
    update_time            datetime                     null comment '更新时间',
    remark                 longtext                     null comment '备注',
    recycle_company_id     bigint                       null comment '所属回收单位',
    medical_institution_id bigint                       null comment '所属医疗机构',
    ethnicity              bigint                       null comment '民族'
)
    comment '用户信息表';

角色表

create table sys_role
(
    role_id             bigint auto_increment comment '角色ID'
        primary key,
    role_name           varchar(30)             not null comment '角色名称',
    role_key            varchar(100)            not null comment '角色权限字符串',
    role_sort           int                     not null comment '显示顺序',
    data_scope          char        default '1' null comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
    menu_check_strictly tinyint(1)  default 1   null comment '菜单树选择项是否关联显示',
    dept_check_strictly tinyint(1)  default 1   null comment '部门树选择项是否关联显示',
    status              char                    not null comment '角色状态(0正常 1停用)',
    del_flag            char        default '0' null comment '删除标志(0代表存在 2代表删除)',
    create_by           varchar(64) default ''  null comment '创建者',
    create_time         datetime                null comment '创建时间',
    update_by           varchar(64) default ''  null comment '更新者',
    update_time         datetime                null comment '更新时间',
    remark              varchar(500)            null comment '备注'
)
    comment '角色信息表';

用户角色关联表

create table sys_user_role
(
    user_id bigint not null comment '用户ID',
    role_id bigint not null comment '角色ID',
    primary key (user_id, role_id)
)
    comment '用户和角色关联表';

创建实体

用户实体

@Entity
@Table(name = "sys_user")
@Data
@Slf4j
public class SysUser {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long userId;

    @JoinColumn(name = "dept_id", referencedColumnName = "dept_id")
    @ManyToOne(cascade = CascadeType.ALL)
    private SysDept sysDept;

    private String userName;

    private String nickName;

    private String userType;

    private String email;

    @Column(name = "phonenumber")
    private String phoneNumber;

    private String sex;

    private String avatar;

    @JsonIgnore
    private String password;

    @Enumerated(EnumType.STRING)
    private Status status;

    private String delFlag;

    private String loginIp;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private java.sql.Timestamp loginDate;

    private String createBy;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private java.sql.Timestamp createTime;

    private String updateBy;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private java.sql.Timestamp updateTime;

    private String remark;

    private Long recycleCompanyId;

    private Long medicalInstitutionId;

    private Long ethnicity;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "sys_user_role",
            joinColumns = {@JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")})
    private Set<SysRole> sysRoles;

}

部门实体

@Entity
@Table(name = "sys_dept")
@Getter
@Setter
@ToString
@RequiredArgsConstructor
public class SysDept {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "dept_id")
  private long deptId;

  private long parentId;

  private String ancestors;

  private String deptName;

  private long orderNum;

  private String leader;

  private String phone;
  private String email;
  private String status;
  private String delFlag;
  private String createBy;
  private java.sql.Timestamp createTime;
  private String updateBy;
  private java.sql.Timestamp updateTime;

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
    SysDept sysDept = (SysDept) o;

    return Objects.equals(deptId, sysDept.deptId);
  }

  @Override
  public int hashCode() {
    return 866095534;
  }
}

角色实体

@Entity
@Data
public class SysRole {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long roleId;
    private String roleName;
    private String roleKey;
    private long roleSort;
    private String dataScope;
    private long menuCheckStrictly;
    private long deptCheckStrictly;
    private String status;
    private String delFlag;
    private String createBy;
    private java.sql.Timestamp createTime;
    private String updateBy;
    private java.sql.Timestamp updateTime;
    private String remark;

}

用户角色关联实体

@Entity
@IdClass(SysUserRole.class)
@Data
public class SysUserRole implements Serializable {

  @Id
  @Column(name = "user_id")
  private long userId;

  @Id
  @Column(name = "role_id")
  private long roleId;

}

Jpa查询接口

这个接口不是必须的,可以调用任意的Crud接口。

public interface SysUserRepository extends JpaRepository<SysUser, Long> {

    /**
     * 根据用户名称查找列表
     *
     * @param userName 用户名称
     * @return 列表
     */
    List<SysUser> findByUserName(String userName);

    //    @Query("select u from SysUser u")
    Stream<SysUser> readAllBy();

    Stream<SysUser> streamAllBy();

    @Async
    Future<List<SysUser>> findAllBy();

    @Query("select u from SysUser u where u.userName = :userName and u.email = :email")
    SysUser findByUserNameAndEmail(@Param("userName") String userName, @Param("email") String email);

    @Query("select u from SysUser u where u.nickName like %:nickName%")
    List<SysUser> findAllByNickName(@Param("nickName") String nickName);

    @Query(value = "select * from sys_user u where email like concat('%',:email,'%')", nativeQuery = true)
    List<SysUser> findAllByEmailLike(@Param("email") String email);

    @Query(value = "select u from SysUser  u")
    Page<SysUser> findAllBy(Pageable pageable);

    SysUser findFirstByUserId(Long userId);

    @Modifying(clearAutomatically = true)
    @Query(value = "update SysUser set remark = '234' where userId = :userId")
    int setRemarkByUserId(@Param("userId") Long userId);
}

测试

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private SysUserRepository sysUserRepository;

    @GetMapping("/findAll")
    @Transactional
    public SysUser findAll() {
        return sysUserRepository.findFirstByUserId(111L);
    }

}
0

评论 (0)

取消