您好,登錄后才能下訂單哦!
本篇內容主要講解“spring框架入門之什么是事務控制”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“spring框架入門之什么是事務控制”吧!
事務是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那么事務就會回滾到最開始的狀態,仿佛什么都沒發生過一樣。
PlatformTransactionManager
接口提供事務操作的方法,包含三個具體的操作
public interface PlatformTransactionManager extends TransactionManager { // 獲取事務狀態信息 TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException; // 提交事務 void commit(TransactionStatus var1) throws TransactionException; // 回滾事務 void rollback(TransactionStatus var1) throws TransactionException; }
開發中常用的實現類:
org.springframework.jdbc.datasource.DataSourceTransactionManager
:使用Spring JDBC或iBatis進行持久化數據時使用
spring中事務控制接口的結構
1.1.2 TransactionDefinition
事務的定義信息對象,包含如下方法:
獲取事務對象名稱:String getName()
獲取事務隔離級別:int getIsolationLevel()
獲取事務傳播行為:int getPropagationBehavior()
獲取事務超時時間:int getTimeout()
獲取事務是否只讀:boolean isReadOnly()
1.1.3 TransactionStatus
描述了某個時間點上事務對象的狀態信息,包含6個具體的操作:
刷新事務:void flush()
獲取是否存在儲存點:boolean hasSavepoint()
獲取事務是否完成:boolean isCompleted()
獲取事務是否為新的事物:boolean isNewTransaction()
獲取事務是否回滾:boolean isRollbackOnly()
設置事務回滾:void set RollbackOnly()
事務的隔離界別反映事務提交并發訪問時的處理態度
1.2.1 事務隔離的級別
① ISOLATION_DEFAULT
默認級別,由 DBA 默認的設置來決定隔離級別,歸屬下列某一種
② ISOLATION_READ_UNCOMMITTED
就是一個事務可以讀取另一個未提交事務的數據。會出現臟讀、不可重復讀、幻讀(隔離級別最低,但并發性高)
③ ISOLATION_READ_COMMITTED
就是一個事務要等另一個事務提交后才能讀取數據,解決臟讀問題。會出現不可重復讀、幻讀問題(鎖定正在讀取的行,適用于大多數系統,Oracle默認級別)
④ ISOLATION_REPEATABLE_READ
就是在開始讀取數據(事務開啟)時,不再允許修改操作,解決不可重復讀問題。會出現幻讀問題(鎖定所讀的所有行,MYSQL默認級別)
⑤ ISOLATION_SERALZABLE
是最高的事務隔離級別,在該級別下,事務串行化順序執行,可以避免臟讀、不可重復讀與幻讀。但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用。(鎖整表)
事務隔離級別由上到下依次提升,隔離級別越高,越能保證數據的完整性和一致性。但對數據庫性能的消耗依次增加,并發執行效率依次下降。
大多數的數據庫默認隔離級別為 Read Commited,比如 SqlServer、Oracle
少數數據庫默認隔離級別為:Repeatable Read 比如:MySQL InnoDB
1.2.2 數據庫讀取時會出現的三種問題
① Dirty reads
:讀臟數據。
也就是說,比如事務A的未提交(還依然緩存)的數據被事務B讀走,如果事務A失敗回滾,會導致事務B所讀取的的數據是錯誤的。
② non-repeatable reads
:數據不可重復讀。
比如事務A中兩處讀取數據price的值。在第一讀的時候,price是100,然后事務B就把price的值改成 200;事務A再讀一次,結果就發現,price竟然就變成200了,造成事務A數據混亂。
③ phantom reads
:幻象讀數據。
這個和non-repeatable reads相似,也是同一個事務中多次讀不一致的問題。但是 non-repeatable reads
的不一致是因為他所要取的數據值被改變了(比如price)而 phantom reads
所要讀的數據的不一致卻是他的條件數據集發生變化了。
比如:執行 Select account.id where account.name="Bruce*"
,第一次讀去了6個符合條件的id;第二次讀取的時候,由于事務B把一個帳號的名字由"dd"改成"Bruce1",結果取出來了7個數據。
不可重復讀的重點是修改:同樣的條件,兩次讀發現值不一樣;
幻讀的重點在于新增或者刪除:同樣的條件,兩次讀發現得到的記錄數不一樣
1.2.3 數據隔離級別和出現的問題之間的關聯
Dirty reads | non-repeatable reads | phantom reads | |
---|---|---|---|
READ_UNCOMMITTED | Y | Y | Y |
READ_COMMITTED | N | Y | Y |
REPEATABLE_READ | N | N | Y |
SERALZABLE | N | N | N |
REQUIRED
:如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。一般的選 擇(默認值)
SUPPORTS
:支持當前事務,如果當前沒有事務,就以非事務方式執行(沒有事務)
MANDATORY
:使用當前的事務,如果當前沒有事務,就拋出異常。
REQUERS_NEW
:新建事務,如果當前在事務中,把當前事務掛起。
NOT_SUPPORTED
:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
NEVER
:以非事務方式運行,如果當前存在事務,拋出異常。
NESTED
:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行REQUIRED類似的操作。
指事務提交后最長可以等待的時間,超出時間則會自動失敗。默認值是-1,沒有時間限制。如果有,則以秒為單位進行設置。
讀寫型事務:增加、刪除、修改時開啟事務
只讀型事務:執行查詢時,也會開啟事務
配置事務管理器
配置事務的通知
此時我們需要導入事務的約束 tx名稱空間和約束,同時也需要aop的使用 <tx:advice>
標簽配置事務通知
id
:給事務通知起一個唯一標識
transaction-manager
:給事務通知提供一個事務管理器引用
配置AOP中的通用切入點表達式
建立事務通知和切入點表達式的對應關系
配置事務的屬性是在事務的通知 <tx:advice>
標簽的內部
isolation
:用于指定事務的隔離級別。默認值是 DEFAULT
,表示使用數據庫的默認隔離級別。
propagation
:用于指定事務的傳播行為。默認值是 REQUIRED
,表示一定會有事務,增刪改的選擇。查詢方法可以選擇 SUPPORTS
。
read-only
:用于指定事務是否只讀。只有查詢方法才能設置為 true
。默認值是false
,表示讀寫。
timeout
:用于指定事務的超時時間,默認值是-1,表示永不超時。如果指定了數值,以秒為單位。
rollback-for
:用于指定一個異常,當產生該異常時,事務回滾,產生其他異常時,事務不回滾。沒有默認值。表示任何異常都回滾。
no-rollback-for
:用于指定一個異常,當產生該異常時,事務不回滾,產生其他異常時事務回滾。沒有默認值。表示任何異常都回滾。
代碼示例:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置數據源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/base_crud"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </bean> <!-- 1.配置事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 2.配置事務通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" read-only="false"></tx:method> <tx:method name="get*" propagation="SUPPORTS" read-only="true"></tx:method> </tx:attributes> </tx:advice> <!-- 3.配置AOP --> <aop:config> <aop:pointcut id="pointcut" expression="execution(* cn.bruce.service.impl.*.*(..))"/> <!-- 4.建立事務通知和切入點表達式的對應關系 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config> <!-- 配置dao --> <bean id="accountDao" class="cn.bruce.dao.impl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置service --> <bean id="accountService" class="cn.bruce.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> </beans>
① 書寫配置類
② 將對象注入到IoC容器中管理
③ 給業務添加事務注釋,并指明事務屬性
代碼示例:
① 配置spring
@Configuration// 聲明為配置類 @ComponentScan("cn.bruce")// 聲明需要掃描的包 @Import({JdbcConfig.class, TransactionConfig.class})// 導入其他配置類 @PropertySource("jdbcConfig.properties")// 導入配置文件 @EnableAspectJAutoProxy(proxyTargetClass = true)// 開啟注解支持 @EnableTransactionManagement// 開啟事務控制 public class SpringConfiguration { }
② 配置jdbc
public class JdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /** * 創建數據源對象 * @return */ @Bean("dataSource") public DataSource creatDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } /** * 創建JdbcTemplate * @param dataSource * @return */ @Bean(name = "jdbcTemplate") public JdbcTemplate creatJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }
③ 配置事務控制器
public class TransactionConfig { /** * 用于創建事務管理器對象 * @param dataSource * @return */ @Bean(name = "transactionManager") public PlatformTransactionManager creatTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
④ 通過 [@Repository](https://my.oschina.net/u/3055569)
和 [@service](https://my.oschina.net/service)
注解將Dao和Service層對象注入IoC容器
⑤ 在業務層使用 [@Transactional](https://my.oschina.net/u/3770144)
注解進行事務配置
// 進行讀寫型事務配置 @Transactional(propagation = Propagation.REQUIRED, readOnly = false) @Override public void transfer(String sourceName, String targetName, Float money) { System.out.println("開始進行轉賬操作。。。"); Account source = accountDao.getAccountByName(sourceName); Account target = accountDao.getAccountByName(targetName); source.setMoney(source.getMoney() - money); target.setMoney(target.getMoney() + money); accountDao.updateAccount(source); int i = 1/0; accountDao.updateAccount(target); System.out.println("轉賬完成。。。"); }
⑥ 書寫測試類進行測試
[@Transactional](https://my.oschina.net/u/3770144)
此注解相當于xml配置中的 <tx:attributes>****</tx:attributes>
用于進行事務的配置,其屬性含義和xml中是一致的
此注解可是使用在接口、類和方法上:
出現在接口上,表示此接口所有的實現類都有事務支持
出現在類上,表示類所有的方法都有事務支持
出現在方法上,表示此方法有事務支持
以上三個位置的優先級:方法 > 類 > 接口
到此,相信大家對“spring框架入門之什么是事務控制”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。