建议将 Hibernate SessionFactory 交给 Spring 进行事务管理,在 applicationContext.xml 里面配置
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> <!-- hibernate的相关属性配置 --> <property name="hibernateProperties"> <props>
...
</bean> <!-- 定义事务管理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> <!-- 自动扫描实体对象 com.waylau.entity 的包结构中存放实体类 --> <property name="packagesToScan" value="com.waylau.entity" /> </bean>
使用 SessionFactory
@Autowired private SessionFactory sessionFactory;
public Session getSession() {
return sessionFactory.getCurrentSession();
}
延伸
声明事务
方法1
在调用的类或者方法上加 @Transactional
注解
/**
* @author waylau.com 2015年1月3日
*/ @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
@Transactional public class TestSdUserDaoImpl {
@Autowired private SdUserDaoImpl sdUserDaoImpl;
@Test public void countAllTest() {
System.out.println(sdUserDaoImpl.countAll());
}
@Test public void findByIdTest() {
SdUser e = sdUserDaoImpl.findById(1);
System.out.println(e.getRealname());
}
}
方法2
用 Spring AOP
<!-- 扫描有注解的文件 base-package 包路径 --> <context:component-scan base-package="com" /> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 事务执行方式 REQUIRED:指定当前方法必需在事务环境中运行, 如果当前有事务环境就加入当前正在执行的事务环境, 如果当前没有事务,就新建一个事务。
这是默认值。 --> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="import*" propagation="REQUIRED" /> <!-- 指定当前方法以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,等我以非事务的状态运行完,再继续原来的事务。 查询定义即可
read-only="true" 表示只读 --> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" /> </tx:attributes> </tx:advice> <!-- 定义切面,在 com.emsc.service.impl.*.*(..) 中执行有关的hibernate session的事务操作 --> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com.emsc.service..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" /> </aop:config>
这样就定义了那些类或者那些方法需要执行事务
问题
假如如此配置还有事务上的问题,如下:
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)
...
如果用 aop 有出现问题,请将<aop:config>
改为 <aop:config proxy-target-class="true">
时间: 2025-01-29 21:54:51