【问题标题】:Hibernate lazy loading within 3-tier java ee application3层java ee应用程序中的休眠延迟加载
【发布时间】:2017-12-19 21:49:10
【问题描述】:

我已经使用 hibernate 和 wildly 10 构建了一个 Java EE 应用程序。我没有使用任何 servlet,而是使用 Java API 构建的 REST API 用于 RESTful WebService。因为我的模型变得越来越大,所以我将我的收藏集从FetchType.EAGER 设置为FetchType.LAZY。现在我收到了LazyInitializationException 和消息could not initialize proxy - no Session。我想我确实理解为什么会发生这种情况,但我不明白 hibernate 何时尝试访问代理。

实体:

@Entity
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Version
    private Timestamp lastChanged;

    @NotNull
    private Date creationDate;

    @ManyToMany
    private Set<Entity> lazyEntity;

    public User() { }

    // getters and setters
}

DAO:

public interface UserDAO {
    public List<User> getAll();
}

豆:

@Stateless
@Remote(UserDAO.class)
public class UserBean<User> implements UserDAO {

    @PersistenceContext
    protected EntityManager em;

    @Override
    public List<User> getAll() {
        return this.em.createQuery("SELECT u FROM User u ORDER BY u.creationDate", User.class)
                      .getResultList();
    }
}

端点:

@Path("/users")
@Stateless
public class UsersEndpoint {

    @EJB
    private UserDAO userDAO;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll() {
        List<User> users = userDAO.getAll();
        if (users.size() == 0)
            return Response.status(Response.Status.NOT_FOUND)
                           .build();
        return Response.ok(users).build();
    }
}

我的问题是为什么lazyEntity 不只是返回为 null 而是抛出错误?在哪一部分是休眠尝试访问lazyEntity,因为正如您在上面的代码中看到的那样,我不会尝试在API端点内访问。我能捕捉到异常吗?

如何在不出现异常的情况下接收如下对象?我已经看到可以通过更改属性hibernate.enable_lazy_load_no_trans 来禁用它。但我也read 表示不强烈推荐。

User {
    id: 1,
    lastChanged: 0981283812738,
    creationDate: 2178371283098,
    lazyEntity: null
}

【问题讨论】:

    标签: hibernate rest jakarta-ee lazy-loading 3-tier


    【解决方案1】:

    我认为问题在于 getAll() 方法的 JSON 序列化导致 UsersEndpoint(由方法上的注释触发)。

    我假设您使用 Jersey+Jackson(这是一种常见的 JavaJSON 转换器)。

    当 getAll() 方法完成后,Jackson 获取该方法的结果并尝试通过获取 User 类的所有数据将其转换为 JSON。为此,Jackson 在 User 类中调用 getLazyEntity() ,并且由于它是延迟加载的,因此触发了数据库访问(并且由于会话关闭而失败)。

    如果您想在 JSON 响应中包含“lazyEntity”的数据,则必须在会话关闭之前获取数据:在 DAO 内部,在 HQL 查询中使用 fetch join。

    如果您不想要 JSON 中的lazyEntity,您必须告诉 Jackson 不要序列化 ​​lazyEntity,您可以使用 Jackson 视图来做到这一点。请参阅How can a @JsonView working with jerseyhttp://wiki.fasterxml.com/JacksonJsonViews

    【讨论】:

    • 感谢您的解释。但我找不到 @JsonView 注释。还有其他方法吗?
    • 好的,我明白了。但是我用@JsonIgnore代替了@JsonView。我认为这是更少的代码还是您不同意?
    • 我同意@JsonView 很麻烦。它的优点是一个属性可以映射到多个@JsonView,这允许有一些端点序列化对象的所有属性,而其他端点只序列化对象的一部分。
    猜你喜欢
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多