欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的事務(wù)操作、注解及XML配置詳解

 更新時間:2018年12月29日 08:39:13   作者:余同學(xué)的開發(fā)之路  
這篇文章主要給大家介紹了關(guān)于Spring中事務(wù)操作、注解及XML配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

事務(wù)

事務(wù)全稱叫數(shù)據(jù)庫事務(wù),是數(shù)據(jù)庫并發(fā)控制時的基本單位,它是一個操作集合,這些操作要么不執(zhí)行,要么都執(zhí)行,不可分割。例如我們的轉(zhuǎn)賬這個業(yè)務(wù),就需要進(jìn)行數(shù)據(jù)庫事務(wù)的處理。

轉(zhuǎn)賬中至少會涉及到兩條 SQL 語句:

update Acoount set balance = balance - money where id = 'A';
update Acoount set balance = balance + money where id = 'B'

上面這兩條 SQL 就可以要看成是一個事務(wù),必須都執(zhí)行,或都不執(zhí)行。如何保證呢,一般這樣表示:

# 開啟事務(wù)
begin transaction
 
 
update Account set balance = balance - money where id = 'A';
update Account set balance = balance + money where id = 'B'
# 提交事務(wù)
commit transaction
 
Exception
 # 回滾事務(wù)
 rollback transaction

事務(wù)的特性(筆試的時候會有)

Atomic(原子性):事務(wù)中包含的操作被看做一個邏輯單元,這個邏輯單元中的操作要么全部成功,要么全部失敗。

Consistency(一致性):只有合法的數(shù)據(jù)可以被寫入數(shù)據(jù)庫,否則事務(wù)應(yīng)該將其回滾到最初狀態(tài)。在轉(zhuǎn)賬的時候不會出現(xiàn)一當(dāng)少錢了,另一方?jīng)]有增加的情況。

Isolation(隔離性):事務(wù)允許多個用戶對同一個數(shù)據(jù)進(jìn)行并發(fā)訪問,而不破壞數(shù)據(jù)的正確性和完整性。同時,并行事務(wù)的修改必須與其他并行事務(wù)的修改相互獨立。

Durability(持久性):事務(wù)完成之后,它對于系統(tǒng)的影響是永久的,該修改即使出現(xiàn)系統(tǒng)故障也將一直保留,真實的修改了數(shù)據(jù)庫。

以上 4 個屬性常被簡稱為 acid(酸的)。

事務(wù)并發(fā)的問題

臟讀:事務(wù)二讀取到事務(wù)一中已經(jīng)更新但是還沒有提交的數(shù)據(jù),這就是臟讀。

不可重復(fù)讀:一個事務(wù)兩次讀取同一個行數(shù)據(jù)結(jié)果不同,因為有其它的事務(wù)對數(shù)據(jù)進(jìn)行了更新。此時的數(shù)據(jù)即為不可重復(fù)讀數(shù)據(jù)。

幻讀:同一事務(wù)執(zhí)行兩次查詢,結(jié)果不一致,因為中間有其它的事務(wù)對數(shù)據(jù)進(jìn)行更改。

如何解決這些問題呢?數(shù)據(jù)庫系統(tǒng)為事務(wù)設(shè)置了 4 種不同的隔離級別。

事務(wù)隔離級別

讀未提交(read uncommitted):最低級別,可能會導(dǎo)入臟讀。

讀已提交(read committed):可以避免臟讀,只能查詢到已經(jīng)提交的數(shù)據(jù)。且具有良好的性能,但是不能避免不可重復(fù)讀和幻讀。

可重復(fù)讀(repeatable):解決了不可重復(fù)讀,可能會出現(xiàn)幻讀。

串行化(serializable):通過加鎖,使同一時間只能執(zhí)行一個事務(wù),不出現(xiàn)上述問題,但是可能會導(dǎo)致大量的超時現(xiàn)象和鎖競爭。

另外,MySQL 中默認(rèn)的隔離級別是可重復(fù)讀。Oracle 中默認(rèn)的事務(wù)隔離級別是讀已提交。

