如何在线程

时间:2016-04-25 01:22:06

标签: spring jpa

现在我在我的网络应用程序中使用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请求线程一样将会话保留在调度线程中吗?

2 个答案:

答案 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;
    }        
}