在权限表中,我们一般会设计用户表、部门表、角色表,一般情况下,一个用户只能属于一个部门,但是一个用户能拥有多个角色,一个角色也可能对应多个部门。
Spring Data Jpa中提供了多个注解,用于处理表之间的关联管理。
常见注解
@OneToOne
@OneToOne
代表一对一的关联关系,需要配合@JoinColumn
一起使用。注意:可以双向关联,也可以只配置一方,需要视实际需求而定。@OneToOne
注释五个属性:targetEntity
、cascade
、fetch
、optional
和mappedBy
- fetch属性默认值是FetchType.EAGER。
- optional = true设置属性可以为null;
- targetEntity属性:Class类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义;
- 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)