您好,登錄后才能下訂單哦!
前言
在前面的內(nèi)容,基本已經(jīng)學(xué)習(xí)了事務(wù)的基本概念以及事務(wù)隔離級別等,接下來的幾個小節(jié),將學(xué)習(xí)怎么使用Spring進行事務(wù)管理,在Spring中,對事務(wù)進行管理有多種方法,主要分別編程式和聲明式,本小節(jié)主要學(xué)習(xí)編程式事務(wù)管理,后面講學(xué)習(xí)Spring的聲明式事務(wù)管理
編程式事務(wù)管理
所謂的編程式事務(wù)管理,其實就是通過編寫代碼的方式來進行事務(wù)管理,也就是通過將事務(wù)管理的代碼硬編碼在代碼中從而達到事務(wù)管理的作用,不過Spring的事務(wù)管理不同于JDBC原始的事務(wù)管理,在JDBC中,對事務(wù)進行管理首先要關(guān)閉自動提交,然后采用手動配置的方式來控制提交以及異常時回滾,而在Spring中,主要是使用Spring的接口來管理,具體如下代碼所示
這里模擬銀行轉(zhuǎn)賬的業(yè)務(wù),正如我們所知道的,轉(zhuǎn)賬其實就是從一個賬號減去金額并且給另外一個賬號增加對應(yīng)的金額
Spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--開啟自動掃描--> <context:component-scan base-package="cn.xuhuanfeng.transaction"/> <!--配置數(shù)據(jù)源,這里采用dbcp--> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="jdbc:mysql://localhost:3306/spring"/> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="username" value="root"/> <property name="password" value="huanfeng"/> </bean> <!--配置JdbcTemplate--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!--注入數(shù)據(jù)源--> <property name="dataSource" ref="dataSource"/> </bean> <!--配置事務(wù)管理--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入數(shù)據(jù)源--> <property name="dataSource" ref="dataSource"/> </bean> <!--配置事務(wù)管理操作類--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <!--注入事務(wù)管理--> <property name="transactionManager" ref="transactionManager"/> <!--定義事務(wù)隔離級別,這里-1代表默認--> <property name="isolationLevel" value="-1"/> <!--配置傳播行為,0代表PROPAGATION_REQUIRED--> <property name="propagationBehavior" value="0"/> <!--由于進行讀寫操作,所以這里的只讀設(shè)置為false,默認也是false,所以可以不用設(shè)置--> <property name="readOnly" value="false"/> </bean> </beans>
在配置事務(wù)隔離級別的時候,由于這里是采用整數(shù)的形式,而不是字符串,一開始在配置的時候有點摸不著頭腦,后來查看了對應(yīng)的源代碼之后,發(fā)現(xiàn)了對應(yīng)的常量,將其記錄如下
// 事務(wù)傳播行為 int PROPAGATION_REQUIRED = 0; int PROPAGATION_SUPPORTS = 1; int PROPAGATION_MANDATORY = 2; int PROPAGATION_REQUIRES_NEW = 3; int PROPAGATION_NOT_SUPPORTED = 4; int PROPAGATION_NEVER = 5; int PROPAGATION_NESTED = 6; // 事務(wù)隔離級別 int ISOLATION_DEFAULT = -1; int ISOLATION_READ_UNCOMMITTED = 1; int ISOLATION_READ_COMMITTED = 2; int ISOLATION_REPEATABLE_READ = 4; int ISOLATION_SERIALIZABLE = 8; int TIMEOUT_DEFAULT = -1;
持久層代碼如下所示
@Repository public class AccountDao { @Autowired private JdbcTemplate jdbcTemplate; public void transferIn(String name, double money){ String sql = "update account set money = money + ? where name = ?"; jdbcTemplate.update(sql, money, name); } public void transferOut(String name, double money){ String sql = "update account set money = money - ? where name = ?"; jdbcTemplate.update(sql, money, name); } }
業(yè)務(wù)層代碼如下所示
@Service public class AccountService { @Autowired private AccountDao accountDao; // 轉(zhuǎn)賬 public void transfer(String fromName, String toName, double money){ accountDao.transferOut(fromName, money); accountDao.transferIn(toName, money); } }
對業(yè)務(wù)層代碼進行檢查測試,可以看到,結(jié)果是沒有問題的,也就是轉(zhuǎn)賬是成功的
如果此時在業(yè)務(wù)代碼執(zhí)行過程中發(fā)生錯誤或者異常,那么結(jié)果會是如何呢
比如說,通過修改transfer代碼,手動模擬異常,如下所示
accountDao.transferOut(fromName, money); int d = 1/0; // 除0異常 accountDao.transferIn(toName, money);
此時運行測試代碼,可以發(fā)現(xiàn),數(shù)據(jù)出現(xiàn)了不一致,金額已經(jīng)轉(zhuǎn)出了,但是由于在轉(zhuǎn)入之前發(fā)生了異常,所以無法轉(zhuǎn)入,導(dǎo)致了有一部分金額莫名其妙丟失了,這也就是為什么需要進行事務(wù)管理了。
對業(yè)務(wù)層代碼添加事務(wù)管理,如下所示
@Service public class AccountService { @Autowired private AccountDao accountDao; // 配置事務(wù)管理操作類 @Autowired private TransactionTemplate transactionTemplate; public void transfer(final String fromName,final String toName,final double money){ // 通過transactionTemplate進行事務(wù)的管理 transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { accountDao.transferOut(fromName, money); int d = 1/0; // 除0異常 accountDao.transferIn(toName, money); } }); } }
此時再運行代碼,可以發(fā)現(xiàn),不管是有沒有異常,數(shù)據(jù)的一致性都得到了保證,這也就是說,事務(wù)管理起了作用
上面的內(nèi)容就是使用Spring進行事務(wù)管理的一種方式,不過這種方式是不太方便的,因為除了要配置事務(wù)管理操作類,也就是TransactionTemplate之外,當(dāng)需要進行事務(wù)管理的時候,還需要在對應(yīng)的代碼中為其編寫相應(yīng)的管理代碼,如上所示,所以這種方式在日常的開發(fā)中比較少使用。
總結(jié)
本小節(jié)我們主要學(xué)習(xí)了如何在Spring配置事務(wù)管理器,并且通過編碼的方式,使用Spring的編程式事務(wù)管理對業(yè)務(wù)操作進行事務(wù)管理,不過這種方式使用起來不是很方便,所以使用的頻率非常少,接下來的小節(jié)我們將學(xué)習(xí)Spring的聲明式事務(wù)管理。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。