說完事務(wù),想想我們曾經(jīng)為了處理事務(wù)而寫過的那些代碼。最后在說說 Spring 中是如何處理的,學(xué)完 Spring 再也不用擔(dān)心事務(wù)操作了。

在 JDBC 時代我們需要這樣手動的處理事務(wù)。

// 獲取連接 conn
conn.setAutoCommit(false); 設(shè)置提交方式為手工提交
// 業(yè)務(wù)代碼
// 減錢
// 加錢
conn.commit(); 提交事務(wù)
// 出現(xiàn)異常
conn.rollback(); 回滾事務(wù)

我們說處理事務(wù)那是處理數(shù)據(jù)庫事務(wù),所以肯定要先有數(shù)據(jù)庫連接才能說事務(wù)的事,而在 Java 中我們連接數(shù)據(jù)庫無非就是 JDBC,或是對 JDBC 進(jìn)一步的封裝,比方說 Hibernate ,Mybatis 或是 Dbutils 這些框架,所以萬變不離其宗,就是這么回事,就是看誰封裝的好罷了。你們有興趣可以看看它們都是如何封裝的。

Spring 中的如何管理事務(wù)呢

首先,我們知道 Spring 是一個容器,不同的框架在處理事務(wù)時用到的對象不同,原生的 JDBC 使用 Connection ,而 Mybatis 中使用 SqlSession 對象。而 Spring 為了整合這些不同的框架,定義了一個 PlatformTransactionManager 接口來統(tǒng)一標(biāo)準(zhǔn),對不同的框架又有不同的實現(xiàn)類。

在 Spring 中根據(jù) DAO 層技術(shù)的不同來選擇不同的事務(wù)處理的對象,是 JDBC 時使用 DataSourceTransactionManager,是 Hibernate 時使用 HibernateTransitionmanager 對象,核心對象就是 Transitionmanager。

在 Spring 中管理事務(wù)會涉及到這幾個屬性,事務(wù)隔離級別、是否只讀、事務(wù)的傳播行為,說到事務(wù)的傳播行為,指的就是不同的業(yè)務(wù)方法之間相互調(diào)用時,應(yīng)該如何管理事務(wù)。Spring 中一共定義了 7 種傳播行為,無腦記住使用 required ,表示支持當(dāng)前事務(wù),若是不存在事務(wù),就創(chuàng)建一個。例如在 A 調(diào)用 B 的時候,會首先使用 A 的事務(wù),若 A 沒有事務(wù),則新創(chuàng)建一個,不管 B 有沒有事務(wù)。

下面就是要實際操作一下,需要有具體的業(yè)務(wù)邏輯,還是那個轉(zhuǎn)賬的例子。來看看如何使用 Spring 來管理事務(wù),有兩種常見的管理方式,我們一種一種的說。

使用 XML 配置

1 首先是導(dǎo)包,Spring 涉及的包是真的多,我有一個省事的方法,可能用到的 jar 包一下子導(dǎo)入。

2 導(dǎo)入新的約束文件,不然在 XML 無法使用 tx 標(biāo)簽。

3 準(zhǔn)備目標(biāo)對象和通知并配置。

目標(biāo)對象 AccountServiceImpl

public class AccountServiceImpl implements AccountService {
 
 private AccountDAO ad;
 
 @Transactional(isolation=Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly=false)
 @Override
 public void transfer(Integer from, Integer to, Double money) {
 
 ad.decreaseMoney(from, money);
 
 //int i = 1/0;
 
 ad.increaseMoney(to, money);
 }
 
 public void setAd(AccountDAO ad) {
 this.ad = ad;
 }
}

在 AOP 中通知即為增強的代碼,而在處理事務(wù)時,要增強的代碼無非就是開啟事務(wù),提交事務(wù)和回滾事務(wù),所以 Spring 已經(jīng)為我們封裝好了處理事務(wù)的通知,我們只需要配置一下即可。

<!-- 導(dǎo)入 properties 配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置連接數(shù)據(jù)庫的核心處理對象-->
<bean name="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref= "dataSource"></property>
</bean>
<!-- 配置通知-->
<tx:advice id="txAdvise" transaction-manager="transactionManager">
 <tx:attributes>
 <tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
 </tx:attributes>
