spring学习(十三、声明式事务)
十三、声明式事务
1.回顾事务
- 把一组业务当成一个业务来做。要么都成功,要么都失败
- 事务在项目开发中十分重要,涉及到数据一致性的问题
- 确保完整性和一致性
事务的ACID原则
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会影响,被持久化的写到存储器中
2.spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
在代码中测试事务的一致性,selectUser就作为一个事务
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
public List<User> selectUser() {
User user = new User(7, "氪二百", "12345666");
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(user);
mapper.deleteUser(user.getId());
return mapper.selectUser();
}
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
在这里将delete的SQL操作写错,来测试事务的一致性
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzt.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd})
</insert>
<!--故意写错,测试事务的一致性-->
<delete id="deleteUser" parameterType="int">
deletes from mybatis.user where id=#{id}
</delete>
</mapper>
在spring-dao.xml中需要添加的配置
xmlns:tx="http://www.springframework.org/schema/tx"
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性 propagation-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="select" read-only="true"/> <!--只读read-only 不能对数据库进行增删改的操作-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
propagation传播方式:
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 spring的默认选择
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
【下面的不怎么用】
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
配置事务切入AOP【写在spring-dao.xml中】
<!--配置事务切入-->
<aop:config>
<!--mapper包下面的所有类所有方法都要被切入-->
<aop:pointcut id="txPointCut" expression="execution(* com.lzt.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
在测试时,测试类中的事务就具有了一致性,如果delete操作出现错误,则整个selectUser操作都会回滚
注意事项:
- 如果不配置事务可能会存在数据提交不一致的情况
- 如果我们不在Spring中配置声明式事务,则需要在代码中手动配置事务
- 事务在项目中十分重要,涉及到数据的一致性和完整性

浙公网安备 33010602011771号