詳解Spring學(xué)習(xí)之編程式事務(wù)管理
前言
在前面的內(nèi)容,基本已經(jīng)學(xué)習(xí)了事務(wù)的基本概念以及事務(wù)隔離級(jí)別等,接下來(lái)的幾個(gè)小節(jié),將學(xué)習(xí)怎么使用Spring進(jìn)行事務(wù)管理,在Spring中,對(duì)事務(wù)進(jìn)行管理有多種方法,主要分別編程式和聲明式,本小節(jié)主要學(xué)習(xí)編程式事務(wù)管理,后面講學(xué)習(xí)Spring的聲明式事務(wù)管理
編程式事務(wù)管理
所謂的編程式事務(wù)管理,其實(shí)就是通過(guò)編寫(xiě)代碼的方式來(lái)進(jìn)行事務(wù)管理,也就是通過(guò)將事務(wù)管理的代碼硬編碼在代碼中從而達(dá)到事務(wù)管理的作用,不過(guò)Spring的事務(wù)管理不同于JDBC原始的事務(wù)管理,在JDBC中,對(duì)事務(wù)進(jìn)行管理首先要關(guān)閉自動(dòng)提交,然后采用手動(dòng)配置的方式來(lái)控制提交以及異常時(shí)回滾,而在Spring中,主要是使用Spring的接口來(lái)管理,具體如下代碼所示
這里模擬銀行轉(zhuǎn)賬的業(yè)務(wù),正如我們所知道的,轉(zhuǎn)賬其實(shí)就是從一個(gè)賬號(hào)減去金額并且給另外一個(gè)賬號(hào)增加對(duì)應(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">
<!--開(kāi)啟自動(dòng)掃描-->
<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ù)管理操作類(lèi)-->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<!--注入事務(wù)管理-->
<property name="transactionManager" ref="transactionManager"/>
<!--定義事務(wù)隔離級(jí)別,這里-1代表默認(rèn)-->
<property name="isolationLevel" value="-1"/>
<!--配置傳播行為,0代表PROPAGATION_REQUIRED-->
<property name="propagationBehavior" value="0"/>
<!--由于進(jìn)行讀寫(xiě)操作,所以這里的只讀設(shè)置為false,默認(rèn)也是false,所以可以不用設(shè)置-->
<property name="readOnly" value="false"/>
</bean>
</beans>
在配置事務(wù)隔離級(jí)別的時(shí)候,由于這里是采用整數(shù)的形式,而不是字符串,一開(kāi)始在配置的時(shí)候有點(diǎn)摸不著頭腦,后來(lái)查看了對(duì)應(yīng)的源代碼之后,發(fā)現(xiàn)了對(duì)應(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ù)隔離級(jí)別 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);
}
}
對(duì)業(yè)務(wù)層代碼進(jìn)行檢查測(cè)試,可以看到,結(jié)果是沒(méi)有問(wèn)題的,也就是轉(zhuǎn)賬是成功的
如果此時(shí)在業(yè)務(wù)代碼執(zhí)行過(guò)程中發(fā)生錯(cuò)誤或者異常,那么結(jié)果會(huì)是如何呢
比如說(shuō),通過(guò)修改transfer代碼,手動(dòng)模擬異常,如下所示
accountDao.transferOut(fromName, money); int d = 1/0; // 除0異常 accountDao.transferIn(toName, money);
此時(shí)運(yùn)行測(cè)試代碼,可以發(fā)現(xiàn),數(shù)據(jù)出現(xiàn)了不一致,金額已經(jīng)轉(zhuǎn)出了,但是由于在轉(zhuǎn)入之前發(fā)生了異常,所以無(wú)法轉(zhuǎn)入,導(dǎo)致了有一部分金額莫名其妙丟失了,這也就是為什么需要進(jìn)行事務(wù)管理了。
對(duì)業(yè)務(wù)層代碼添加事務(wù)管理,如下所示
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
// 配置事務(wù)管理操作類(lèi)
@Autowired
private TransactionTemplate transactionTemplate;
public void transfer(final String fromName,final String toName,final double money){
// 通過(guò)transactionTemplate進(jìn)行事務(wù)的管理
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.transferOut(fromName, money);
int d = 1/0; // 除0異常
accountDao.transferIn(toName, money);
}
});
}
}
此時(shí)再運(yùn)行代碼,可以發(fā)現(xiàn),不管是有沒(méi)有異常,數(shù)據(jù)的一致性都得到了保證,這也就是說(shuō),事務(wù)管理起了作用
上面的內(nèi)容就是使用Spring進(jìn)行事務(wù)管理的一種方式,不過(guò)這種方式是不太方便的,因?yàn)槌艘渲檬聞?wù)管理操作類(lèi),也就是TransactionTemplate之外,當(dāng)需要進(jìn)行事務(wù)管理的時(shí)候,還需要在對(duì)應(yīng)的代碼中為其編寫(xiě)相應(yīng)的管理代碼,如上所示,所以這種方式在日常的開(kāi)發(fā)中比較少使用。
總結(jié)
本小節(jié)我們主要學(xué)習(xí)了如何在Spring配置事務(wù)管理器,并且通過(guò)編碼的方式,使用Spring的編程式事務(wù)管理對(duì)業(yè)務(wù)操作進(jìn)行事務(wù)管理,不過(guò)這種方式使用起來(lái)不是很方便,所以使用的頻率非常少,接下來(lái)的小節(jié)我們將學(xué)習(xí)Spring的聲明式事務(wù)管理。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間
這篇文章主要介紹了Springboot之如何統(tǒng)計(jì)代碼執(zhí)行耗時(shí)時(shí)間問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Nacos+Spring Cloud Gateway動(dòng)態(tài)路由配置實(shí)現(xiàn)步驟
Nacos最近項(xiàng)目一直在使用,本文通過(guò)gateway、nacos-consumer、nacos-provider三個(gè)簡(jiǎn)單模塊來(lái)展示:Nacos下動(dòng)態(tài)路由配置,,感興趣的小伙伴們可以參考一下2021-08-08
Java JDK動(dòng)態(tài)代理在攔截器和聲明式接口中的應(yīng)用小結(jié)
Java動(dòng)態(tài)代理技術(shù)通過(guò)反射機(jī)制在運(yùn)行時(shí)動(dòng)態(tài)生成代理類(lèi),實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象方法的攔截和增強(qiáng),本文給大家介紹Java JDK動(dòng)態(tài)代理在攔截器和聲明式接口中的應(yīng)用小結(jié),感興趣的朋友跟隨小編一起看看吧2025-01-01
深入解析Java中的編碼轉(zhuǎn)換以及編碼和解碼操作
這篇文章主要介紹了Java中的編碼轉(zhuǎn)換以及編碼和解碼操作,文中詳細(xì)解讀了編碼解碼的相關(guān)IO操作以及內(nèi)存使用方面的知識(shí),需要的朋友可以參考下2016-02-02
如何通過(guò)ServletInputStream讀取http請(qǐng)求傳入的數(shù)據(jù)
這篇文章主要介紹了如何通過(guò)ServletInputStream讀取http請(qǐng)求傳入的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
maven如何動(dòng)態(tài)統(tǒng)一修改版本號(hào)的方法步驟
這篇文章主要介紹了maven如何動(dòng)態(tài)統(tǒng)一修改版本號(hào)的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Springboot使用POI實(shí)現(xiàn)導(dǎo)出Excel文件示例
本篇文章主要介紹了Springboot使用POI實(shí)現(xiàn)導(dǎo)出Excel文件示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-02-02