</tx:advice>
<!-- 配置 AOP ,以達(dá)成自動處理事務(wù)的要求-->
<aop:config>
 <aop:pointcut expression="execution(* yu.transation.*ServiceImpl.*(..))" id="txPointcut"/>
 
 <aop:advisor advice-ref="txAdvise" pointcut-ref="txPointcut"/>
</aop:config>
 
 
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
 <property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
 <property name="driverClass" value="${jdbc.driverClass}" ></property>
 <property name="user" value="${jdbc.user}" ></property>
 <property name="password" value="${jdbc.password}" ></property>
</bean>
<!-- 配置 DAO 層對象-->
<bean name="ad" class="yu.transation.AccountDaoImpl">
 <property name="dataSource" ref = "dataSource"></property>
</bean>
<!-- 配置 Service 層對象-->
<bean name = "accountService" class = "yu.transation.AccountServiceImpl">
 <property name="ad" ref = "ad"></property>
</bean>

上面的配置文件中,在配置通知時,我們具體到不同的方法會有不同的配置,在項目應(yīng)用時,會使用通配符來進(jìn)行配置。下面介紹一下使用注解來處理事務(wù),看起來會比較簡單。

步驟和上面有重復(fù)的部分,需要導(dǎo)包導(dǎo)入約束,接下來就是配置一下使用注解管理事務(wù)的開關(guān)

使用注解配置

<!-- 打開注解配置 AOP 事務(wù) -->
<tx:annotation-driven/>

下面是使用注解為 Service 中的方法配置事務(wù)處理的屬性,當(dāng)然,每一個方法都寫會比較麻煩,也可以在類上面使用注解,若是某個方法的處理規(guī)則不一致就單獨使用注解配置一下。

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly=false)
@Override
public void transfer(Integer from, Integer to, Double money) {...}

回顧一下,以上主要說了事務(wù)以及 Spring 中處理事務(wù)的方式,而這也正是 AOP 思想在 Spring 中的應(yīng)用,我們可以看到不管是前面說的 IoC 還是 AOP 在這里都有體現(xiàn)。

注解的出現(xiàn)是為了替換配置文件,所以我就以配置文件為主,并說一下與之對應(yīng)的注解方式。

Spring 中的配置主要在核心配置文件 applicationContext.xml 中,由不同的標(biāo)簽來表示,所以首先我們就需要導(dǎo)入各種約束,常用的約束有 bean、context、aop、tx 。

bean 標(biāo)簽是最基本的標(biāo)簽,主要用來配置各種對象。

<!--
屬性介紹:
id: 為對象命名,唯一性標(biāo)識,不能重復(fù),不能使用特殊字符。
name: 和 id 的作用類似,區(qū)別在于可是使用特殊字符,可重復(fù),但是不建議重復(fù)。
class: 指定對象的全類名。
init-method: 對象初始化之后立即執(zhí)行的方法。
destroy-method: 對象銷毀之前執(zhí)行的方法。
scope: 對象的作用范圍,可以設(shè)置單例 singleton 和多例 prototype。默認(rèn)為單例
 -->
<bean name="userService" class="yu.service.UserServiceImpl" >
 <property name="" value="" ></property>
 <property name="" ref="" ></property>
</bean>

對應(yīng)的注解有以下幾個,但是想要使用注解之前要首先配置一下……

<!-- 打開注解配置,掃描包及其子包 -->
<context:component-scan base-package="yu"></context:component-scan>

使用注解的時候,我們可以使用 @Component 來表示將這個對象交由 Spring 管理,@Scope 來指定對象的作用域。之后便可以使用 @Resource 來獲取對象。

在注冊對象的時候我們可以使用 @Component ,但是若是每一個對象都是用這個注解,不能很好的分辨出對象屬于哪一層,所以 Spring 又提供了 @Controller @Service @Repository 來分別表示控制器層,Service 層和 DAO 層的對象,功能和 @Component 是一模一樣的。

