前面讲了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());
    }
}
09-16 03:45