自学内容网 自学内容网

spring-data-jpa 一对多,多对一,多对多

spring-data-jpa 一对多,多对一,多对多

首先介绍几个主要用到的注解

  • @ManyToOne 多对一
  • @ManyToMany 多对多
  • @OneToMany 一对多
  • @JoinColumn 两表之间的关联
  • @JsonIgnoreProperties 忽略属性(避免Jason套娃)

比如我有两张表:customerbill,一个customer数据对应bill中多条数据,两表通过 customer.idbill.customer_id 关联

实体如下

@Entity
@Table(name = "bill")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Bill {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "customer_id")
    private Long customerId;
    @Column(name = "bill_no")
    private String billNo;
    @Column(name = "bill_amount")
    private float billAmount;
    @Column(name = "bill_date")
    private LocalDate billDate;
}
@Entity
@Table(name = "customer")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "customer_name")
    private String customerName;
    @Column(name = "customer_age")
    private Integer customerAge;
    @Column(name = "customer_account")
    private String customerAccount;
    @Column(name = "customer_password")
    private String customerPassword;
}

为了使两张表关联起来,需要在实体中加入关联的逻辑

customer.java 中加入

@OneToMany( targetEntity = Bill.class, fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@JsonIgnoreProperties(value = {"customer"})
@JoinColumn(name = "customer_id",
        referencedColumnName = "id",
        insertable = false,
        updatable = false )
private List<Bill> bills;

Bill.java 中加入

@ManyToOne(targetEntity = Customer.class, fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@JsonIgnoreProperties(value = {"bills"})
@JoinColumn(name = "customer_id",
        referencedColumnName = "id",
        insertable = false,
        updatable = false )
private Customer customer;

下面说说如何配置使用

@ManyToOne,@ManyToMany,@OneToMany

意义就不解释了,通过注解名称就可以看懂,只说明属性

  • targetEntity

    类型:Class<?>

    指定关系的另一端实体的类型。比如上述代码中,customer实体类与bill实体关联,所以我在customer类的bills属性上的注解@OneToMany的targetEntity属性赋值Bill.class;这个属性是可选的,如果不指定,spring-data-jpa 将根据字段的类型来确定目标实体类,建议写上。

  • fetch

    类型:javax.persistence.FetchType

    指定加载策略:立即加载(FetchType.EAGER)和 延迟加载(FetchType.LAZY)

    • 立即加载:加载主实体时,其关联的实体或集合也会同时被加载。这种策略通过减少数据库查询次数来提高性能,因为它尝试在一个查询中获取所有关联实体的数据

    • 延迟加载:加载主实体时,其关联的实体或集合不会立即被加载,而是在第一次访问关联属性时才进行加载。这种策略可以减少不必要的数据库查询,因为只有在实际需要数据时才会进行加载

      使用延迟加载,我遇到了一个坑,这里顺便记录,有时一条a表数据对应几十万条b表数据,使用立即加载肯定是不合适的,故而用了延迟加载,使用延迟加载的时候,报错如下

       No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->com.train.spr.entities.Bill["customer"]->com.train.spr.entities.Customer$HibernateProxy$g4FqEJel["hibernateLazyInitializer"])
      

      如果你也遇到同样的问题,用如下方式解决
      在实体类名上加一句代码,如下

      @JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
      public class Bill {
      // 实现(略)
      }
      
  • cascade

    类型:javax.persistence.CascadeType[]

    级联操作,定义哪些持久化操作(如保存、更新、删除)应该被级联到关系的另一端实体。CascadeType是枚举类,可选值如下

    • CascadeType.ALL:表示所有的持久化操作都会级联到关系的另一端实体。这包括:PERSIST、MERGE、REMOVE、REFRESH 和 DETACH
    • CascadeType.PERSIST:当实体的对象被创建时,相关的实体也会被级联保存
    • CascadeType.MERGE:当实体被合并到当前持久化上下文时,相关的实体也会被级联合并
    • CascadeType.REMOVE:当实体被删除时,相关的实体也会被级联删除(删customer表中一条数据,jpa自动删除bill表中关联数据)
    • CascadeType.REFRESH:当实体被刷新时,相关的实体也会被级联刷新
    • CascadeType.DETACH:当实体被分离出持久化上下文时,相关的实体也会被级联分离

@JoinColumns 关联关系集合

若两张表之间通过多个字段相关联,比如A表和B表通过A.CREATE_DATE = B.CREATE_DATE AND A.ID = B.A_ID相关联,使用 @JoinColumns 包裹 @JoinColumn 集合

@JoinColumn 关联关系

定义两个实体之间以什么字段相关联;属性如下

  • name

    类型:string

    指定本表关联其他表的本表列名称

  • referencedColumnName

    类型:string

    指定本表关联其他表的其他表列名称(其他表的列名称也叫做外键)

  • unique

    类型:bool

    指定外键列是否具有唯一性约束(可选,默认false),拿我给的例子来说,一个customer可以对应多个bill,但是一个bill仅能对应一个customer,所以bill类中customer属性的@JoinColumn注解的属性改为true,表示customer中仅能有唯一一个实体与之对应

  • nullable

    类型:bool

    指定外键列是否可以为 NULL(可选,默认true),表示列可以为 NULL

  • insertable

    类型:bool

    指定外键列是否在插入操作时可被插入(可选,默认true)

  • updatable

    类型:bool

    指定外键列是否在更新操作时可被更新(可选,默认true)

  • columnDefinition

    类型:string

    指定外键列的 SQL 类型定义。这允许你自定义列的 SQL 类型和大小等详细信息(可选)

  • table

    类型:string

    指定外键列所在的表的名称。这在多表继承的场景中使用

  • foreignKey

    类型:String

    指定外键约束的名称。如果未指定,spring-data-jpa根据实体关系自动生成一个外键约束名称(可选)

@JsonIgnoreProperties JSON属性忽略

如果实体类的关联属性上不加此注解,那么你查出来的json数据结构绝对是“套娃”;属性如下

  • value

    类型:string[]

    指定忽略对方实体类中的某个属性转换为json,比如我上述例子中 customer.java 中有属性 bills,而bill.java中又有customer,所以他俩得互相忽略对方实体类中对自己引用的属性名,故而customer实体中忽略bill中的customer,bill实体中忽略customer中的bills。这么说有点抽象哈,不过你自己试一试就很轻松能明白了

  • ignoreUnknown

    类型:boolean

    ignoreUnknown 属性只适用于从 JSON 数据到 Java 对象的反序列化过程,当设置为 true 时,如果 JSON 中包含未在 Java 类中定义的属性,这些属性将被忽略。这有助于处理 JSON 数据中可能存在的额外字段,而不会抛出异常(可选)

  • allowGetters

    类型:boolean

    当设置为 true 时,即使属性没有 setter 方法,也可以通过 getter 方法访问。这通常用于只读属性(可选)

  • allowSetters

    类型:boolean

    当设置为 true 时,即使属性没有 getter 方法,也可以通过 setter 方法设置值。这通常用于只写属性(可选)


暂且写到这儿,后续有总结再补


原文地址:https://blog.csdn.net/qq_35215728/article/details/143572175

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!