1. 事务的概念与特性
事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败;用统一的机制来处理不同数据访问技术的事务处理;
特性 | 描述 |
---|---|
原子性-atomicity | 事务中的各个操作不可单独执行,要么整体发生,要么整体不发生 |
一致性-consistency | 事务执行前后的数据完整性必需保持一致 |
隔离性-isolation | 事务执行过程中不应该被其他事务干扰,多个并发事务之间的数据要互相隔离 |
持久性-durability | 一个事务一旦提交,数据库中数据的改变就是永久性的 |
2. 事务管理 API
由 Spring 提供常用的 3 个 API 实现事务的管理
2.1 PlatformTransactionManager-事务管理器
常用事务 | 描述 |
---|---|
org.springframework.jdbc.datasource.DataSourceTransactionManager | Spring JDBC 或 Batis 进行持久化数据使用 |
org.springframework.orm.hibernate3.HibernateTransactionManager | Hiberbate 3.0 版本进行持久化数据使用 |
2.2 TransactionDefinition-事务定义信息
隔离级别 | 描述 |
---|---|
READ_UNCOMMITED | 最低隔离级别,充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读 |
READ_COMMITTED | 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读 |
REPEAtABLE_READ | 防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读) |
SERIALIZABLE | 花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读 |
传播行为 | 描述 |
---|---|
REQUIRED | 支持当前事务,如果不存在则创建 |
SUPPORTS | 支持当前事务,如果不存在就不使用 |
MANDATORY | 支持当前事务,如果不存在便抛出异常 |
REQUIRES_NEW | 如果有事务存在,挂起事务并创建新事物 |
NOT_SUPPORTED | 以非事务方式运行,如果事务存在则挂起当前事务 |
NEVER | 以非事务方式运行,如果事务存在则抛出异常 |
NESTED | 如果当前事务存在,则嵌套事务执行 |
2.3 TransactionStatus-事务状态表现形式
3. 事务管理方式
3.1 编程式事务管理
- 业务类实现.class
public class ServiceImpl{
// 注入事务管理的模板
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate t){
this.transactionTemplate = t;
}
// 某个测试业务方法
public void tansactionTest(){
transactionTemplate.execute(new TransactionCallbackWithoutResult()){
@Override
protected void doInTransactionWithResult(TransactionStatus transactionStatus){
// 此处可以开始执行事务中的相关操作
}
}
}
}
- 编辑配置文件.xml
<beans ...>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置事务管理器,关联连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务管模板,事务包装 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!-- 业务类,模板应用 -->
<bean id="service" class="com...ServiceImpl">
<!-- 注入事务管理的模板 -->
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
</beans>
3.2 声明式事务管理 - 推荐
3.2.1 基于 TransactionProxyFactoryBean 方式
需为每个事务管理的类都配置一个 TransactionProxyFactoryBean 。需要引入两包:
- com.springsource.org.aopalliance.jar
- spring-aop.jar
- 业务类实现.class
public class ServiceImpl{
// 某个测试业务方法
public void tansactionTest(){
// 此处可以开始执行事务中的相关操作
}
}
- 编辑配置文件.xml
<beans ...>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 业务类 -->
<bean id="service" class="com...ServiceImpl"></bean>
<!-- 配置事务管理器,关联连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 业务层代理-->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
<!-- 关联目标对象 -->
<property name="target" ref="service"/>
<!-- 注入事务管理器 -->
<property name="transactionManager" ref="transactionManager"/>
<!-- 注入事务属性,代替目标对象完成注入工作 -->
<property name="transactionAtteributes">
<props>
<!--
prop 格式:
PROPAGATION : 事务的传播行为;
ISOLATION : 事务的隔离级别;
readOnly : 只读;
-Exception : 指定发生异常执行回滚;
+Exception : 指定发生异常依然提交事务,不自信回滚;
-->
<prop key"transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
3.2.2 基于 AspectJ 方式
只需在 xml 配置中实现事务的增强式管理,而对应的类无需任何操作。需要引入两包:
- com.springsource.org.aspectj.weaver.jar
- spring-aspects.jar
- 业务类实现.class
public class ServiceImpl{
// 某个测试业务方法
public void tansactionTest(){
// 此处可以开始执行事务中的相关操作
}
}
- 编辑配置文件.xml
<beans ...>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 业务类 -->
<bean id="service" class="com...ServiceImpl"></bean>
<!-- 配置事务管理器,关联连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务的通知:(事务增强) -->
<tx:advice id="txAdvice" transaction-manager"="transactionManager">
<tx:attributes>
<!--
propagation : 事务的传播行为;
isolation : 事务的隔离级别;
read-only : 只读;
rollback-for : 指定发生异常执行回滚;
no-rollback-for: 指定发生异常依然提交事务,不自信回滚;
timeout : 过期信息;
-->
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!-- 设定切入点 -->
<aop:pointcut expression="execution(* com...ServiceImpl+.*(..))" id="pointcut"/>
<!-- 设定切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
</beans>
3.2.2 基于注解方式
除 xml 配置并开启事务以外,还需要为每个事务管理类添加相应的注解信息。
- 业务类实现.class
/*
propagation : 事务的传播行为;
isolation : 事务的隔离级别;
readOnly : 只读;
rollbackFor : 指定发生异常执行回滚;
noRollbackFor : 指定发生异常依然提交事务,不自信回滚;
注意:方法亦可以加该注解,标识覆盖类声明的注解信息。
*/
@Transactional(propagation=Propagation.REQUIRED)
public class ServiceImpl{
// 某个测试业务方法
public void tansactionTest(){
// 此处可以开始执行事务中的相关操作
}
}
- 编辑配置文件.xml
<beans ...>
<!-- 配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 业务类 -->
<bean id="service" class="com...ServiceImpl"></bean>
<!-- 配置事务管理器,关联连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解事务,配置文件.class 可用 @EnableTransactionManagement 启用事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>