总结
我有一个方法,使用Session对象构建criteriaBuilder,然后获取一个名为Document(文档)的对象。该对象有两个“一对多”列表。我想初始化它们。 即使会话打开,它也拒绝初始化两个列表,并在行中给出“会话无法初始化代理 - 无会话”:Hibernate.initialize(singleResult.getRevisoes());
建议的解决方案
将
@Transactional(Transactional.TxType.REQUIRED)
添加到方法签名中可以解决该问题。但是,这会打开一个新连接吗?我浪费资源了吗?有没有更好的方法来解决这个问题?
@Autowired
protected Session session;
....
@Override
public Document find(Long id, boolean close) {
try {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Document> queryDocument = criteriaBuilder.createQuery(Document.class);
Root<Document> rootDocument = queryDocument.from(Document.class);
queryDocument.select(rootDocument);
queryDocument.where(criteriaBuilder.equal(rootDocument.get("id"), id));
TypedQuery<Document> query = session.createQuery(queryDocument);
Document singleResult = query.getSingleResult();
System.out.println(session.isOpen()); //Returns true
//Initialize other lists (one to many)
Hibernate.initialize(singleResult.getRevisions());
Hibernate.initialize(singleResult.getFiles());
//
return singleResult;
} catch (Exception ex) {
throw ex;
} finally {
if (session != null && close) {
session.close();
}
}
}
参考文献
https://codete.com/blog/spring-transaction-propagation-modes
不知道为什么你会在这里得到“没有会话”,因为我没有太多使用这种类型的标准构建。但使用 @Transactional 不应该有任何性能问题。将 @Transactional 想象为指示它在方法开始时创建数据库会话,并在方法结束时提交并关闭它。您甚至可以删除
REQUIRED
类型,因为它是默认类型。
我认为最好的选择是使用查询的连接获取类型来一次加载所有内容(如果适合您)。