同樣的在為對象賦值的時候,我們可以使用注解 @Autowired 來自動獲取容器中的對象,可是若是有重名的情況就需要另外一個注解 @Qualifier 來具體指定叫什么名字,這樣就有點麻煩了,我們一般都是直接使用 @Resource 來指定對象。

@Component("user")
@Scope("prototype")
public class User{
 private String name;
 
 @Value(value = "18") // 屬性注入,項目中不用。
 private Integer age;
 
 //@Autowired 自動裝配 Car 類型變量,同一類型
 //@Qualifier("car") 指定具體的是哪一個。
 @Resource(name = "car") // 指名道姓指定是哪個對象
 private Car car;
 
 ...
 
 @PostConstruct
 public void init(){
 System.out.println("init 方法");
 }
 @PreDestroy
 public void destroy(){
 System.out.println("destory 方法");
 }
}

aop 相關(guān)的配置和注解

在 Spring 中我們可以自定義通知和切面,下面只是展示了如何配置,但是在具體的業(yè)務(wù)中應(yīng)該不會出現(xiàn) 5 種通知齊上陣的現(xiàn)象。

<aop:config>
 <!-- 配置切點-->
 <aop:pointcut expression="execution(* yu.service.*ServiceImpl.*(..))" id="pc"/>
 
 <aop:aspect ref="myAdvice" >
  <!-- 指定名為before方法作為前置通知 -->
  <aop:before method="before" pointcut-ref="pc" />
  <!-- 后置 -->
  <aop:after-returning method="afterReturning" pointcut-ref="pc" />
  <!-- 環(huán)繞通知 -->
  <aop:around method="around" pointcut-ref="pc" />
  <!-- 異常攔截通知 -->
  <aop:after-throwing method="afterException" pointcut-ref="pc"/>
  <!-- 后置 -->
  <aop:after method="after" pointcut-ref="pc"/>
 </aop:aspect>
</aop:config>

同樣的,我們也可以使用注解來達(dá)到自定義配置的方式。同樣的套路,想用注解配置實現(xiàn) aop,需要打開注解配置 AOP 的開關(guān)。

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

之后就是在通知類中進(jìn)行配置即可。

@Aspect
//通知類
public class MyAdvice {
 
 // 快速配置切點表達(dá)式,方法直接調(diào)用即可
 @Pointcut("execution(* yu.service.*ServiceImpl.*(..))")
 public void pc(){}
 
 //前置通知
 @Before("MyAdvice.pc()")
 public void before(){
  System.out.println("這是前置通知!!");
 }
 //后置通知
 @AfterReturning("MyAdvice.pc()")
 public void afterReturning(){
  System.out.println("這是后置通知(如果出現(xiàn)異常不會調(diào)用)!!");
 }

context 主要是和全局有關(guān)的配置

<!-- 打開注解配置對象,掃描包及其子包 -->
<context:component-scan base-package="yu"></context:component-scan>
 
 
 
<!-- 導(dǎo)入 properties 配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
 
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
 <property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
 <property name="driverClass" value="${jdbc.driverClass}" ></property>
 <property name="user" value="${jdbc.user}" ></property>
 <property name="password" value="${jdbc.password}" ></property>
</bean>

tx 配置事務(wù)管理中的通知

tx 用來配置通知對象,而這個對象是由 Spring 為我們寫好了,而事務(wù)管理依賴于數(shù)據(jù)庫連接對象,所以你能看到 transactionManager 對象依賴于 dataSource 對象。

<bean name="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref= "dataSource"></property>
</bean>
 
<tx:advice id="txAdvise" transaction-manager="transactionManager">
 <tx:attributes>
  <tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
 </tx:attributes>
</tx:advice>
 
<aop:config>
 <aop:pointcut expression="execution(* yu.transation.*ServiceImpl.*(..))" id="txPointcut"/>
 
 <aop:advisor advice-ref="txAdvise" pointcut-ref="txPointcut"/>
</aop:config>

使用注解配置時還是需要打開注解配置的開關(guān)

<!-- 打開注解配置 AOP 事務(wù) -->
<tx:annotation-driven/>

在具體的業(yè)務(wù)方法上或是類上使用注解 @Transactional 來配置事務(wù)處理的方式。

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly=false)
@Override
public void transfer(Integer from, Integer to, Double money) {...}

