微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 为后台线程创建JPA会话

我们通过JPA和Spring使用Hibernate来管理Web应用程序中的对象持久性.我们使用open-session-in-view模式为响应http请求的线程创建会话.我们还使用了一些不产生视图的线程 – 它们只是不时醒来完成工作.这会产生问题,因为认情况下它们没有打开会话,所以它们会产生异常

org.hibernate.SessionException: Session is closed! 

要么

 Could not initialize proxy - no Session

我们发现,如果每个后台线程在使用@Transactional注释的方法调用其逻辑,则没有这种类型的异常,因为@Transactional确保线程在事务内部时具有会话.

解决了一段时间的问题,但我不认为这是一个很好的解决方案 – 使长时间运行的方法事务导致问题,因为在提交事务之前,其他线程无法看到数据库中所做的更改.

我创建了一个java-pseudocode示例来更好地说明我的问题:

public class FirstThread {

    ...

    @Transactional
    public void processQueue() {
        for(element : queue){
            if(elementCanBeProcessed(element)){
                elementDao.saveIntoDatabase(element);
                secondThread.addToQueue(element.getId());
            }
        }
    }

    private boolean elementCanBeProcessed(element){
        //code that gets a few objects from database and processes them
    }
}

如果我用@Transactional注释整个processQueue方法所做的更改

elementDao.saveIntoDatabase(element);

在事务提交之前不会在secondThread中看到(因此直到整个队列被处理).如果我不这样做,那么线程将不会在elementCanBeProcessed中有会话,并且它将无法访问数据库.我也无法注释elementCanBeProcessed,因为它是这个类中的私有方法,我必须将它移动到另一个类,以便Spring代理可以工作.

是否可以将会话绑定到线程而不使整个方法具有事务性?我应该如何管理像那样的后台线程中的会话和事务?

最佳答案
我不知道任何针对此的Spring-ready解决方案.所以,我认为你需要实现一个类似于OpenEntityManagerInViewInterceptor类.

基本上,当你的线程启动时,你需要使用TransactionSynchronizationManager来绑定资源()一个EntityManagerHolder的实例,当线程完成时你需要使用unbindResource().

OpenEntityManagerInViewInterceptor的核心部分是:

    if (TransactionSynchronizationManager.hasResource(getEntityManagerFactory())) {
        ...
    }
    else {
        logger.debug("opening JPA EntityManager in OpenEntityManagerInViewInterceptor");
        try {
            EntityManager em = createEntityManager();
            EntityManagerHolder emHolder = new EntityManagerHolder(em);
            TransactionSynchronizationManager.bindResource(getEntityManagerFactory(),emHolder);

            ...
        }
        catch (PersistenceException ex) {
            throw new DataAccessResourceFailureException("Could not create JPA EntityManager",ex);
        }
    }

如果您实施了,请在此处发布代码作为答案.

原文地址:https://www.jb51.cc/spring/431746.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