当前位置: 首页 > 知识库问答 >
问题:

某些事务传播不能与Spring/Hibernate 4一起工作

陈瀚
2023-03-14
org.hibernate.HibernateException: No Session found for current thread

在SpringSessionContext中。这不是 在错误上下文中定义的问题,也不是缺少CGLIB库的情况。大多数测试都有效,这意味着在大多数情况下,事务代理是有效的。

它现在失败的情况似乎是在使用NOT_SUPPORTED、NEVER和SUPPORTED传播类型时出现的。无论出于何种原因,SpringSessionContext在这些情况下都不会创建会话。

我们的用例有时要求事务边界与方法边界不严格一致,而且会话有时比事务寿命长。在Spring3/Hibernate3中,会话上下文绑定到本地线程,调用SessionFactory.getCurrentSession()将返回会话实例,即使事务没有启动。这是我希望在Hibernate4情况下仍然具有的行为。

有人知道解决办法吗?如果Spring拒绝创建没有有效事务的会话,那么很难将会话边界与会话而不是事务对齐。一个会话及其持久性上下文不应该与一个开放事务绑定在一起。

共有1个答案

姬弘文
2023-03-14

通过实现CurrentSessionContext,它是围绕SpringSessionContext的包装器,并将一些代码更改借用到Spring Framwork4+中,从而解决了这个问题:

public class ClassLoaderSpringSessionContext implements CurrentSessionContext {

    private final SessionFactoryImplementor sessionFactory;
    private final SpringSessionContext sessionContext;

    public ClassLoaderSpringSessionContext(final SessionFactoryImplementor sessionFactory) {
        this.sessionFactory = sessionFactory;  // This is actually some class loading logic that isn't important to this transaction problem.
        this.sessionContext = new SpringSessionContext(this.sessionFactory);
    }

    @Override
    public Session currentSession() throws HibernateException {
        try {
            return sessionContext.currentSession();
        } catch (HibernateException e) {
            if (TransactionSynchronizationManager.isSynchronizationActive()) {
                Session session = this.sessionFactory.openSession();
                if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                    session.setFlushMode(FlushMode.MANUAL);
                }
                SessionHolder sessionHolder = new SessionHolder(session);
                TransactionSynchronizationManager
                        .registerSynchronization(new SpringSessionSynchronization(sessionHolder,
                            this.sessionFactory));
                TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
                sessionHolder.setSynchronizedWithTransaction(true);
                return session;
            } else {
                throw new HibernateException(
                        "Could not obtain transaction-synchronized Session for current thread");
            }
        }
    }
}

SpringSessionSynchronization是Spring4中的包私有类,因此我还必须将该类的一个版本作为私有内部类拉到ClassLoaderSpringSessionContext

希望这能帮助其他人。

 类似资料:
  • 所称的刀是: 我希望服务类中的方法在事务中运行,并在方法出现异常时回滚所有内容。但这不是在事务中运行的。 如果我将添加到DAO方法中,那么它看起来就像是在单独的事务中运行的。这是正确的吗?

  • 我试图理解Spring事务概念。如下所示,我必须将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有当两个插入都成功时才应该提交事务,否则应该回滚。 如果我根据需要使用传播或REQUIRES\u NEW,我会得到错误“非法尝试使用现有的两阶段资源提交一阶段资源”。 但是如果我使用NOT_SUPPORTED或支持,它工作正常(即如果其中一个插

  • Spring对RDBMS事务管理的支持在Spring WebFlux中也起作用吗? 例如,假设配置正确,用注释注释的方法是否会使用Spring事务管理器并在发生错误时回滚事务? 如果事务管理确实起作用,那么方法是否确实和异常,或者或返回类型是否发出错误信号? 我知道JDBC本质上是阻塞的,因此任何JDBC操作都必须从阻塞桥接到反应桥接,反之亦然。 我的组织有WebFlux和Cassandra的经验

  • pom.xml版本信息: SpringFox-Swagger2:2.5.0 昂首阔步-核心:1.5.10 springfox-swagger-ui:2.6.1 Springboot:1.5.3 我有一个项目与swagger2和Springboot。 没有@Aspect的项目代码工作得很好。 正确的结果: 但是当我添加以下代码时,swagger-ui没有显示test-api-impl。 swagge

  • 我试图将zookeeper和kafka设置为共享名称空间中单独的Kubernetes部署/吊舱。我已经在我的Ubuntu沙盒上通过kubeadm用Calico引导了一个本地K8s 1.8... 所以我假设我的集群中有一个普通的网络问题,然后我注意到一些更让我困惑的事情...如果我将zookeeper.connect设置为10.107.41.148:2181(zookeeper服务的当前地址),连接

  • 我使用的是Spring批处理版本2.2.4.Release,我试图用有状态的ItemReader、ItemProcessor和ItemWriter bean编写一个简单的示例。 在我的集成测试中,我在一个内部静态java配置类中声明bean,如下所示: 这个测试通过了。 但是,一旦我将StatefulItemReader定义为step范围的bean(这对于有状态的读取器更好),“Before st