一、概念:
1、级联关系类型:
- CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法
- CascadeType.REMOVE:级联删除,当调用remove()方法删除Order实体时会先级联删除OrderItem的相关数据
- CascadeType.MERGE:级联更新,当调用了Merge()方法,如果Order中的数据改变了会相应的更新OrderItem中的数据
- CascadeType.ALL:包含以上所有级联属性
- CascadeType.PERSIST:级联保存,当调用了Persist() 方法,会级联保存相应的数据
2、mappedBy属性的用法
- mappedBy 单向关系不需要设置该属性,双向关系必须设置,避免双方都建立外键字段**数据库**中1对多的关系,关联关系总是被多方维护的即外键建在多方,我们在单方对象的@OneToMany(mappedby=” “);
- 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
- mappedBy标签一定是定义在the owned side(被拥有方的),他指向theowning side(拥有方);
- 关系的拥有方负责关系的维护,在拥有方建立外键。所以用到@JoinColumn
- mappedBy跟JoinColumn/JoinTable总是处于互斥的一方
1. @OneToOne
单向映射,在字段上使用@OneToOne注解和@JoinColumn(name=”xxxx”),其中xxxx为当前表中关联其他表的字段,该字段为其他表的主键
(1)代码实例:
1、AdminEntity表:
@Entity
@Table(name = "identity_card_entity")
public class IdentityCardEntity implements Serializable{
//序列化
private static final long serialVersionUID = 1L;
/**
* 数据库自增长ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 删除标识
*/
private boolean delFlag = true;
/**
* 身份证号
*/
private String userNumber;
/**
* 用户-身份证(一对一)
*/
@OneToOne
@JoinColumn(name = "id")
private UserEntity userEntity;
}
2、UserEntity表:
/**
* 用户实体
* @ClassName: UserEntity
* @Description:
* @Author :chengwenixng
* @Copyright: Smartlab411
* @DateTime 2021-05-13 10:55:01
*/
@Entity//表示该类是一个实体
@Table(name = "user_entity")//数据库总将创建一个名user_entity的表
public class UserEntity implements Serializable{
//序列化
private static final long serialVersionUID = 1L;
/**
* 数据库自增长ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 删除标识
*/
private boolean delFlag = true;
/**
* 用户名字
*/
private String userName;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private IdentityCardEntity identityCardEntity;
}
如上代码表示:basicUser_id字段是与 AdminEntity表相关联表BasicUserEntity对应的id字段。
(2)数据库表之间的关联
图1:用户表
图2:身份证表
总结:观察数据库表我们得知用户表通过身份证id字段 identity_card_entity_id与身份证表进行了关联
2. JPA中@OneToMany映射(one方获得维护权,many方提供数据)
(1)one方注解:
/**
*
* @ClassName: TeacherEntity
* @Description:
* @Author :chengwenixng
* @Copyright: Smartlab411
* @DateTime 2021-05-14 15:33:32
*/
@Entity//表示该类是一个实体
@Table(name = "teacher_entity")//数据库总将创建一个名user_entity的表
public class TeacherEntity implements Serializable{
//序列化
private static final long serialVersionUID = 1L;
/**
* 数据库自增长ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 删除标识
*/
private boolean delFlag = true;
/**
* 用户名字
*/
private String teacherName;
/**
* 讲师-学生(多对一)
*/
@OneToMany(mappedBy = "teacherEntity", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<StudentEntity> studentEntities = new ArrayList<>();
}
其中cascade = CascadeType.ALL使one获得所有级联权限
/**
*
* @ClassName: StudentEntity
* @Description:
* @Author :chengwenixng
* @Copyright: Smartlab411
* @DateTime 2021-05-14 15:34:03
*/
@Entity//表示该类是一个实体
@Table(name = "student_entity")//数据库总将创建一个名user_entity的表
public class StudentEntity implements Serializable{
//序列化
private static final long serialVersionUID = 1L;
/**
* 数据库自增长ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 删除标识
*/
private boolean delFlag = true;
/**
* 学生名字
*/
private String studentName;
/**
* 学生-讲师(多对一)
*/
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private TeacherEntity teacherEntity;
}
如不需要相互映射,可不写many方代码
数据库表对比:
图3:学生表
图4:老师表
总结:观察数据库表我们得知学生表通过老师teacher_entity_id字段与讲师表表进行了关联
2. JPA中@ManyToMany映射:
(1)单向 ManyToMany
多对多关联关系中只能通过中间表的方式进行映射。
@ManyToMany 注解用于关系的发出端
同时关系的发出端--定义一个集合类型的接收端的字段属性;
关系的接收端,不需要做任何定义;
单向是指类层面,在下面例子中老师类可以知道要教哪些学生,学生不知被哪些老师教
需要用到连接表@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},inverseJoinColumns={@JoinColumn(name="student_id")}
)
也可以不用连接表,但是若不用连接表,表名、列名规则:
在student表中没有写外键则会用对方的表名_主键名
在teacher表中有外键,则会s_id(也是student的主键名)
表名是student_teacher
student类:
@Entity//表示该类是一个实体
@Table(name = "student")
public class student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
}
Teacher类
@Entity//表示该类是一个实体
@Table(name = “teacher")
public class teacher implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@ManyToMany
@JoinTable(name="t_s",joinColumns={@JoinColumn(name="teacher_id")},inverseJoinColumns={@JoinColumn(name="student_id")} )//将会以上两个字段为联合主键
//定义中间表的名称,列名:joinColumns,inverseJoinColumns是预防组合主键的时候。
private List<Student> routerList = new ArrayList<>();
}
(2)双向 ManyToMany
@ManyToMany 注解用于关系的发出端和接收端
同时关系的发出端和接收端--定义一个集合类型的接收端的字段属性;
关系的接收端,@ManyToMany(mappedBy='集合类型发出端实体的字段名称');
/**
* @ClassName: RouterEntity
* @Description: 路由实体
* @Author chengwenxing
* @DateTime 2021-03-31
*/
@Entity
@Table(name ="router_entity")
public class RouterEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
/**
* 路由-角色(多对多)
*/
@JSONField(serialize = false)
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "router_relate_role", joinColumns = @JoinColumn(name = "router_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<RoleEntity> joinRoleList = new ArrayList<>();
}
/**
* @ClassName: RoleEntity
* @Description:角色实体
* @Author chengwenxing
* @DateTime 2021-03-31
*/
@Entity
@Table(name ="role_entity")
public class RoleEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
/**
* 路由-角色(多对多)
*/
@JSONField(serialize = false)
@ManyToMany(mappedBy = "joinRoleList", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<RouterEntity> routerList = new ArrayList<>();
}