我遇到了一个问题,即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”错误,这是有道理的,因为我的事务已经从我的服务中提交了。
谢谢!
答案 0 :(得分:6)
有几种选择:
如果您总是急需加载您的收藏品,可以在地图中指定fetch = FetchType.EAGER
,如其他答案所示。
否则,您可以为特定查询启用急切提取:
在HQL / JPQL查询中使用JOIN FETCH
子句:
SELECT e FROM Employee e JOIN FETCH e.children WHERE ...
Session
访问Hibernate em.unwrap(Session.class)
)答案 1 :(得分:3)
你真的有两个选择:
toJSON
库反映整个对象图。我知道一些JSON库允许您只将对象的某些属性序列化为JSON。如果你的图书馆只使用反射,我个人认为#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相同的问题。诀窍是,取决于你想要破坏多少东西,
选项一是我们为我们所做的第一个大项目所做的,但它破坏了我们用于任何通用目的的数据访问库。从那时起,我们更倾向于选择二。
YMMV
答案 7 :(得分:0)
简单直接的事情是创建新的数据类(类似于DTO) 使用Hibernate.isInitialized()来检查对象是否由hibernate初始化。 我正在检查gson,如果我可以覆盖任何东西。如果我发现任何新内容,我会在此发布。