JPA2 / Hibernate – 停止延迟加载?

我遇到了一个问题,即JPA在我不想要的时候试图懒洋洋地加载我的数据。 基本上发生的事情是我正在使用服务来检索一些数据,当我将数据解析为JSON时,JSON库正在触发hibernate尝试并且懒洋洋地加载数据。 有没有办法阻止这个? 我在下面给出了一个例子。

// Web Controller method public String getEmployeesByQuery(String query) { Gson gson = new Gson(); List employees = employeeService.findEmployeesByQuery(query); // Here is where the problem is occurring - the gson.toJSON() method is (I imagine) // using my getters to format the JSON output, which is triggering hibernate to // try and lazily load my data... return gson.toJSON(employees); } 

是否可以将JPA / hibernate设置为不尝试并且懒惰地加载数据?

更新:我意识到你可以使用FetchType.EAGER – 但如果我不想急于加载那些数据呢? 我只是想阻止hibernate尝试检索更多数据 – 我已经拥有了我想要的数据。 现在每当我尝试访问get()方法时,hibernate都会抛出“no session或session is closed”错误,这是有道理的,因为我的事务已经从我的服务中提交了。

谢谢!

你真的有两个选择:

  1. 您可以将数据从员工复制到未被hibernate代理的数据。
  2. 看看有没有办法让toJSON库反映整个对象图。 我知道一些JSON库允许您只将对象的某些属性序列化为JSON。

我个人认为如果您的图书馆只使用reflection,#1会更容易。

有几种选择:

  • 如果您总是需要急切地加载您的集合,则可以在映射中指定fetch = FetchType.EAGER ,如其他答案中所建议的那样。

  • 否则,您可以为特定查询启用急切提取:

    • 通过在HQL / JPQL查询中使用JOIN FETCH子句:

       SELECT e FROM Employee e JOIN FETCH e.children WHERE ... 
    • 通过使用获取配置文件 (在JPA中,您可以通过em.unwrap(Session.class)访问Hibernate Session

正如其他人所说,这不是JPA / hibernate的问题,而是你正在使用的json序列化库。 您应该指示 gson排除您不想要遍历的属性。

我建议您在事务之外制作要使用的实体的获取副本。 这样,延迟加载将在一个事务中发生,你可以传递给Gson一个普通的,而不是增强的POJO。

您可以使用Doozer执行此操作。 它非常灵活,通过一些配置(读取你将会松散你的头发配置它 )你甚至可以部分检索你想发送给Gson的数据。

是:

 @*ToMany(fetch=FetchType.EAGER) 

您始终可以将fetch属性更改为FetchType.EAGER ,但如果您的事务具有正确的范围,也值得考虑。 如果在事务中访问集合,则将正确加载集合。

您的问题是您正在序列化数据。 我们遇到了与Flex和JPA / Hibernate相同的问题。 诀窍在于,取决于你想要破坏多少东西

  1. 将数据模型更改为不追踪您不想要的数据。
  2. 将您想要的数据复制到某种没有关系担心的DTO中。
  3. 假设你正在使用Hibernate,添加Session-in-viewfilter….就像那样,它会在你序列化整个数据库时保持会话打开。 ;)

选项一是我们为第一个大项目所做的,但它破坏了我们用于任何通用目的的数据访问库。 从那时起,我们更倾向于选择二。

因人而异

简单而直接的做法是创建新的数据类(类似于DTO)使用Hibernate.isInitialized()来检查对象是否由hibernate初始化。 我正在检查gson,如果我可以覆盖任何东西。 如果我发现任何新内容,我会在此发布。