zoukankan      html  css  js  c++  java
  • Hibernate4中使用getCurrentSession报Could not obtain transaction-synchronized Session for current thread

    架个spring4+hibernate4的demo,dao层直接注入的sessionFactory,然后用getCurrentSession方法获取session,然后问题来了,直接报错:

    Could not obtain transaction-synchronized Session for current thread

    提示无法获取当前线程的事务同步session,略微奇怪,这和事务有什么关系..然后百度一下有人说改成用openSession方法就好了,那我又百度了一下这2个方法的区别:

    (1)openSession每次打开都是新的Session,所以多次获取的Session实例是不同的,并且需要人为的调用close方法进行Session关闭。
    (2)getCurrentSession是从当前上下文中获取Session并且会绑定到当前线程,第一次调用时会创建一个Session实例,如果该Session未关闭,后续多次获取的是同一个Session实例;事务提交或者回滚时会自动关闭Sesison,无需人工关闭。

    看起来这个getCurrentSession方法的确和事务有点关系.然后我加上事务:

        <bean id="transactionManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory">
                <ref bean="sessionFactory" />
            </property>
        </bean>
    
        <tx:annotation-driven transaction-manager="transactionManager"/>

    然后在dao层加上@Transaction注解,再运行ok了..不过好奇驱使吧,看了一下getCurrentSession的源码(我的demo中用的spring的实现类),关键点:

    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, true));
                TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder);
                sessionHolder.setSynchronizedWithTransaction(true);
                return session;
     }
     else {
                throw new HibernateException("Could not obtain transaction-synchronized Session for current thread");
     }

    然后点进去看了一下isSynchronizationActive()方法:

    public static boolean isSynchronizationActive() {
            return (synchronizations.get() != null);
        }

    get方法说明:

    Returns the value in the current thread's copy of this thread-local variable. If the variable has no value for the current thread, it is first initialized to the value returned by an invocation of the initialValue method.

    然后再看initialValue的说明:

    This implementation simply returns null; if the programmer desires thread-local variables to have an initial value other than null, ThreadLocal must be subclassed, and this method overridden. Typically, an anonymous inner class will be used.

    到此问题明了了,补充一点之前配置文件中配了事务,不过是原来那种在配置中根据方法名字来定义事务传播的方式,但是在dao中并没有继承它,故实际上是没有事务的,只有实现.而在spring的事务实现中需要判断当前线程中的事务是否同步,而没有事务的时候,那个判断是否同步的方法会因为get返回初始的null值而返回false,最终导致throw一个Could not obtain transaction-synchronized Session for current thread的异常.

    综上:spring4+hibernate4,使用hibernate的api的时候需要配置事务的,如果不配置事务会导致获取当前session抛出异常.

  • 相关阅读:
    springboot热启动中那些不为人知的东东
    maven生命周期(lifecycle)—— maven权威指南学习笔记(四)
    maven 一个简单项目 —— maven权威指南学习笔记(三)
    maven 安装、运行、获取帮助 —— maven权威指南学习笔记(二)
    maven 简介 —— maven权威指南学习笔记(一)
    用opencsv文件读写CSV文件
    java基础之——DecimalFormat格式化数字
    Git学习
    Spring Boot教程(二十四)Web应用的统一异常处理
    Spring Boot教程(二十三)使用Swagger2构建强大的RESTful API文档(2)
  • 原文地址:https://www.cnblogs.com/chyu/p/4817291.html
Copyright © 2011-2022 走看看