Spring事務(wù)管理零基礎(chǔ)入門
一、簡(jiǎn)介
概念:事務(wù)是數(shù)據(jù)庫(kù)操作的最小工作單元,是作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,這些操作一起提交,要么都執(zhí)行,要么都不執(zhí)行。事務(wù)時(shí)一組不可分割的操作集合(工作邏輯單元)。
簡(jiǎn)而言之,就是一系列操作要么都執(zhí)行成功(事務(wù)提交),要么都執(zhí)行失?。ㄊ聞?wù)回滾)
二、特性(一原持久隔離)
2.1 原子性
事務(wù)中所有操作是不可再分割的原子單位。事務(wù)中所有操作要么都執(zhí)行成功,要么都執(zhí)行失敗
2.2 一致性(類似能量守恒)
事務(wù)執(zhí)行后,數(shù)據(jù)庫(kù)狀態(tài)與其他業(yè)務(wù)規(guī)則保持一致,保證數(shù)據(jù)的一致性
2.3 隔離性
在并發(fā)操作中,不同事務(wù)之間應(yīng)該隔離開(kāi),使每個(gè)并發(fā)的事務(wù)不會(huì)相互干擾
2.4 持久性
一旦事務(wù)提交成功,事務(wù)中所有的數(shù)據(jù)操作都必須持久化到數(shù)據(jù)庫(kù)中,即使提交事務(wù)后,數(shù)據(jù)庫(kù)立馬崩潰,在數(shù)據(jù)庫(kù)重啟時(shí),也必須能通過(guò)某種機(jī)制恢復(fù)數(shù)據(jù)
三、隔離級(jí)別
3.1 事務(wù)級(jí)別(從低到高)
Read uncommitted:
讀未提交,一個(gè)事務(wù)可以讀取另一個(gè)未提交事務(wù)的數(shù)據(jù)。會(huì)產(chǎn)生臟讀。
Read committed:
讀提交,一個(gè)事務(wù)要等另一個(gè)事務(wù)提交后才能讀取數(shù)據(jù),會(huì)產(chǎn)生不可重復(fù)讀。
Repeatable read:
重復(fù)讀,開(kāi)始讀取數(shù)據(jù)(事務(wù)開(kāi)啟)時(shí),不再允許修改操作,可能出現(xiàn)幻讀。
Seriazable:
最高的事務(wù)隔離級(jí)別,該級(jí)別下事務(wù)串行化順序執(zhí)行,可避免臟讀、不可重復(fù)讀、幻讀,但是該事務(wù)級(jí)別效率低下,比較耗數(shù)據(jù)庫(kù)性能,一般不使用。
3.2 常用數(shù)據(jù)庫(kù)默認(rèn)級(jí)別:
Sql Server、Oracle 默認(rèn)事務(wù)隔離級(jí)別: Read committed
Mysql 默認(rèn)隔離級(jí)別是:Repeatable read
3.3 事務(wù)中可能出現(xiàn)的問(wèn)題:
臟讀(讀取了未提交的新事物,然后回滾了)
A 事務(wù)讀取了 B 事務(wù)中未提交的數(shù)據(jù), 如果事務(wù) B 回滾,則 A 讀取使用了錯(cuò)誤的數(shù)據(jù)。

不可重復(fù)讀(讀取了提交的新事物,指更新操作)
在對(duì)于數(shù)據(jù)庫(kù)中某個(gè)數(shù)據(jù),一個(gè)事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個(gè)事務(wù)修改了。

幻讀(讀取了新提交的事務(wù),指增加刪除操作)
在事務(wù) A 多次讀取構(gòu)成中,事務(wù) B 對(duì)數(shù)據(jù)進(jìn)行了新增/刪除操作,導(dǎo)致 事務(wù) A 多次讀取的數(shù)據(jù)不一致。

第一類事務(wù)丟失(回滾丟失)
事務(wù) A、B 同時(shí)執(zhí)行一個(gè)數(shù)據(jù),事務(wù) B 已經(jīng)提交,事務(wù) A 回滾了,B 的事務(wù)操作就因?yàn)槭聞?wù) A 回滾而丟失了
第二類事務(wù)丟失(提交覆蓋丟失)
事務(wù) A、B 同時(shí)執(zhí)行一個(gè)數(shù)據(jù),兩個(gè)同時(shí)獲取到一個(gè)數(shù)據(jù),事務(wù) B 先提交, 事務(wù) A 后提交,則事務(wù) A 覆蓋了事務(wù) B
四、傳播特性
事務(wù)的傳播性分為以下三類,所有的都是給內(nèi)部方法配置
4.1 死活都不要事務(wù)
Never:外部方法沒(méi)有事務(wù)就非事務(wù)執(zhí)行,有就拋出異常
Not_Supported:外部方法沒(méi)有事務(wù)就非事務(wù)執(zhí)行,有就直接掛起,然后非事務(wù)執(zhí)行
4.2 可有可無(wú)的
Supported:外部方法有事務(wù)就用,沒(méi)有就算了
4.3 必須要有事務(wù)
Requires_new:不管外部方法有沒(méi)有事務(wù)都新建事務(wù),如果外部有,就將外部事務(wù)掛起
Nested:如果外部方法沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果外部有事務(wù),就在外部事務(wù)中嵌套事務(wù)
Required:如果外部方法沒(méi)有事務(wù)就新建一個(gè)事務(wù),如果有,就加入外部方法的事務(wù),這個(gè)是最常用的,也是默認(rèn)的
Mandatory:如果外部方法沒(méi)有事務(wù)就拋出異常,如果有,就使用外部方法的事務(wù)
五、應(yīng)用
5.1 數(shù)據(jù)表

