JPA2 / Hibernate - 停止延迟加载?

时间:2011-01-26 14:39:16

标签: java hibernate jpa gson

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

// Web Controller method
public String getEmployeesByQuery(String query) {

    Gson gson = new Gson();
    List<Employee> 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”错误,这是有道理的,因为我的事务已经从我的服务中提交了。

谢谢!

8 个答案:

答案 0 :(得分:6)

有几种选择:

  • 如果您总是急需加载您的收藏品,可以在地图中指定fetch = FetchType.EAGER,如其他答案所示。

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

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

      SELECT e FROM Employee e JOIN FETCH e.children WHERE ...
      
    • 使用fetch profiles(在JPA中,您可以通过Session访问Hibernate em.unwrap(Session.class)

答案 1 :(得分:3)

你真的有两个选择:

  1. 您可以将员工的数据复制到未被hibernate代理的数据。
  2. 查看是否有办法让toJSON库反映整个对象图。我知道一些JSON库允许您只将对象的某些属性序列化为JSON。
  3. 如果你的图书馆只使用反射,我个人认为#1会更容易。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

是:

@*ToMany(fetch=FetchType.EAGER)

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

  1. 将您的数据模型更改为不追踪您不想要的数据。
  2. 将您想要的数据复制到某种无需担心的DTO中。
  3. 假设你正在使用Hibernate,添加Session-in-view过滤器....就像那样,它会在序列化整个数据库时保持会话打开。 ;)
  4. 选项一是我们为我们所做的第一个大项目所做的,但它破坏了我们用于任何通用目的的数据访问库。从那时起,我们更倾向于选择二。

    YMMV

答案 7 :(得分:0)

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