hibernate/jpa 忽略 @XxxToOne 关系中的 LAZY FETCHING

Posted

技术标签:

【中文标题】hibernate/jpa 忽略 @XxxToOne 关系中的 LAZY FETCHING【英文标题】:hibernate/jpa ignoring LAZY FETCHING in @XxxToOne relationship 【发布时间】:2018-03-21 03:58:08 【问题描述】:

我使用 hibernate 5 作为 JPA 实现,我遇到了 @OneToMany 双向关系的问题。

这些是我的实体:

@Entity(name = "product_item")
public class ProductItem 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "receptacle")
    private Receptacle receptacle;

...



@Entity(name = "receptacle")
public class Receptacle 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @OneToMany(mappedBy = "receptacle", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Set<ProductItem> productItems = new HashSet<>();

...


我希望这种关系在两个方向上都是惰性的,因为我想通过 FETCH JOIN 手动获取数据,如下面的查询:

String query = "SELECT " 
            + " DISTINCT r" 
            + " FROM" 
            + " receptacle r"
            + " JOIN FETCH product_item pi ON r.id = pi.receptacle.id"
            + " JOIN ereturn er ON er.id = pi.ereturn.id"
            + " WHERE"
            + " r.masterCrossDock IS NULL"; 

但我的问题是休眠忽略了@ManyToOne(fetch = FetchType.LAZY),因此杰克逊由于通过引用链的无限递归(***Error)而中断,如下所示:

org.glassfish.jersey.server.internal.process.MappableException: com.fasterxml.jackson.databind.JsonMappingException:无限 递归(***Error)(通过引用链: returnitRest.Receptacle["productItems"]->org.hibernate.collection.internal.PersistentSet[0]->returnitRest.ProductItem["receptacle"]->returnitRest.Receptacle["productItems"]->org.hibernate.collection。 internal.PersistentSet[0]->returnitRest.ProductItem["receptacle"]- ...

问题 1: 如何告诉 hibernate 不要获取 @ManyToOne 关系方向?

问题 2: 如果我试图做的事情是不可能的,为什么?

问题 3: 做我想做的事情的最佳方式是什么?

非常感谢

【问题讨论】:

我怀疑问题可能不是由于ManyToOneLazyEager。您可能需要为杰克逊打破这个循环,我相信您可能需要将@JsonIgnore 放在关联的一侧。 @MadhusudanaReddySunnapu 为什么你认为延迟获取对我没有帮助? 一旦您将 ManyToOne 指定为 Lazy,hibernate 就会尊重这一点,并且不会影响 ManyToOne。但是,我认为正在发生的是,随后在杰克逊反序列化期间,它也尝试反序列化 ManyToOne 关联,除非我们告诉杰克逊忽略它,因此它会导致此时获取 ManyToOne 并随后进入反序列化周期。 我没有尝试过,但为了排除休眠,您可能需要手动创建 ProductItem 和 Receptacle 对象,并在 OneToMany 和 ManyToOne 设置器中手动关联它们,并尝试对此对象进行杰克逊反序列化。 我在杰克逊开始之前关闭了 entityManager... 我想知道 hibernate 是否知道父对象已经在缓存中,因此它会自动创建循环,因此延迟获取意味着不要去数据库获取对象,但如果已经在缓存中,则构建它。有意义吗? 【参考方案1】:

根据 JPA 规范,延迟加载是提供者可以完全忽略的提示,完全取决于提供者(此处为休眠)是否考虑它或忽略它(还考虑到单值关联 -OneToOne 和 ManyToOne - 默认情况下急切加载)....所以你不能依赖它。

关于递归问题,请查看my post here,我遇到了与 gson 类似的问题,这就是我解决它的方法

【讨论】:

以上是关于hibernate/jpa 忽略 @XxxToOne 关系中的 LAZY FETCHING的主要内容,如果未能解决你的问题,请参考以下文章

hibernate jpa 报错

Spring Hibernate JPA 联表查询

Spring Hibernate JPA 联表查询 复杂查询

Hibernate JPA 的异常

直接加入 JPA 或 HIBERNATE

Hibernate + JPA:模式验证:缺少列