关于在JPA中使用@OneToOne @OneToMany @ManyToOne @ManyToMany

1,666 阅读2分钟

一、概念:

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<>();

}