2

编辑- 我已经使用库https://github.com/FasterXML/jackson-module-hibernate解决了我的 jackson/hibernate 的具体问题。解决方案不是我在这里搜索的解决方案,但在我的情况下同样有效。

原始问题:

org.hibernate.LazyInitializationException我最近在使用 Hibernate/Spring/Jackson 时遇到了臭名昭著的问题。当杰克逊试图序列化和对象时,我的问题就出现了,找到了一个延迟获取的值的属性并努力访问它。我已经阅读了很多关于此的问题、帖子和讨论,但建议的解决方案似乎总是两种选择的变体

  • 确保在事务结束之前加载惰性属性。
  • 配置 jackson 忽略该属性。

我想知道是否还有另一种解决方案,因为事实是,当我的服务返回一个带有一些未初始化属性的 Hibernate 对象时,我想以这种方式显示该对象。为特定目的配置杰克逊似乎是一种策略,其中表示层需要复杂的数据库层知识,这似乎是一个糟糕的解决方案。

从我最初对框架的看法开始,我希望它的工作方式是,每当在事务之外访问 Hibernate 实体时,hibernate 不应该关心该对象,它应该像普通的 POJO 一样工作。在本质上:

  1. 开始交易
  2. 对 Hibernate 托管对象执行 CRUD 操作。
  3. 结束事务并可能返回获取/修改的对象,这些对象可以在没有事件传播到底层数据库的情况下读取/更改。

期望行为示例:

//Start transaction
MyEntity entity = entityManager.find(primaryKey, MyEntity.class);
entity.getLazyLoadedFooList(); //Load the list from database
//End transaction
entity.getLazyLoadedBarList(); //Return null instead of throw LazyInitializationException

基本思想是应用程序具有表示层、服务层和 DAO 层。DAO 层关注针对数据库的 CRUD 操作。服务层将 DAO 方法包装在事务中,并返回代表所请求数据的 java 对象。然后这些对象可供表示层使用,表示层将它们原样转换为所需的格式,在本例中为 JSON。

关于这个的两个问题:

  • 可以像我描述的那样或以类似的方式完成吗?
  • 这是一个好/坏主意吗?
4

3 回答 3

0

获取实体后,您可以detach从休眠会话中获取。

之后您将不会得到任何LazyInitializationException信息(但惰性字段将为空)。

所以按照你的例子:

   //Start transaction
   MyEntity entity = entityManager.find(primaryKey, MyEntity.class);
   entity.getLazyLoadedFooList(); //Load the list from database
   //End transaction
    entityManager.clear(); // detaches the enitities
    entity.getLazyLoadedBarList(); //Return null instead of throw LazyInitializationException
于 2013-05-27T09:30:49.823 回答
0

您可以尝试使用以下代码将实体从休眠实体更改为常规 POJO。我使用它来读取存在于我的代码中但不存在于休眠代理中的类的注释。

import org.hibernate.proxy.HibernateProxy;

import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;

public class StripHibernateProxy {

    // This function takes the hibernate entity and forces it to be a real java
    // object instead

@SuppressWarnings("unchecked")
public static <T> T initializeAndUnproxy(T entity) {

            if (entity == null) {
                    throw new NullPointerException("Entity passed for initialization is null");
            }

            Hibernate.initialize(entity);

            if (entity instanceof HibernateProxy) {
                    entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
            }

            return entity;
    }
}
于 2013-05-28T20:10:59.397 回答
0

这个问题有真正的答案吗?多年来我一直沉迷于它,只发现了一些 hack 解决方案,如 Gilead 或 Jackson-hibernate 模块。如果 hibernate 能够遵守 POJO 合同而不抛出异常,那就太好了,至少如果它被设置为这样做的话。也许某种类似于只读的提示。

List<Customer> list = em.createQuery(q, Customer.class)
            .setParameter("lastName", "Vest")
            .setHint("org.hibernate.readOnly", true)
            .getResultList();
于 2017-01-10T08:55:12.900 回答