2011-01-26 288 views
9

我遇到问题,JPA试图在我不想要的时候懒洋洋地加载我的数据。基本上发生了什么是我正在使用服务来检索一些数据,当我将这些数据解析为JSON时,JSON库正在触发休眠以尝试并延迟加载数据。有什么办法可以阻止它吗?下面给出了一个例子。JPA2 /休眠 - 停止延迟加载?

// 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 /休眠不尝试并延迟加载数据?

更新:我意识到你可以使用FetchType.EAGER - 但如果我不想急于加载该数据呢?我只是想停止尝试检索更多数据的休眠 - 我已经有了我想要的数据。现在,无论何时尝试访问get()方法,hibernate都会抛出“无会话或会话已关闭”的错误,这很有意义,因为我的事务已经从我的服务提交。

谢谢!

+0

你能否告诉你更多关于你的问题:你是否想从懒惰加载完全切换到急切加载,或者你是否不想在这种特定情况下延迟加载员工以及为什么。 – gabuzo 2011-01-26 15:03:14

+0

我的问题是我不想懒惰地加载数据。当然,我可以将其标记为EAGER加载 - 但如果我现在不关心这些数据会怎么样?例如,如果我有一个拥有多个职位的员工,但我不想要这些数据,因为它对于我想呈现的视图来说太详细了,那么如何告诉JPA不要尝试并获取该数据? – 2011-01-26 15:34:43

+0

试试这个: http://stackoverflow.com/questions/4802887/gson-how-to-exclude-specific-fields-from-serialization-without-annotations – 2012-08-24 23:44:28

回答

3

你真的有两个选择:

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

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

0

是:

@*ToMany(fetch=FetchType.EAGER) 
0

你总是可以在fetch属性更改为FetchType.EAGER,但也是值得考虑的,如果你有你的交易有合适的范围。如果在事务中访问集合,集合将被正确加载。

6

有几种选择:

  • 如果你总是需要热切加载您的收藏,您可以在地图指定fetch = FetchType.EAGER,在其他的答案建议。

  • 否则,您可以启用渴望获取对特定查询:

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

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

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

您可以使用Doozer来做到这一点。这是非常灵活的,通过一个小配置(阅读,你会松散你的头发配置它),你甚至可以只检索你想发送给Gson的部分数据。

0

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

  1. 更改你的数据模型,不追逐你不想要的数据。
  2. 将你想要的数据复制到某种没有关系的关系的DTO中。
  3. 假设您使用的是Hibernate,请添加Session-in-view过滤器......其类似的东西,它会在您序列化整个数据库时保持会话打开状态。 ;)

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

因人而异

2

正如其他人所指出的,这不符合JPA的问题/休眠而是用JSON序列库所使用。您应该使用gson来排除您不想要遍历的属性。

0

要做的简单而直接的事情就是创建新的Data类(类似于DTO) 使用Hibernate.isInitialized()来检查对象是否被hibernate初始化。 我正在检查gson,如果我可以覆盖任何东西。如果我发现任何新东西,我会在这里发布。