【发布时间】: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),因此杰克逊由于通过引用链的无限递归(StackOverflowError)而中断,如下所示:
org.glassfish.jersey.server.internal.process.MappableException: com.fasterxml.jackson.databind.JsonMappingException:无限 递归(StackOverflowError)(通过引用链: 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: 做我想做的事情的最佳方式是什么?
非常感谢
【问题讨论】:
-
我怀疑问题可能不是由于
ManyToOne是Lazy或Eager。您可能需要为杰克逊打破这个循环,我相信您可能需要将@JsonIgnore放在关联的一侧。 -
@MadhusudanaReddySunnapu 为什么你认为延迟获取对我没有帮助?
-
一旦您将 ManyToOne 指定为 Lazy,hibernate 就会尊重这一点,并且不会影响 ManyToOne。但是,我认为正在发生的是,随后在杰克逊反序列化期间,它也尝试反序列化 ManyToOne 关联,除非我们告诉杰克逊忽略它,因此它会导致此时获取 ManyToOne 并随后进入反序列化周期。
-
我没有尝试过,但为了排除休眠,您可能需要手动创建 ProductItem 和 Receptacle 对象,并在 OneToMany 和 ManyToOne 设置器中手动关联它们,并尝试对此对象进行杰克逊反序列化。
-
我在杰克逊开始之前关闭了 entityManager... 我想知道 hibernate 是否知道父对象已经在缓存中,因此它会自动创建循环,因此延迟获取意味着不要去数据库获取对象,但如果已经在缓存中,则构建它。有意义吗?
标签: java hibernate jpa fetch jpa-2.1