这里有无数的问题,如何解决"无法初始化代理"通过急切提取问题,保持交易开放,打开另一个,OpenEntityManagerInViewFilter
等等。
但是,是否可以简单地告诉Hibernate忽略该问题并假装该集合为空?在我的情况下,不提取它只是意味着我不在乎。
这实际上是以下Y的XY问题:
我有像
这样的课程class Detail {
@ManyToOne(optional=false) Master master;
...
}
class Master {
@OneToMany(mappedBy="master") List<Detail> details;
...
}
并希望提供两种请求:一种请求返回单个master
及其所有details
,另一种请求返回master
s列表而不包含details
。结果将由Gson转换为JSON。
我已尝试session.clear
和session.evict(master)
,但他们没有触及代替details
使用的代理。有用的是
master.setDetails(nullOrSomeCollection)
感觉相当hacky。我更喜欢&#34;无知&#34;因为它通常适用,而不知道代理的部分是什么。
写一个Gson TypeAdapter
忽略AbstractPersistentCollection
与initialized=false
的实例可能是一种方式,但这取决于org.hibernate.collection.internal
,这肯定不是好事。在TypeAdapter
中捕获异常听起来不太好。
我的目标不是&#34;加载数据而不是例外&#34; ,但&#34;如何获取< strong> null 而不是异常&#34; 我
Dragan raises忘记获取并返回错误数据的有效点将比异常更糟糕。但是有一个简单的方法:
null
null
而不是空集合作为未获取数据的指示这样,结果永远不会被错误地解释。如果我忘记取件,响应将包含无效的null
。
答案 0 :(得分:5)
您可以使用Hibernate.isInitialized,它是Hibernate公共API的一部分。
所以,在TypeAdapter
中,您可以添加以下内容:
if ((value instanceof Collection) && !Hibernate.isInitialized(value)) {
result = new ArrayList();
}
然而,在我的谦虚意见中,你的方法通常不是可行的方法。
“在我的情况下,不提取它只是意味着我不在乎。”
或者它意味着您忘记获取它,现在您返回错误数据(比获取异常更糟糕;服务的使用者认为该集合为空,但事实并非如此)。
我不想提出“更好”的解决方案(这不是问题的主题,每种方法都有自己的优势),但是我在大多数用例中解决这些问题的方式(并且它是其中之一)通常采用的方法)使用DTO:只需定义代表服务响应的DTO,将其填入事务上下文(没有LazyInitializationException
)并将其提供给将其转换为服务响应的框架(json,xml等)。
答案 1 :(得分:2)
您可以尝试的解决方案如下。
创建名为LazyLoader
@FunctionalInterface // Java 8
public interface LazyLoader<T> {
void load(T t);
}
并在您的服务中
public class Service {
List<Master> getWithDetails(LazyLoader<Master> loader) {
// Code to get masterList from session
for(Master master:masterList) {
loader.load(master);
}
}
}
并调用此服务,如下所示
Service.getWithDetails(new LazyLoader<Master>() {
public void load(Master master) {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
}
});
在Java 8中,您可以使用Lambda,因为它是单一抽象方法(SAM)。
Service.getWithDetails((master) -> {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
});
您可以将上述解决方案与session.clear
和session.evict(master)
答案 2 :(得分:1)
解决方案是使用查询而不是关联(一对多或多对多)。甚至Hibernate的一位原作者也说Collections are a feature而不是最终目标。
在您的情况下,您可以更灵活地删除集合映射,并在数据访问层中需要时简单地获取关联的关系。