首页 > 解决方案 > 使用 EJB + JPA + Jersey 进行延迟加载

问题描述

我有以下工作没有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,但无济于事。

标签: jersey-2.0java-ee-7jpa-2.1hibernate-5.xejb-3.2

解决方案


由于您的问题可以追溯到一段时间,我希望它仍然与您相关:

如果您将映射声明为惰性映射(或默认行为类似),则 JPA 在访问它之前不会获取它。因此Lazy,只有在 JSON 尝试转换整个内容时才能访问您的类,并且此时您似乎不再有打开的会话,因此无法获取数据并将导致org.hibernate.LazyInitializationException.

如果您坚持使用惰性映射(这通常很好),如果您需要用于用例的数据,则必须显式地获取或访问它。

查看Vlad对该主题的出色解释。


推荐阅读