我遇到了LazyInitializationException
然后我遇到了来自官方doc的以下段落。不幸的是,这对我来说毫无意义。请帮忙。
(文档中段落上方的代码块)
@GET
@Timed
@UnitOfWork
public Person findPerson(@PathParam("id") LongParam id) {
return dao.findById(id.get());
}
重要
在资源方法返回之前,Hibernate会话已关闭 值(例如,数据库中的Person),表示您的资源 方法(或DAO)负责初始化所有延迟加载的 收藏品等,在返回之前。否则,你会得到一个 在模板中抛出LazyInitializationException(或null值 杰克逊制作。
首先The Hibernate session is closed before your resource method’s return value
。这怎么可能?如果围绕我的资源返回语句有try-finally
块,这本来是可能的,但这不是这种情况。
我的资源应该由另一个方法调用,我猜测在调用资源方法之前会打开Hibernate会话,然后在我的资源方法返回后关闭会话。如何在我的方法返回之前关闭它。我不明白。
最重要的部分 - which means your resource method (or DAO) is responsible for initializing all lazily-loaded collections, etc., before returning.
我没有Hibernate经验。我现在是第一次使用它。我如何初始化,或者更确切地说是"初始化"在Hibernate的背景下?代码示例将有很多帮助。
PS :这个问题可能看起来很奇怪,粗略看一眼的人甚至可能会建议将其移至"英语语言和用法",但请仔细阅读。这是一个技术问题,而不是段落剖析。
修改 添加了文档中的代码块,否则它对任何人都没有意义。此外,我在发布问题后立即从我的问题中删除了一个段落,这个段落很明显。
答案 0 :(得分:2)
首先在资源方法之前关闭Hibernate会话 回报价值。这怎么可能?这本来是可能的 围绕我的资源返回声明进行了try-finally阻止, 但这不是这种情况。
我对Dropwizard一无所知。所以,让我们看一下来源(我稍微改变一下)。
class UnitOfWorkAwareProxyFactory {
public <T> T create(Class<T> clazz) {
final ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(clazz);
final Proxy proxy = (Proxy) factory.createClass().newInstance();
proxy.setHandler(new MethodHandler() {
@Override
public Object invoke(Object self, Method overridden,
Method proceed, Object[] args) {
final UnitOfWork unitOfWork = overridden.getAnnotation(UnitOfWork.class);
final UnitOfWorkAspect unitOfWorkAspect = new UnitOfWorkAspect(sessionFactories);
try {
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = proceed.invoke(self, args);
unitOfWorkAspect.afterEnd();
return result;
} catch (Exception e) {
unitOfWorkAspect.onError();
throw e;
}
}
});
return (T) proxy;
}
}
如果你有一个班级
class PersonDao {
@UnitOfWork
public Person findPerson(LongParam id) {
return dao.findById(id.get());
}
}
你可以做这样的事情
UnitOfWorkAwareProxyFactory factory = new UnitOfWorkAwareProxyFactory();
PersonDao proxy = factory.create(PersonDao.class);
当你做
时Person person = proxy.findPerson(1L);
该行变为
unitOfWorkAspect.beforeStart(unitOfWork);
Object result = findPerson.invoke(proxy, 1L);
unitOfWorkAspect.afterEnd();
return result;
来自来源UnitOfWorkAspect
的方法unitOfWorkAspect.beforeStart(unitOfWork)
和unitOfWorkAspect.afterEnd()
class UnitOfWorkAspect {
public void beforeStart(UnitOfWork unitOfWork) {
session = sessionFactory.openSession();
configureSession();
beginTransaction();
}
public void afterEnd() {
try {
commitTransaction();
} catch (Exception e) {
rollbackTransaction();
throw e;
} finally {
session.close();
}
}
}
最重要的部分 - 这意味着您的资源方法(或DAO)负责在返回之前初始化所有延迟加载的集合等。我没有Hibernate经验。我现在是第一次使用它。我如何初始化,或者更确切地说是&#34;初始化&#34;在Hibernate的背景下?
在此上下文中初始化意味着应从数据库加载集合数据。一些初始化方法
1.使用急切加载,例如
class User {
@ManyToMany(fetch = FetchType.EAGER)
private List<Role> roles;
}
当你获得roles
实体时,Hibernate将通过连接或子选择加载User
。
Hibernate.initialize(user.getRoles())
join fetch
- from User user left join fetch user.roles
Criteria
与setFetchMode()