简体   繁体   English

无法检索预绑定的Hibernate会话 - 无法获取当前线程的事务同步会话

[英]Could not retrieve pre-bound Hibernate session - Could not obtain transaction-synchronized Session for current thread

I am creating a web application with spring-mvc, spring-security, spring-core, and hibernate. 我正在创建一个带有spring-mvc,spring-security,spring-core和hibernate的web应用程序。

But I always get this non-error from hibernate session factory. 但我总是从hibernate会话工厂得到这个非错误。

It is actually throwing HibernateException, but I see on the log it is in debug level, and my application actually continues its execution with no problem. 它实际上是在抛出HibernateException,但我在日志中看到它处于调试级别,我的应用程序实际上继续执行它没有问题。

But I am very curious to understand the reason of the exception raised. 但我很好奇理解提出异常的原因。

The log shows the following lines. 日志显示以下行。

2016-08-29 13:34:55,310 DEBUG [sg.com.diamond.express.base.dao.impl.HibernateDAOImpl].[doExecute]([328]) [http-nio-8888-exec-4] - Could not retrieve pre-bound Hibernate session
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
    at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:325)
    at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308)
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:418)
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:411)
    at sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl.findById(BaseHibernateDaoImpl.java:160)
    at sg.com.diamond.express.webadmin.service.impl.ClientProfileServiceImpl.searchByName(ClientProfileServiceImpl.java:48)
    at sg.com.diamond.express.webadmin.controller.impl.ClientController.home(ClientController.java:48)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:472)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:409)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

This is the code that I have. 这是我的代码。

DAO Level DAO等级

This is an abstraction level that I created to minimise the number of boiler-plate codes for DAO, no need to implement the basic crud. 这是我创建的抽象级别,用于最小化DAO的样板代码数量,无需实现基本的crud。

BaseDAO Interface BaseDAO接口

public interface BaseDAO <ID extends Serializable, M extends BaseModel> {
    Session getCurrentSession();

    M findById(ID id) throws DAOException;
    List<M> findByCriteria(M criteria) throws DAOException;
    List<M> listAll() throws DAOException;
    ID saveObject(M object) throws DAOException;
    void saveOrUpdate(M object) throws DAOException;
    Query createQuery(String hql) throws DAOException;
    Query createSQLQuery(String sql) throws DAOException;
    Criteria createCriteria(Class clazz) throws DAOException;
    List<M> runQuery(Query query) throws DAOException;
    List<M> runQuery(String sql) throws DAOException;
}

BaseDAO Implementation BaseDAO实施

public class BaseHibernateDaoImpl<ID extends Serializable, M extends BaseModel> extends HibernateTemplate implements BaseDAO<ID, M> {

    protected Class<M> modelClass;

    @Override
    public Session getCurrentSession() {
        return this.getSessionFactory().getCurrentSession();
    }

    public ID saveObject(M object) throws DAOException {
        try {
            object.setCreator("Batch");
            object.setCreatedAt(new Timestamp(new Date().getTime()));
            object.setUpdater("Batch");
            object.setUpdatedAt(new Timestamp(new Date().getTime()));
            return (ID) super.save(object);
        } catch (Exception e) {
            logger.error(ExceptionUtil.getStackTraces(e), e);
            throw new DAOException(e);
        }
    }