最后有一個完美的意外,那就是 import 標(biāo)簽。用于導(dǎo)入其它的配置模塊到主配置文件中。

<!-- 導(dǎo)入其它的 Spring 配置模塊 -->
<import resource="yu/transation/applicationContext.xml"/>

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Netty分布式pipeline管道傳播事件的邏輯總結(jié)分析

    Netty分布式pipeline管道傳播事件的邏輯總結(jié)分析

    這篇文章主要為大家介紹了Netty分布式pipeline管道傳播事件總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • 使用eclipse導(dǎo)入javaWeb項目的圖文教程

    使用eclipse導(dǎo)入javaWeb項目的圖文教程

    這篇文章主要介紹了如何使用eclipse導(dǎo)入別人的javaWeb項目,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • 詳解Java枚舉與接口常量和類常量的區(qū)別

    詳解Java枚舉與接口常量和類常量的區(qū)別

    這篇文章主要為大家詳細(xì)介紹了Java中枚舉與接口常量、類常量有什么區(qū)別,文中的示例代碼講解詳細(xì),具有一定的參考價值,感興趣的可以了解一下
    2022-10-10
  • 詳解Java中的內(nèi)存屏障

    詳解Java中的內(nèi)存屏障

    這篇文章主要介紹了Java中的內(nèi)存屏障的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-05-05
  • SpringMVC使用@Valid注解實現(xiàn)數(shù)據(jù)驗證的代碼示例

    SpringMVC使用@Valid注解實現(xiàn)數(shù)據(jù)驗證的代碼示例

    在 Web 開發(fā)中,數(shù)據(jù)驗證是一個非常重要的環(huán)節(jié),它可以確保數(shù)據(jù)的合法性和正確性,保護(hù)系統(tǒng)不受到惡意攻擊或用戶誤操作的影響,在 SpringMVC 中,我們可以使用 @Valid 注解來實現(xiàn)數(shù)據(jù)驗證,所以本文就給大家介紹具體的使用方法,需要的朋友可以參考下
    2023-07-07
  • Java反射機制的簡單講解

    Java反射機制的簡單講解

    這篇文章主要介紹了Java反射機制的簡單講解,本文講解了Java的高級概念反射機制,通過文字介紹案例該項概念和代碼的詳細(xì)展示,需要的朋友可以參考下
    2021-07-07
  • Java開發(fā)利器之Guava?Cache的使用教程

    Java開發(fā)利器之Guava?Cache的使用教程

    緩存技術(shù)被認(rèn)為是減輕服務(wù)器負(fù)載、降低網(wǎng)絡(luò)擁塞、增強Web可擴展性的有效途徑之一。今天咱們就來聊聊Guava?Cache本地緩存,感興趣的可以了解一下
    2022-09-09
  • 基于SpringBoot集成測試遠(yuǎn)程連接Redis服務(wù)的教程詳解

    基于SpringBoot集成測試遠(yuǎn)程連接Redis服務(wù)的教程詳解

    這篇文章主要介紹了基于SpringBoot集成測試遠(yuǎn)程連接的Redis服務(wù)的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • spring cloud 阿波羅 apollo 本地開發(fā)環(huán)境搭建過程

    spring cloud 阿波羅 apollo 本地開發(fā)環(huán)境搭建過程

    Apollo(阿波羅)是攜程框架部門研發(fā)的配置管理平臺,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r推送到應(yīng)用端,并且具備規(guī)范的權(quán)限、流程治理等特性
    2018-01-01
  • Java跨域問題分析與解決方法詳解

    Java跨域問題分析與解決方法詳解

    這篇文章主要介紹了Java跨域問題分析與解決方法,跨域問題是在Web應(yīng)用程序中,由于同源策略的限制,導(dǎo)致瀏覽器無法發(fā)送跨域請求,也無法獲取跨域響應(yīng)的問題,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05

最新評論