Java 无法检索预先绑定的Hibernate会话-无法获取当前线程的事务同步会话
我正在用SpringMVC、SpringSecurity、SpringCore和hibernate创建一个web应用程序 但我总是从hibernate会话工厂得到这个非错误 它实际上抛出了HibernateException,但我在日志中看到它处于调试级别,我的应用程序实际上继续执行,没有问题 但我很想了解提出这一例外的原因 日志显示以下行Java 无法检索预先绑定的Hibernate会话-无法获取当前线程的事务同步会话,java,spring,hibernate,Java,Spring,Hibernate,我正在用SpringMVC、SpringSecurity、SpringCore和hibernate创建一个web应用程序 但我总是从hibernate会话工厂得到这个非错误 它实际上抛出了HibernateException,但我在日志中看到它处于调试级别,我的应用程序实际上继续执行,没有问题 但我很想了解提出这一例外的原因 日志显示以下行 2016-08-29 13:34:55,310 DEBUG [sg.com.diamond.express.base.dao.impl.HibernateD
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)
这是我的密码
DAO级别
这是一个抽象级别,我创建它是为了尽量减少DAO的锅炉板代码的数量,不需要实现基本的c-r-u-d
BaseDAO接口
公共接口BaseDAO{
会话getCurrentSession();
M findById(ID)抛出异常;
列出findByCriteria(M标准)异常;
List listAll()引发异常;
ID saveObject(M object)抛出异常;
void saveOrUpdate(M对象)抛出异常;
querycreatequery(stringhql)抛出异常;
querycreatesqlquery(stringsql)抛出异常;
criteriacreatecriteria(类clazz)抛出异常;
List runQuery(查询查询)抛出异常;
列表运行查询(字符串sql)抛出异常;
}
BaseDAO实现
公共类BaseHibernateDaoImpl扩展了HibernateTemplate实现BaseDAO{
保护类模型类;
@凌驾
公共会话getCurrentSession(){
返回这个.getSessionFactory().getCurrentSession();
}
公共ID保存对象(M对象)引发异常{
试一试{
对象。setCreator(“批处理”);
setCreatedAt(新时间戳(new Date().getTime());
对象。setUpdater(“批处理”);
setUpdatedAt(新时间戳(new Date().getTime());
返回(ID)超级保存(对象);
}捕获(例外e){
记录器错误(例外直到getStackTraces(e),e);
抛出新的异常(e);
}
}
/**所有其他实施方法**/
SpringXML配置
<!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 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>
真的
真的
10
org.hibernate.dialen.oracle10galent
问题
<!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 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>
为什么会发生错误?而且它不会破坏我的应用程序,日志级别是调试,而不是错误,我的应用程序可以在这之后正常继续
我的配置正确吗
注意
不要介意完整的xml配置,出于某种原因,我需要使用完整的xml和无注释
回答
在研究了aop切入点表达式之后,我注意到在我编写的一个简单批处理程序中,我只有1个上下文,没有这个问题
这让我找到了答案
我最初将SpringXML配置结构化为多个层
- 在顶层,在应用程序上下文中,我声明了所有数据源和事务管理
- 在第二层,servlet层,每个servlet都有自己的上下文
- 这个“第二级”上下文应该有多个,例如,一个servlet上下文应该处理所有RESTful服务,而另一个上下文处理web ui
谢谢。发生此错误是因为您的aop事务配置不正确。它不包括堆栈跟踪中的服务类。请调整映射,直到停止获取堆栈跟踪。或者,如果可能,最好使用带注释的事务配置。 第二个问题的答案在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 }
基于“sg.com.diamond.webadmin.service.impl.ClientProfileService”的类名和searchByName(字符串名)的方法名,您建议我使用什么样的切入点表达式?您已经为我指出了正确的答案。我将更新问题以反映我找到的答案,并将此答案标记为正确。
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 }