前面讲了Spring Boot 使用 JPA,实现JPA 的增、删、改、查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用。JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层和sql语句即可实现完整的数据操作方法。但是,之前都是介绍的单表的增删改查等操作,多表多实体的数据操作怎么实现呢?接下来聊一聊 JPA 的一对一,一对多,多对一,多对多等实体映射关系。
一、常用注解详解
@JoinColumn指定该实体类对应的表中引用的表的外键,name属性指定外键名称,referencedColumnName指定应用表中的字段名称
@JoinColumn(name=”role_id”): 标注在连接的属性上(一般多对1的1),指定了本类用1的外键名叫什么。
@JoinTable(name="permission_role") :标注在连接的属性上(一般多对多),指定了多对多的中间表叫什么。
备注:Join的标注,和下面几个标注的mappedBy属性互斥!
@OneToOne 配置一对一关联,属性targetEntity指定关联的对象的类型 。
@OneToMany注解“一对多”关系中‘一’方的实体类属性(该属性是一个集合对象),targetEntity注解关联的实体类类型,mappedBy注解另一方实体类中本实体类的属性名称
@ManyToOne注解“一对多”关系中‘多’方的实体类属性(该属性是单个对象),targetEntity注解关联的实体类类型
属性1: mappedBy="permissions" 表示,当前类不维护状态,属性值其实是本类在被标注的链接属性上的链接属性,此案例的本类时Permission,连接属性是roles,连接属性的类的连接属性是permissions
属性2: fetch = FetchType.LAZY 表示是不是懒加载,默认是,可以设置成FetchType.EAGER
属性3:cascade=CascadeType.ALL 表示当前类操作时,被标注的连接属性如何级联,比如班级和学生是1对多关系,cascade标注在班级类中,那么执行班级的save操作的时候(班级.学生s.add(学生)),能级联保存学生,否则报错,需要先save学生,变成持久化对象,在班级.学生s.add(学生)
注意:只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
二、一对一
首先,一对一的实体关系最常用的场景就是主表与从表,即主表存关键经常使用的字段,从表保存非关键字段,类似 User与UserDetail 的关系。主表和详细表通过外键一一映射。
一对一的映射关系通过@OneToOne 注解实现。通过 @JoinColumn 配置一对一关系。
其实,一对一有好几种,这里举例的是常用的一对一双向外键关联(改造成单向很简单,在对应的实体类去掉要关联其它实体的属性即可),并且配置了级联删除和添加,相关类如下:
1、User 实体类定义:
package com.weiz.pojo; import lombok.Getter; import lombok.Setter; import javax.persistence.*; @Getter @Setter @Entity @Table(name = "Users") public class Users { @Id @GeneratedValue private Long id; private String name; private String account; private String pwd; @OneToOne(cascade = {CascadeType.PERSIST,CascadeType.REMOVE}) @JoinColumn(name="detailId",referencedColumnName = "id") private UsersDetail userDetail; @Override public String toString() { return String.format("Book [id=%s, name=%s, user detail=%s]", id, userDetail.getId()); } }