一、什麼是事務 事務就是一系列的業務邏輯的操作,必須要全部執行成功,否則每個操作所執行的內容都要撤銷。 二、事務的四大特性 1.原子性(atomicity):事務雖然有一系列的操作,但要把它看作一個整體(單一原子),要麼都成功,要麼都失敗; 2.一致性(consistency):事務必須是使資料庫從 ...
一、什麼是事務
事務就是一系列的業務邏輯的操作,必須要全部執行成功,否則每個操作所執行的內容都要撤銷。
二、事務的四大特性
1.原子性(atomicity):事務雖然有一系列的操作,但要把它看作一個整體(單一原子),要麼都成功,要麼都失敗;
2.一致性(consistency):事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態;
3.隔離性(isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾;
4.持久性(durability):持久性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。
三、Spring中聲明式的事務管理實現
以上一篇學習中的項目為例
1.我們修改UserMapper介面,添加兩個方法:
package com.jms.mapper; import com.jms.pojo.User; import java.util.List; public interface UserMapper { List<User> selectUsers(); void insertUser(User user); void deleteUser(int id); }
2.修改UserMapper.xml文件
<?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.jms.mapper.UserMapper"> <select id="selectUsers" resultType="user"> select * from mybaties.user </select> <insert id="insertUser" parameterType="com.jms.pojo.User"> insert into mybaties.user values(#{id}, #{username}, #{password}) </insert> <delete id="deleteUser" parameterType="_int"> deletes from mybaties.user where id=#{id} </delete> </mapper>
請註意看,這裡我的delete語句是有錯誤的。
3.修改實現類UserMapperImpl
package com.jms.mapper; import com.jms.pojo.User; import org.mybatis.spring.SqlSessionTemplate; import java.util.List; public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSessionTemplate; public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } @Override public List<User> selectUsers() { User user = new User(101, "jms101", "123456"); UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class); userMapper.insertUser(user); userMapper.deleteUser(10001); return userMapper.selectUsers(); } @Override public void insertUser(User user) { UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class); userMapper.insertUser(user); } @Override public void deleteUser(int id) { UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class); userMapper.deleteUser(id); } }
註意看,select方法中調用了insert和delete方法
4.測試類
@Test public void test01() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapperImpl userMapper = applicationContext.getBean("userMapper", UserMapperImpl.class); userMapper.selectUsers(); }
由於delete語句有錯誤,所以一定會報錯,但是insert語句會執行成功
查看資料庫,insert插入成功
很明顯這不符合事務的原子性,所以我們需要配置事務管理,在出現錯誤時讓已經執行的操作進行回滾。
我們先把插入的這一行刪掉,然後配置spring配置文件spring-mybatis.xml,添加以下內容:
<!--配置聲明式事務管理--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="dataSource" /> </bean> <!--結合AOP實現事務的織入--> <!--配置事務通知--> <tx:advice id="interceptor" transaction-manager="transactionManager"> <!--給哪些方法(這裡是所有方法)配置事務管理--> <!--配置事務的傳播特性--> <tx:attributes> <tx:method name="select*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--配置事務切入--> <aop:config> <!--切入點--> <aop:pointcut id="txPointCut" expression="execution(* com.jms.mapper.*.*(..))"/> <aop:advisor advice-ref="interceptor" pointcut-ref="txPointCut"/> </aop:config>
三個步驟:配置事務管理、配置事務通知、配置事務切入。
註意配置事務通知中,name是事務的方法名,propagation是事務傳播特性。
PROPAGATION_REQUIRED:支持當前事務,如果當前沒有事務,就新建一個事務。這是預設選擇。
PROPAGATION_SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行
PROPAGATION_MANDATORY:支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起
PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED:支持當前事務,新增Savepoint點,與當前事務同步提交或回滾。
接下來進行測試:
依舊報錯,但是表中沒有被插入數據
(本文僅作個人學習記錄用,如有紕漏敬請指正)