5.2 實(shí)體類
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
public class User {
@Id
@GeneratedValue
private Integer id;
private String name;
private double money;
}5.3 Service
package com.dily.study.work.service;
import com.dily.study.work.entity.User;
import com.dily.study.work.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired // 使用jpa
private UserRepository userRepository;
/**
* 轉(zhuǎn)出
*
* @param fromName 從誰(shuí)轉(zhuǎn)出
* @param money 轉(zhuǎn)出金額
*/
public void out(String fromName, int money) {
User user = userRepository.findByName(fromName);
user.setMoney(user.getMoney() - money);
userRepository.save(user);
}
/**
* 轉(zhuǎn)入
*
* @param toName 轉(zhuǎn)到哪里
* @param money 轉(zhuǎn)入金額
*/
public void in(String toName, int money) {
User user = userRepository.findByName(toName);
user.setMoney(user.getMoney() + money);
userRepository.save(user);
}
/**
* 帶事務(wù)
* 要么都成功,要么都失敗
*
* @param fromName 從哪里轉(zhuǎn)出
* @param toName 轉(zhuǎn)入到哪里
* @param money 金額
*/
@Transactional
public void transfer(String fromName, String toName, int money) {
out(fromName, money);
if (true) throw new RuntimeException("出錯(cuò)了");
in(toName, money);
}
/**
* 不帶事務(wù)
* 只有轉(zhuǎn)出成功,轉(zhuǎn)入失敗
*
* @param fromName 從哪里轉(zhuǎn)出
* @param toName 轉(zhuǎn)入到哪里
* @param money 金額
*/
public void transfer(String fromName, String toName, int money) {
out(fromName, money);
if (true) throw new RuntimeException("出錯(cuò)了");
in(toName, money);
}
}事務(wù)的嵌套
// 在 UserService 中注入自己,因?yàn)槿绻麅?nèi)部調(diào)用自己的方法,事務(wù)注解不生效。
@Autowired
private UserService userService;
/**
* 外層事務(wù),外層只轉(zhuǎn)出
*
* @param fromName 從哪里轉(zhuǎn)出
* @param toName 轉(zhuǎn)入到哪里
* @param money 金額
*/
@Transactional
public void laoda(String fromName, String toName, int money) {
userService.out(fromName, money);
if (true) throw new RuntimeException("出錯(cuò)了");
userService.xiaodi(toName,money);
}
/**
* 內(nèi)層事務(wù),內(nèi)層只轉(zhuǎn)入
* 可以修改 propagation 的值來(lái)查看不同傳播類型的效果
*
* @param toName 轉(zhuǎn)入到哪里
* @param money 金額
*/
@Transactional(propagation = Propagation.MANDATORY)
public void xiaodi(String toName, int money) {
if (true) throw new RuntimeException("出錯(cuò)了");
userService.in(toName, money);
}內(nèi)外部方法盡量避免操作同一張表,當(dāng)外部方法事務(wù)掛起時(shí),則外部操作的表會(huì)被加鎖,內(nèi)部方法事務(wù)則無(wú)法操作同一張表
到此這篇關(guān)于Spring事務(wù)管理零基礎(chǔ)入門的文章就介紹到這了,更多相關(guān)Spring事務(wù)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 8 Function函數(shù)式接口及函數(shù)式接口實(shí)例
函數(shù)式接口(Functional Interface)就是一個(gè)有且僅有一個(gè)抽象方法,但是可以有多個(gè)非抽象方法的接口。接下來(lái)通過(guò)本文給大家介紹Java 8 Function函數(shù)式接口及函數(shù)式接口實(shí)例代碼,需要的朋友可以參考下2018-05-05
SpringBoot和Vue.js實(shí)現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng)
本文主要介紹了SpringBoot和Vue.js實(shí)現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
spring中FactoryBean中的getObject()方法實(shí)例解析
這篇文章主要介紹了spring中FactoryBean中的getObject()方法實(shí)例解析,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02
詳解OAuth2 Token 一定要放在請(qǐng)求頭中嗎
這篇文章主要介紹了詳解OAuth2 Token 一定要放在請(qǐng)求頭中嗎,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(共享模式)
這篇文章主要為大家詳細(xì)介紹了Java并發(fā)系列之AbstractQueuedSynchronizer源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
PostMan post請(qǐng)求發(fā)送Json數(shù)據(jù)的方法
下面小編就為大家分享一篇PostMan post請(qǐng)求發(fā)送Json數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
java中int轉(zhuǎn)string與string轉(zhuǎn)int的效率對(duì)比
這篇文章主要介紹了java中int轉(zhuǎn)string與string轉(zhuǎn)int的效率對(duì)比,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot修改子模塊Module的jdk版本的方法 附修改原因
這篇文章主要介紹了SpringBoot修改子模塊Module的jdk版本的方法 附修改原因,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04

