javascript
Spring总结之事务
Spring事務(wù)
1)定義
????事務(wù)是指多個(gè)操作單元組成的集合,多個(gè)操作單元是整體不可分割的,要么都成功,要么都不成功。必須遵守四個(gè)原則(ACID)
? ? ? ●原子性(Atomicity):即事務(wù)是不可分割的最小工作單元,事務(wù)內(nèi)的操作要么全做,要么全不做;
???? ?●一致性(Consistency):在事務(wù)執(zhí)行前數(shù)據(jù)庫(kù)的數(shù)據(jù)處于正確的狀態(tài),而事務(wù)執(zhí)行完成后數(shù)據(jù)庫(kù)的數(shù)據(jù)還是應(yīng)該處于正確的狀態(tài),即數(shù)據(jù)完整性約束沒(méi)有被破壞;如銀行轉(zhuǎn)帳,A轉(zhuǎn)帳給B,必須保證A的錢(qián)一定轉(zhuǎn)給B,一定不會(huì)出現(xiàn)A的錢(qián)轉(zhuǎn)了但B沒(méi)收到,否則數(shù)據(jù)庫(kù)的數(shù)據(jù)就處于不一致(不正確)的狀態(tài)。
? ? ? ●隔離性(Isolation):并發(fā)事務(wù)執(zhí)行之間互不影響,在一個(gè)事務(wù)內(nèi)部的操作對(duì)其他事務(wù)是不產(chǎn)生影響,這需要事務(wù)隔離級(jí)別來(lái)指定隔離性;
? ? ? ●持久性(Durability):事務(wù)一旦執(zhí)行成功,它對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)的改變必須是永久的,不會(huì)因比如遇到系統(tǒng)故障或斷電造成數(shù)據(jù)不一致或丟失。
2)Spring事務(wù)隔離級(jí)別
????spring有五大隔離級(jí)別,其在TransactionDefinition接口中定義。看源碼可知,其默isolation_default(底層數(shù)據(jù)庫(kù)默認(rèn)級(jí)別),其他四個(gè)隔離級(jí)別跟數(shù)據(jù)庫(kù)隔離級(jí)別一致。
????●ISOLATION_DEFAULT:用底層數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別,數(shù)據(jù)庫(kù)管理員設(shè)置什么就是什么
???? ●ISOLATION_READ_UNCOMMITTED(未提交讀):最低隔離級(jí)別、事務(wù)未提交前,就可被其他事務(wù)讀取(會(huì)出現(xiàn)幻讀、臟讀、不可重復(fù)讀)
???? ●ISOLATION_READ_COMMITTED(提交讀):一個(gè)事務(wù)提交后才能被其他事務(wù)讀取到(該隔離級(jí)別禁止其他事務(wù)讀取到未提交事務(wù)的數(shù)據(jù)、所以還是會(huì)造成幻讀、不可重復(fù)讀)、sql server默認(rèn)級(jí)別
???? ●ISOLATION_REPEATABLE_READ(可重復(fù)讀):可重復(fù)讀,保證多次讀取同一個(gè)數(shù)據(jù)時(shí),其值都和事務(wù)開(kāi)始時(shí)候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(該隔離基本可防止臟讀,不可重復(fù)讀(重點(diǎn)在修改),但會(huì)出現(xiàn)幻讀(重點(diǎn)在增加與刪除))(MySql默認(rèn)級(jí)別,更改可通過(guò)set transaction isolation level 級(jí)別)
???? ●ISOLATION_SERIALIZABLE(序列化):代價(jià)最高最可靠的隔離級(jí)別(該隔離級(jí)別能防止臟讀、不可重復(fù)讀、幻讀)
?
丟失更新:兩個(gè)事務(wù)同時(shí)更新一行數(shù)據(jù),最后一個(gè)事務(wù)的更新會(huì)覆蓋掉第一個(gè)事務(wù)的更新,從而導(dǎo)致第一個(gè)事務(wù)更新的數(shù)據(jù)丟失,這是由于沒(méi)有加鎖造成的;
幻讀:同樣的事務(wù)操作過(guò)程中,不同時(shí)間段多次(不同事務(wù))讀取同一數(shù)據(jù),讀取到的內(nèi)容不一致(一般是行數(shù)變多或變少)。
臟讀:一個(gè)事務(wù)讀取到另外一個(gè)未提及事務(wù)的內(nèi)容,即為臟讀。
不可重復(fù)讀:同一事務(wù)中,多次讀取內(nèi)容不一致(一般行數(shù)不變,而內(nèi)容變了)。
幻讀與不可重復(fù)讀的區(qū)別:幻讀的重點(diǎn)在于插入與刪除,即第二次查詢會(huì)發(fā)現(xiàn)比第一次查詢數(shù)據(jù)變少或者變多了,以至于給人一種幻象一樣,而不可重復(fù)讀重點(diǎn)在于修改,即第二次查詢會(huì)發(fā)現(xiàn)查詢結(jié)果比第一次查詢結(jié)果不一致,即第一次結(jié)果已經(jīng)不可重現(xiàn)了。
?
數(shù)據(jù)庫(kù)隔離級(jí)別越高,執(zhí)行代價(jià)越高,并發(fā)執(zhí)行能力越差,因此在實(shí)際項(xiàng)目開(kāi)發(fā)使用時(shí)要綜合考慮,為了考慮并發(fā)性能一般使用提交讀隔離級(jí)別,它能避免丟失更新和臟讀,盡管不可重復(fù)讀和幻讀不能避免,但可以在可能出現(xiàn)的場(chǎng)合使用悲觀鎖或樂(lè)觀鎖來(lái)解決這些問(wèn)題。
?
3)Spring事務(wù)管理
????(1)編程式事務(wù)管理 ??????
????????Spring 提供的事務(wù)模版類:org.springframework.transaction.support.TransactionTemplate
????????事務(wù)管理器: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"/><!-- 數(shù)據(jù)源 --><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 事務(wù)管理器--><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()在同一個(gè)事務(wù)中 @Overridepublic void addUser() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {userDao.addUser();userDao.updateUser();}});} }(2)聲明式事務(wù)管理
????????使用 XML 配置聲明式事務(wù);
<?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"/><!-- 數(shù)據(jù)源 --><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 事務(wù)管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事務(wù)通知 --><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>使用注解配置聲明式事務(wù)( @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"/><!-- 數(shù)據(jù)源 --><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 事務(wù)管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 注解聲明式事務(wù),織入事務(wù)管理器 --><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)事務(wù)的傳播行為
????事務(wù)傳播行為:Spring 中,當(dāng)一個(gè) service 方法調(diào)用另外一個(gè) service 方法的時(shí)候,因?yàn)槊總€(gè) service 方法都有事
務(wù),這時(shí)候就出現(xiàn)了事務(wù)的嵌套;由此,就產(chǎn)生了事務(wù)傳播行為;
????在 Spring 中,通過(guò)配置 Propagation,來(lái)定義事務(wù)傳播行為;
????????PROPAGATION_REQUIRED--支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)。這是最常見(jiàn)的選擇。
????????PROPAGATION_SUPPORTS--支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。
????????PROPAGATION_MANDATORY--支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就拋出異常。
????????PROPAGATION_REQUIRES_NEW--新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
????????PROPAGATION_NOT_SUPPORTED--以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
????????PROPAGATION_NEVER--以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
轉(zhuǎn)載于:https://www.cnblogs.com/jnba/p/10832722.html
總結(jié)
以上是生活随笔為你收集整理的Spring总结之事务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《Linux就该这么学》培训笔记_ch0
- 下一篇: learnByWork