Spring声明 式事务实现过程中,在配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化。
比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。使用myBatis时用的是JDBC事务管理器,因此TransactionManager的实现为DataSourceTransactionManager。
先假设我们在myBatis中自己写事务,是这个样子:
public class StudentService {
public Student createStudent(Student student) {
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory()
.openSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.insertAddress(student.getAddress());
mapper.insertStudent(student);
sqlSession.commit();
return student;
} catch (Exception e) {
sqlSession.rollback();
throw new RuntimeException(e);
} finally {
sqlSession.close();
}
}
}
按这个方式,在每一个需要用到事务的方法中,添加事务的提交、回滚、关闭等。
现在我们来使用spring的事务处理能力。首先在Spring的配置文件中配置TransactionManager。
Spring全局配置beans.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliases" value="com.owen.mybatis.domain.Student" />
<property name="typeHandlers"
value="com.owen.mybatis.typehandlers.PhoneTypeHandler" />
<property name="typeHandlersPackage" value="com.owen.mybatis.typehandlers" />
<property name="mapperLocations" value="classpath*:com/mybatis3/**/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.owen.mybatis.mappers" />
</bean>
<!-- ============事务配置============= -->
<!-- 基于注解的事务处理特性,Spring需要先使用下面的配置 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
现在可以在Spring的服务的Bean中注解@ Transactional。这个注解表明每个方法都是Spring来管理的。如果方法成功处理,那么Spring就会提交事务;如果就去处理过程出现了错误,那么事务就会被回滚。当然,Spring将会关心MyBatis的转换过程是否出现Exceptons的DataAccessExceptions的异常栈。
在DAO上需加上@Transactional注解,如下:
package twm.spring.transactiondemo.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;
import twm.spring.transactiondemo.pojo.User;
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, noRollbackFor = { TException.class }, readOnly = true, timeout = 3)
@Component
public class StudentService {
@Autowired
private StudentMapper studentMapper;
public Student createStudent(Student student) {
studentMapper.insertAddress(student.getAddress());
if(student.getName().equalsIgnoreCase("")) {
throw new RuntimeException("Student name should not be empty.");
}
studentMapper.insertStudent(student);
return student;
}
}
另附参考文章:
根据代理机制的不同,总结了五种Spring事务的配置方式,见
http://www.blogjava.net/robbie/archive/2009/04/05/264003.html