使用 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 进行延迟加载的主要内容,如果未能解决你的问题,请参考以下文章

使用 JPA2 时如何对 EJB 进行单元测试?

使用 JPA2 时如何对 EJB 进行单元测试?

在 EntityListener 中使用带有 PersistenceContext 的 EJB 时,JPA 尝试在数据库中插入相同的实体两次

JPA与EJB3的关系

Spring+Jersey+JPA+Hibernate+MySQL实现CRUD操作案例

如何使用 JPA/EJB3 和 WildFly 读取未提交的数据?