    /** all other implementation methods **/

Spring XML Configuration Spring XML配置

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Data Source Configuration
        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  -->
    <bean id="targetDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@192.168.170.36:1521:EXPT2" />
        <property name="username" value="EXP_USER" />
        <property name="password" value="passw0rd" />
    </bean>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
        <property name="targetDataSource" ref="targetDataSource"/>
    </bean>

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Hibernate abstract session factory parent
        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  -->
    <bean id="baseSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" abstract="true">
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
            </props>
        </property>
    </bean>

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Hibernate entity configurations
        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  -->
    <bean id="expressSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" parent="baseSessionFactory">
        <property name="hibernateProperties">
            <props merge="true">
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
            </props>
        </property>
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingLocations" value="classpath*:hbm/express/*.hbm.xml"/>
    </bean>

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Transaction Management
        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="expressSessionFactory"/>
    </bean>

    <aop:config>
        <aop:pointcut id="servicePointcut" expression="execution(* sg.com.diamond.express.webadmin.service.*.*.*(..))"/>
        <aop:advisor id="serviceTx" advice-ref="txAdvice" pointcut-ref="servicePointcut"/>
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="get*"      propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" />
            <tx:method name="search*"   propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" />
            <tx:method name="list*"     propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" />
            <tx:method name="is*"       propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" />
            <tx:method name="*"         propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="false"/>
        </tx:attributes>
    </tx:advice>

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Base Dao Definitions
        |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  -->
    <bean id="baseExpressDAO" class="sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl" abstract="true">
        <property name="sessionFactory" ref="expressSessionFactory"/>
    </bean>

Question

Why does the error happen? 为什么会发生错误? and it doesn't break my app, the log level is DEBUG, not ERROR, my app is able to continue properly after that. 并且它不会破坏我的应用程序,日志级别是DEBUG,而不是ERROR,我的应用程序能够在此之后正常继续。

Is my configuration correct? 我的配置是否正确?

Note 注意

Don't mind the full-xml config, for some reason, I need to use full-xml and none-annotations. 不要介意full-xml配置,出于某种原因,我需要使用full-xml和none-annotations。

Answer 回答

After mucking around with the aop pointcut expression, I noticed that on a simple batch program that I wrote, where I only have 1 context, I do not have this problem. 在使用aop切入点表达式后,我注意到在我编写的一个简单的批处理程序中,我只有1个上下文,我没有这个问题。

This leads me to the answer. 这引出了我的答案。

I originally structured my spring xml config as multiple layers. 我最初将我的spring xml配置为多层。

  • At the top level, at the application context, I declare all the data sources, and the transaction managements. 在顶层,在应用程序上下文中,我声明了所有数据源和事务管理。
  • At the second level, the servlet level, each servlet has its own context. 在第二级,servlet级别,每个servlet都有自己的上下文。 At this level, I put all the controller-service-dao configurations. 在这个级别,我把所有的controller-service-dao配置。
  • There should be multiple of this "second-level" context, for example, 1 servlet context should handle all RESTful services, where another one handles web-ui. 应该存在多个这种“第二级”上下文,例如,1个servlet上下文应该处理所有RESTful服务,其中另一个处理web-ui。

I've structured it assuming it will take on the transaction management setup in the application context. 假设它将在应用程序上下文中进行事务管理设置,我构建它。 Sort of like "all servlet context should be able to use the same data-source and transaction-management the same way" 类似“所有servlet上下文应该能够以相同的方式使用相同的数据源和事务管理”

But as it turns out, it doesn't. 但事实证明,事实证明并非如此。

When I moved the transaction management piece, including the data-source config, into the servlet context configuration, it all works fine, and the service is now wrapped correctly under transaction. 当我将事务管理部分(包括数据源配置)移动到servlet上下文配置中时,一切正常,现在服务在事务下正确包装。

Thanks. 谢谢。

The error happens because your aop transaction configuration is not correct. 发生错误是因为您的aop事务配置不正确。 It does not cover the service class from the stack trace. 它不会覆盖堆栈跟踪中的服务类。 Tweak with the mapping until you stop getting the stack trace. 调整映射,直到您停止获取堆栈跟踪。 Or maybe better use annotated transaction configuration if possible. 或者,如果可能,最好使用带注释的事务配置。 The answer to your second question is in the sources of hibernate template: 你的第二个问题的答案是在hibernate模板的来源:

try {
325         session =     getSessionFactory().getCurrentSession();
326         }
327         catch (HibernateException ex) {
328             logger.debug("Could not retrieve pre-bound Hibernate session", ex);
329         }
330         if (session == null) {
331             session = getSessionFactory().openSession();
332             session.setFlushMode(FlushMode.MANUAL);
333             isNew = true;
334         }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 休眠5-无法获取当前线程的事务同步会话; - hibernate 5 - Could not obtain transaction-synchronized Session for current thread; 休眠-无法获取当前线程的事务同步会话 - Hibernate - Could not obtain transaction-synchronized Session for current thread Hibernate无法获取当前线程的事务同步会话 - Hibernate Could not obtain transaction-synchronized Session for current thread Hibernate SessionFactory,无法获取当前线程的事务同步会话 - Hibernate SessionFactory and could not obtain transaction-synchronized session for current thread Spring和Hibernate-无法获得当前线程的事务同步会话 - Spring and Hibernate - Could not obtain transaction-synchronized Session for current thread HibernateException:无法获取当前线程的事务同步会话 - HibernateException: Could not obtain transaction-synchronized Session for current thread 无法获取当前线程的事务同步会话 - Could not obtain transaction-synchronized Session for current thread 迁移到Hibernate 4 + Spring 4.2.2:org.hibernate.HibernateException:无法获取当前线程的事务同步Session - migration to hibernate 4 + spring 4.2.2: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread Spring 4+ Hibernate 4:无法获取当前线程的事务同步会话 - Spring 4+ Hibernate 4: Could not obtain transaction-synchronized Session for current thread Spring,Hibernate,WebApplication:无法获取当前线程的事务同步会话 - Spring, Hibernate, WebApplication: Could not obtain transaction-synchronized Session for current thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM