使用 EJB + JPA + Jersey 进行延迟加载
Posted
技术标签:
【中文标题】使用 EJB + JPA + Jersey 进行延迟加载【英文标题】:Lazy Loading with EJB + JPA + Jersey 【发布时间】:2018-10-23 19:02:54 【问题描述】:没有FetchType.LAZY
,我有以下工作:
@Entity
public class Test
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
@ManyToOne
@JoinColumn(name = "lazy_id")
private Lazy lazy;
//getters and setters
@Entity
public class Lazy
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
//getters and setters
以及查询方法:
public List<Test> all()
try
return em.createQuery("FROM Test t").getResultList();
catch (NoResultException e)
return null;
这是 JSON 结果:
["id":1,"text":"test 1","lazy":"id":1,"text":"lazy 1",
"id":2,"text":"test 2","lazy":"id":2,"text":"lazy 2"]
但是我只想返回 id 和 text 数据,所以我尝试更改 @ManyToOne(fetch = FetchType.LAZY)
然后我得到这个错误:
Severe: Generating incomplete JSON
Severe: org.hibernate.LazyInitializationException: could not initialize proxy [model.Lazy#1] - no Session
我可以做一些事情,比如更改查询以仅获取我想要的字段:
public List<Test> all()
try
return em.createQuery("SELECT t.id, t.text FROM Test t").getResultList();
catch (NoResultException e)
return null;
但是我在 javascript 前端的响应是:
[[1,"test 1"],[2,"test 2"]]
不再是对象数组,映射所有实体的数量与我所拥有的实体数量相去甚远。
我发现的大部分内容是之后如何获取数据,这不是我关心的,我只需要首先发送我想要的字段。我不确定是否应该使用 EJB @TransactionAttribute,我找不到工作示例。我还尝试将策略更改为 Lazy 类中的@OneToMany,但无济于事。
【问题讨论】:
【参考方案1】:由于您的问题可以追溯到一段时间,我希望它对您仍然相关:
如果您将映射声明为惰性映射(或默认行为类似),则 JPA 在访问它之前不会获取它。所以你的Lazy
类只有在JSON试图转换整个东西时才会被访问,此时你似乎不再有一个打开的会话,所以数据不能被获取并且会导致org.hibernate.LazyInitializationException
。
如果您坚持使用惰性映射(这通常很好),如果您需要用于用例的数据,则必须显式获取或访问它。
查看Vlad's excellent explanation 的主题。
【讨论】:
是的,我确实在使用带有 JPA 投影的 DTO 设计模式,这是我能找到的所有东西,但它仍然非常糟糕。我试图找到一种让 Jersey/Jackson 理解 FetchType.LAZY 的方法,但它太不成功了,所以我暂时把它放在一边。如果我弄清楚了,我会在这里发布答案。以上是关于使用 EJB + JPA + Jersey 进行延迟加载的主要内容,如果未能解决你的问题,请参考以下文章
在 EntityListener 中使用带有 PersistenceContext 的 EJB 时,JPA 尝试在数据库中插入相同的实体两次