现在我在我的网络应用程序中使用JPA。我有一个这样的课:
class A {
...
@OneToMany
private List<B> list;
...
}
当它在HTTP请求中时,我可以使用a.getList()成功。但是在调度线程中,它会引发异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: A.list, could not initialize proxy - no Session
我可以像http请求线程一样将会话保留在调度线程中吗?
答案 0 :(得分:0)
实际上,当spring处理http请求时,它会通过拦截器org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
或过滤器org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
启动事务。因此,如果我们想要保持会话,我们可以自己开始并提交交易。
以下是代码:
public class BackendThread {
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Override
public void onMessage(Message message, byte[] pattern) {
new TransactionTemplate(platformTransactionManager).execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus transactionStatus) {
...
your code here
...
return null;
}
});
}
}
答案 1 :(得分:0)
如果您使用JTA,TransactionTemplate会很有帮助。我没有使用它并在后台线程中自己创建了一个会话/事务,因此每个任务都有自己的环境:
注入实体管理器或从Spring上下文获取它或将其作为参考传递:
@PersistenceContext
private EntityManager entityManager;
然后创建一个新的实体管理器,以避免使用共享管理器:
EntityManager em = entityManager.getEntityManagerFactory().createEntityManager();
现在您可以启动事务并使用Spring DAO,Repository,JPA等
private void save(EntityManager em) {
try
{
em.getTransaction().begin();
<your database changes>
em.getTransaction().commit();
}
catch(Throwable th) {
em.getTransaction().rollback();
throw th;
}
}