javascript
Spring总结之事务
Spring事務
1)定義
????事務是指多個操作單元組成的集合,多個操作單元是整體不可分割的,要么都成功,要么都不成功。必須遵守四個原則(ACID)
? ? ? ●原子性(Atomicity):即事務是不可分割的最小工作單元,事務內的操作要么全做,要么全不做;
???? ?●一致性(Consistency):在事務執行前數據庫的數據處于正確的狀態,而事務執行完成后數據庫的數據還是應該處于正確的狀態,即數據完整性約束沒有被破壞;如銀行轉帳,A轉帳給B,必須保證A的錢一定轉給B,一定不會出現A的錢轉了但B沒收到,否則數據庫的數據就處于不一致(不正確)的狀態。
? ? ? ●隔離性(Isolation):并發事務執行之間互不影響,在一個事務內部的操作對其他事務是不產生影響,這需要事務隔離級別來指定隔離性;
? ? ? ●持久性(Durability):事務一旦執行成功,它對數據庫的數據的改變必須是永久的,不會因比如遇到系統故障或斷電造成數據不一致或丟失。
2)Spring事務隔離級別
????spring有五大隔離級別,其在TransactionDefinition接口中定義。看源碼可知,其默isolation_default(底層數據庫默認級別),其他四個隔離級別跟數據庫隔離級別一致。
????●ISOLATION_DEFAULT:用底層數據庫的默認隔離級別,數據庫管理員設置什么就是什么
???? ●ISOLATION_READ_UNCOMMITTED(未提交讀):最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、臟讀、不可重復讀)
???? ●ISOLATION_READ_COMMITTED(提交讀):一個事務提交后才能被其他事務讀取到(該隔離級別禁止其他事務讀取到未提交事務的數據、所以還是會造成幻讀、不可重復讀)、sql server默認級別
???? ●ISOLATION_REPEATABLE_READ(可重復讀):可重復讀,保證多次讀取同一個數據時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的數據(該隔離基本可防止臟讀,不可重復讀(重點在修改),但會出現幻讀(重點在增加與刪除))(MySql默認級別,更改可通過set transaction isolation level 級別)
???? ●ISOLATION_SERIALIZABLE(序列化):代價最高最可靠的隔離級別(該隔離級別能防止臟讀、不可重復讀、幻讀)
?
丟失更新:兩個事務同時更新一行數據,最后一個事務的更新會覆蓋掉第一個事務的更新,從而導致第一個事務更新的數據丟失,這是由于沒有加鎖造成的;
幻讀:同樣的事務操作過程中,不同時間段多次(不同事務)讀取同一數據,讀取到的內容不一致(一般是行數變多或變少)。
臟讀:一個事務讀取到另外一個未提及事務的內容,即為臟讀。
不可重復讀:同一事務中,多次讀取內容不一致(一般行數不變,而內容變了)。
幻讀與不可重復讀的區別:幻讀的重點在于插入與刪除,即第二次查詢會發現比第一次查詢數據變少或者變多了,以至于給人一種幻象一樣,而不可重復讀重點在于修改,即第二次查詢會發現查詢結果比第一次查詢結果不一致,即第一次結果已經不可重現了。
?
數據庫隔離級別越高,執行代價越高,并發執行能力越差,因此在實際項目開發使用時要綜合考慮,為了考慮并發性能一般使用提交讀隔離級別,它能避免丟失更新和臟讀,盡管不可重復讀和幻讀不能避免,但可以在可能出現的場合使用悲觀鎖或樂觀鎖來解決這些問題。
?
3)Spring事務管理
????(1)編程式事務管理 ??????
????????Spring 提供的事務模版類:org.springframework.transaction.support.TransactionTemplate
????????事務管理器:org.springframework.jdbc.datasource.DataSourceTransactionManager
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><context:property-placeholder location="jdbc.properties"/><!-- 數據源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- jdbc 事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- TransactionTemplate --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"></property></bean><!-- dao --><bean id="userDao" class="top.ruandb.dao.impl.UserDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="userService" class="top.ruandb.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property><property name="transactionTemplate" ref="transactionTemplate"></property></bean></beans> public class UserServiceImpl implements UserServiceI {private TransactionTemplate transactionTemplate;private UserDaoI userDao;public void setTransactionTemplate(TransactionTemplate transactionTemplate) {this.transactionTemplate = transactionTemplate;}public void setUserDao(UserDaoI userDao) {this.userDao = userDao;}//addUser()和updateUser()在同一個事務中 @Overridepublic void addUser() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {userDao.addUser();userDao.updateUser();}});} }(2)聲明式事務管理
????????使用 XML 配置聲明式事務;
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><context:property-placeholder location="jdbc.properties"/><!-- 數據源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- jdbc 事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事務通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="edit*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="new*" propagation="REQUIRED" /> <tx:method name="set*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="change*" propagation="REQUIRED" /> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" read-only="true" /> </tx:attributes> </tx:advice><aop:config><aop:pointcut expression="execution(* top.ruandb.service.*.*(..))" id="serviceMethod"/><aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/></aop:config><!-- dao --><bean id="userDao" class="top.ruandb.dao.impl.UserDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="userService" class="top.ruandb.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean></beans>使用注解配置聲明式事務( @Transactional);<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><context:property-placeholder location="jdbc.properties"/><!-- 數據源 --><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- jdbc 事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 注解聲明式事務,織入事務管理器 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- dao --><bean id="userDao" class="top.ruandb.dao.impl.UserDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="userService" class="top.ruandb.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean></beans> @Transactional public class UserServiceImpl implements UserServiceI {private UserDaoI userDao;public void setUserDao(UserDaoI userDao) {this.userDao = userDao;}@Overridepublic void addUser() {userDao.addUser();userDao.updateUser();} }4)事務的傳播行為
????事務傳播行為:Spring 中,當一個 service 方法調用另外一個 service 方法的時候,因為每個 service 方法都有事
務,這時候就出現了事務的嵌套;由此,就產生了事務傳播行為;
????在 Spring 中,通過配置 Propagation,來定義事務傳播行為;
????????PROPAGATION_REQUIRED--支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
????????PROPAGATION_SUPPORTS--支持當前事務,如果當前沒有事務,就以非事務方式執行。
????????PROPAGATION_MANDATORY--支持當前事務,如果當前沒有事務,就拋出異常。
????????PROPAGATION_REQUIRES_NEW--新建事務,如果當前存在事務,把當前事務掛起。
????????PROPAGATION_NOT_SUPPORTED--以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
????????PROPAGATION_NEVER--以非事務方式執行,如果當前存在事務,則拋出異常。
轉載于:https://www.cnblogs.com/jnba/p/10832722.html
總結
以上是生活随笔為你收集整理的Spring总结之事务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Linux就该这么学》培训笔记_ch0
- 下一篇: learnByWork