Spring 3とHibernate 4を統合すると、システムはデータベース操作の実行中に次のメッセージを表示します。
org.hibernate.HibernateException: No Session found for current thread
`sessionFactory`は次のように注入されます:
spring-hibernate4.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>orm/Users.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect </value> </property> </bean> <bean id="userDao" class="com.mkyong.users.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="userService" class="com.mkyong.users.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> </beans>
解決策
`sessionFactory`はトランザクションを処理し、それを解決し、Springのトランザクションマネージャを宣言する必要があります。
spring-hibernate4.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>orm/Users.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect </value> </property> </bean> <bean id="userDao" class="com.mkyong.users.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="userService" class="com.mkyong.users.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> </bean> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find** " read-only="true"/> <tx:method name="** "/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="userServicePointCut" expression="execution(** com.mkyong.users.service.** Service.** (..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut"/> </aop:config> </beans>
-
ソリューション2 ** :プログラムによるトランザクション管理。トランザクションマネージャをコードで宣言する。
package com.mkyong.users.service; //... import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; public class UserServiceImpl implements UserService { private UserDao userDao; private TransactionTemplate transactionTemplate; public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionTemplate = new TransactionTemplate(transactionManager); } @Override public UserDetails findByUsername(final String username) { //Programmatic transaction management return transactionTemplate.execute(new TransactionCallback<UserDetails>() { public UserDetails doInTransaction(TransactionStatus status) { UserDetails user = userDao.findByUserName(username); //etc etc } }); }
-
注** +詳細については、http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/transaction.html[公式Springトランザクション管理]を参照してください。