JPA - 不要扩展对其他类的引用

Posted

技术标签:

【中文标题】JPA - 不要扩展对其他类的引用【英文标题】:JPA - do not expand reference to other class 【发布时间】:2020-04-14 01:49:57 【问题描述】:

在 Spring Boot 应用程序中,我有一个类 A,它引用了另一个类 B。类 A 中的引用用 @ManyToOne 注释。

当我从 A 类获取记录时,对 B 类的每个引用都会扩展以显示 B 中的值。

如果我添加一个@JsonIdentityInfo 注释,那么列出类 A 只会在第一次检索时扩展类 B 引用。具有相同 B 类 ref 的后续 A 类记录仅具有 id。

什么注释我不需要扩展class B ref,以便每个class A记录简单地显示class B id。

更新代码

气候.java

@Entity
@SequenceGenerator(name = "climate_gen", sequenceName = "climate_gen", initialValue = 100)
public class Climate 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "climate_gen")
    private long id;

    private float temperature;
    private float humidity;
    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime date;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "location_id", nullable = false)
    private Location location;

位置.java

@Entity
@SequenceGenerator(name = "location_gen", sequenceName = "location_gen", initialValue = 100)
public class Location 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "location_gen")
    private long id;
    private String name;
    private String gps;
    private String timezone;

因此,将 fetchType 设置为 EAGER 可以为每种气候提供扩展的位置记录。

将 fetchtype 设置为 LAZY 会出错

$ curl -k -w "\n" -H "授权:不记名$TOKEN" https://mint191:8453/api/v1/climates “时间戳”:“2019-12-23T16:33:36.047+0000”,“状态”:500,“错误”:“内部 Server Error","message":"类型定义错误:[简单类型,类 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor];嵌套的 例外是 com.fasterxml.jackson.databind.exc.InvalidDefinitionException:否 为类找到序列化程序 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor 并且没有 发现创建 BeanSerializer 的属性(为了避免异常, 禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用 链: java.util.ArrayList[0]->com.norricorp.bikes.model.Climate[\"location\"]->com.norricorp.bikes.model.Location$HibernateProxy$atNV2KHn[\"hibernateLazyInitializer\"])" ,"路径":"/api/v1/climates"

问候,

【问题讨论】:

【参考方案1】:

如果我没听错,那么我猜你是在 OneToMany 注释中搜索 LazyLoading 注释

  @OneToMany(fetch = FetchType.LAZY)

例如:https://www.baeldung.com/hibernate-lazy-eager-loading

也许你可以分享一些示例代码?

【讨论】:

我原以为惰性会起作用,但它会导致读取错误。我也有ManyToOne的关系。让我在更新的问题中显示代码。 您能否尝试在您的延迟加载的私有属性上添加注释:@JsonIgnoreProperties("hibernateLazyInitializer", "handler")【参考方案2】:

这里有一些想法:

使用自定义 Jackson serializer - example

在杰克逊处理bidirectional relationships 的其他方式

使用带有 JPQL Constructor Expression 的自定义查询 - 更多关于 SO 和本文中的内容:The best way to map a projection query to a DTO (Data Transfer Object) with JPA and Hibernate

而不是A 直接引用B,使用BId 实体映射到与B 相同的表:How to map multiple JPA entities to one database table with Hibernate。这是一个非常简单的project,我正在使用这种方法

使用Spring Data JPA Projections或DTO Projections

更新(2019 年 12 月 25 日)

当使用FetchType.LAZY 时,Hibernate 返回一个proxy。 以下是解决您遇到的错误的一些方法:

Jackson – JsonMappingException (No serializer found for class)

No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor

Avoid Jackson serialization on non fetched lazy objects

【讨论】:

谢谢你。我认为序列化程序是要走的路。尽管从我现在读到的内容来看,气候中的私有字段应该可以访问,因为有 getter 和 setter,但编译器错误 - 由于私有访问,它们不可见。 我最终使用了自定义序列化程序。似乎是最直接有效的。我也只是引用了公共吸气剂并将属性保留为私有。再次,尽管每个例子都说它可以工作,但直接引用私有属性并没有起作用。将此标记为答案。

以上是关于JPA - 不要扩展对其他类的引用的主要内容,如果未能解决你的问题,请参考以下文章

django模型引用其他类的对象

软件工程设计原则

不变类

类的设计技巧简单总结

《Java编程思想》笔记 第七章 复用类

Spring学习指南-第二章-Spring框架基础