Spring声明式事务
事务的概念
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
事务应该具有ACID原则:
-
原子性:事务中的操作要么都发生,要么都不发生
-
一致性:事务前后的数据完整性要保持一致
-
隔离性:多个用户并发访问数据库,数据库为每一个用户开启一个事务,不能被其他事务的操作干扰,多个并发事务之间要互相隔离
-
持久性:事务一旦提交则不可逆,被持久化到数据库中。
简单来说:把一组业务当作一个业务,要么都成功,要么都失败。
下面通过例子来了解事务:我们把查找用户、增加用户、删除用户当作一个业务来做,然后故意在删除用户的sql制造错误,看看增加用户能否成功。
public List<User> selectUser() {
addUser(new User(5,"大张三","221133","221133@11",new Date(145235286565L)));
deleteUser(8);
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
@Override
public int addUser(User user) {
getSqlSession().getMapper(UserMapper.class).addUser(user);
return 0;
}
@Override
public int deleteUser(int id) {
getSqlSession().getMapper(UserMapper.class).deleteUser(id);
return 0;
}
我们在selectUser()方法中调用addUser() 和 deleteUser() 把他们当成一组事务。
<delete id="deleteUser" parameterType="_int">
deletes from users where id = #{id}
</delete>
故意把delete语句写错
结果是增加用户成功了,删除用户没有成功,按照事务的原则,增加用户也不应该成功,原因是在这个项目中没有开启事务。下面我们通过spring来开启事务。
spring事务管理
在spring中有两种事务
-
声明式事务:通过AOP横切,不影响原有代码
-
编程式事务:通过对原有代码进行改变,不推荐使用
-
在配置文件中配置声明式事务
通过注册bean的方式,class是spring提供的DataSourceTransactionManage,需要注入的属性就是上面注册的dataSource
<!-- 配置声明式事务--> <bean id="transactionManage" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
-
结合AOP实现事务的织入
首先需要先配置事务的通知,利用的是 tx:advice标签(事务专用标签),这个标签需要上面新注册的事务管理器transactionManage
在 tx:advice标签 里面需要用到 tx:attribute标签来汇总 tx:method标签
tx:method 就代表给哪些方法配置事务,可以用*代替,还可以配置事务的传播特性propagation
<!-- 结合AOP实现事务的织入--> <!-- 配置事务通知--> <tx:advice transaction-manager="transactionManage"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
需要注意的是:使用tx标签需要引入tx的依赖
-
配置事务的切入
<!-- 配置事务切入--> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.wang.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
-
再次测试
测试结果是没有将用户添加到数据库,删除用户也没有成功,这就达到了我们预期的结果