亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring的事務(wù)管理你了解嗎

 更新時間:2022年01月20日 11:53:13   作者:YSOcean  
這篇文章主要為大家介紹了Spring的事務(wù)管理,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

1、事務(wù)介紹

事務(wù)(Transaction),一般是指要做的或所做的事情。在計算機術(shù)語中是指訪問并可能更新數(shù)據(jù)庫中各種數(shù)據(jù)項的一個程序執(zhí)行單元(unit)。

這里我們以取錢的例子來講解:比如你去ATM機取1000塊錢,大體有兩個步驟:第一步輸入密碼金額,銀行卡扣掉1000元錢;第二步從ATM出1000元錢。這兩個步驟必須是要么都執(zhí)行要么都不執(zhí)行。如果銀行卡扣除了1000塊但是ATM出錢失敗的話,你將會損失1000元;如果銀行卡扣錢失敗但是ATM卻出了1000塊,那么銀行將損失1000元。

如何保證這兩個步驟不會出現(xiàn)一個出現(xiàn)異常了,而另一個執(zhí)行成功呢?事務(wù)就是用來解決這樣的問題。事務(wù)是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那么事務(wù)就會回滾到最開始的狀態(tài),仿佛什么都沒發(fā)生過一樣。在企業(yè)級應(yīng)用程序開發(fā)中,事務(wù)管理是必不可少的技術(shù),用來確保數(shù)據(jù)的完整性和一致性。

2、事務(wù)的四個特性(ACID)

①、原子性(Atomicity):事務(wù)是一個原子操作,由一系列動作組成。事務(wù)的原子性確保動作要么全部完成,要么完全不起作用。

②、一致性(Consistency):一旦事務(wù)完成(不管成功還是失?。?,系統(tǒng)必須確保它所建模的業(yè)務(wù)處于一致的狀態(tài),而不會是部分完成部分失敗。在現(xiàn)實中的數(shù)據(jù)不應(yīng)該被破壞。

③、隔離性(Isolation):可能有許多事務(wù)會同時處理相同的數(shù)據(jù),因此每個事務(wù)都應(yīng)該與其他事務(wù)隔離開來,防止數(shù)據(jù)損壞。

④、持久性(Durability):一旦事務(wù)完成,無論發(fā)生什么系統(tǒng)錯誤,它的結(jié)果都不應(yīng)該受到影響,這樣就能從任何系統(tǒng)崩潰中恢復(fù)過來。通常情況下,事務(wù)的結(jié)果被寫到持久化存儲器中。

3、Spring 事務(wù)管理的核心接口

首先我們創(chuàng)建一個Java工程,然后導(dǎo)入 Spring 核心事務(wù)包  

我們打開Spring的核心事務(wù)包,查看如下類:org.springframework.transaction

  

上面所示的三個類文件便是Spring的事務(wù)管理接口。如下圖所示:下面我們分別對這三個接口進行簡單的介紹

  

4、PlatformTransactionManager 事務(wù)管理器

Spring事務(wù)管理器的接口是org.springframework.transaction.PlatformTransactionManager,如上圖所示,Spring并不直接管理事務(wù),通過這個接口,Spring為各個平臺如JDBC、Hibernate等都提供了對應(yīng)的事務(wù)管理器,也就是將事務(wù)管理的職責委托給Hibernate或者JTA等持久化機制所提供的相關(guān)平臺框架的事務(wù)來實現(xiàn)。

我們進入到 PlatformTransactionManager 接口,查看源碼:  

①、TransactionStatus getTransaction(TransactionDefinition definition),事務(wù)管理器 通過TransactionDefinition,獲得“事務(wù)狀態(tài)”,從而管理事務(wù)。

②、void commit(TransactionStatus status)根據(jù)狀態(tài)提交

③、void rollback(TransactionStatus status)根據(jù)狀態(tài)回滾

也就是說Spring事務(wù)管理的為不同的事務(wù)API提供一致的編程模型,具體的事務(wù)管理機制由對應(yīng)各個平臺去實現(xiàn)。

比如下面我們導(dǎo)入實現(xiàn)事務(wù)管理的兩種平臺:JDBC和Hibernate

  

然后我們再次查看PlatformTransactionManager接口,會發(fā)現(xiàn)它多了幾個實現(xiàn)類,如下:

  

5、TransactionStatus 事務(wù)狀態(tài)

在上面 PlatformTransactionManager 接口中,有如下方法:

  

這個方法返回的是 TransactionStatus對象,然后程序根據(jù)返回的對象來獲取事務(wù)狀態(tài),然后進行相應(yīng)的操作。

而 TransactionStatus 這個接口的內(nèi)容如下:  

這個接口描述的是一些處理事務(wù)提供簡單的控制事務(wù)執(zhí)行和查詢事務(wù)狀態(tài)的方法,在回滾或提交的時候需要應(yīng)用對應(yīng)的事務(wù)狀態(tài)。

6、TransactionDefinition 基本事務(wù)屬性的定義

上面講到的事務(wù)管理器接口PlatformTransactionManager通過getTransaction(TransactionDefinition definition)方法來得到事務(wù),這個方法里面的參數(shù)是TransactionDefinition類,這個類就定義了一些基本的事務(wù)屬性。

那么什么是事務(wù)屬性呢?事務(wù)屬性可以理解成事務(wù)的一些基本配置,描述了事務(wù)策略如何應(yīng)用到方法上。事務(wù)屬性包含了5個方面,如圖所示:

  

TransactionDefinition 接口方法如下:  

一、傳播行為:

當事務(wù)方法被另一個事務(wù)方法調(diào)用時,必須指定事務(wù)應(yīng)該如何傳播。

Spring 定義了如下七中傳播行為,這里以A業(yè)務(wù)和B業(yè)務(wù)之間如何傳播事務(wù)為例說明:

  • ①、PROPAGATION_REQUIREDrequired , 必須。默認值,A如果有事務(wù),B將使用該事務(wù);如果A沒有事務(wù),B將創(chuàng)建一個新的事務(wù)。
  • ②、PROPAGATION_SUPPORTSsupports ,支持。A如果有事務(wù),B將使用該事務(wù);如果A沒有事務(wù),B將以非事務(wù)執(zhí)行。
  • ③、PROPAGATION_MANDATORYmandatory ,強制。A如果有事務(wù),B將使用該事務(wù);如果A沒有事務(wù),B將拋異常。
  • ④、PROPAGATION_REQUIRES_NEWrequires_new,必須新的。如果A有事務(wù),將A的事務(wù)掛起,B創(chuàng)建一個新的事務(wù);如果A沒有事務(wù),B創(chuàng)建一個新的事務(wù)。
  • ⑤、PROPAGATION_NOT_SUPPORTEDnot_supported ,不支持。如果A有事務(wù),將A的事務(wù)掛起,B將以非事務(wù)執(zhí)行;如果A沒有事務(wù),B將以非事務(wù)執(zhí)行。
  • ⑥、PROPAGATION_NEVER never,從不。如果A有事務(wù),B將拋異常;如果A沒有事務(wù),B將以非事務(wù)執(zhí)行。
  • ⑦、PROPAGATION_NESTED nested ,嵌套。A和B底層采用保存點機制,形成嵌套事務(wù)。

二、隔離級別:

定義了一個事務(wù)可能受其他并發(fā)事務(wù)影響的程度。

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

在典型的應(yīng)用程序中,多個事務(wù)并發(fā)運行,經(jīng)常會操作相同的數(shù)據(jù)來完成各自的任務(wù)。并發(fā)雖然是必須的,但可能會導(dǎo)致以下的問題。

  • ①、臟讀(Dirty reads)——臟讀發(fā)生在一個事務(wù)讀取了另一個事務(wù)改寫但尚未提交的數(shù)據(jù)時。如果改寫在稍后被回滾了,那么第一個事務(wù)獲取的數(shù)據(jù)就是無效的。
  • ②、不可重復(fù)讀(Nonrepeatable read)——不可重復(fù)讀發(fā)生在一個事務(wù)執(zhí)行相同的查詢兩次或兩次以上,但是每次都得到不同的數(shù)據(jù)時。這通常是因為另一個并發(fā)事務(wù)在兩次查詢期間進行了更新。
  • ③、幻讀(Phantom read)——幻讀與不可重復(fù)讀類似。它發(fā)生在一個事務(wù)(T1)讀取了幾行數(shù)據(jù),接著另一個并發(fā)事務(wù)(T2)插入了一些數(shù)據(jù)時。在隨后的查詢中,第一個事務(wù)(T1)就會發(fā)現(xiàn)多了一些原本不存在的記錄。

注意:不可重復(fù)讀重點是修改,而幻讀重點是新增或刪除。

在 Spring 事務(wù)管理中,為我們定義了如下的隔離級別:

  • ①、ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫默認的隔離級別
  • ②、ISOLATION_READ_UNCOMMITTED:最低的隔離級別,允許讀取尚未提交的數(shù)據(jù)變更,可能會導(dǎo)致臟讀、幻讀或不可重復(fù)讀
  • ③、ISOLATION_READ_COMMITTED:允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生
  • ④、ISOLATION_REPEATABLE_READ:對同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復(fù)讀,但幻讀仍有可能發(fā)生
  • ⑤、ISOLATION_SERIALIZABLE:最高的隔離級別,完全服從ACID的隔離級別,確保阻止臟讀、不可重復(fù)讀以及幻讀,也是最慢的事務(wù)隔離級別,因為它通常是通過完全鎖定事務(wù)相關(guān)的數(shù)據(jù)庫表來實現(xiàn)的

上面定義的隔離級別,在 Spring 的TransactionDefinition.class 中也分別用常量 -1,0,1,2,4,8表示。

比如 ISOLATION_DEFAULT 的定義:

  

三、只讀

這是事務(wù)的第三個特性,是否為只讀事務(wù)。如果事務(wù)只對后端的數(shù)據(jù)庫進行該操作,數(shù)據(jù)庫可以利用事務(wù)的只讀特性來進行一些特定的優(yōu)化。通過將事務(wù)設(shè)置為只讀,你就可以給數(shù)據(jù)庫一個機會,讓它應(yīng)用它認為合適的優(yōu)化措施。

四、事務(wù)超時

為了使應(yīng)用程序很好地運行,事務(wù)不能運行太長的時間。因為事務(wù)可能涉及對后端數(shù)據(jù)庫的鎖定,所以長時間的事務(wù)會不必要的占用數(shù)據(jù)庫資源。事務(wù)超時就是事務(wù)的一個定時器,在特定時間內(nèi)事務(wù)如果沒有執(zhí)行完畢,那么就會自動回滾,而不是一直等待其結(jié)束。

五、回滾規(guī)則

事務(wù)五邊形的最后一個方面是一組規(guī)則,這些規(guī)則定義了哪些異常會導(dǎo)致事務(wù)回滾而哪些不會。默認情況下,事務(wù)只有遇到運行期異常時才會回滾,而在遇到檢查型異常時不會回滾(這一行為與EJB的回滾行為是一致的) 。但是你可以聲明事務(wù)在遇到特定的檢查型異常時像遇到運行期異常那樣回滾。同樣,你還可以聲明事務(wù)遇到特定的異常不回滾,即使這些異常是運行期異常。

7、Spring 編程式事務(wù)和聲明式事務(wù)的區(qū)別 

編程式事務(wù)處理:所謂編程式事務(wù)指的是通過編碼方式實現(xiàn)事務(wù),允許用戶在代碼中精確定義事務(wù)的邊界。即類似于JDBC編程實現(xiàn)事務(wù)管理。管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對于編程式事務(wù)管理,spring推薦使用TransactionTemplate。

聲明式事務(wù)處理:管理建立在AOP之上的。其本質(zhì)是對方法前后進行攔截,然后在目標方法開始之前創(chuàng)建或者加入一個事務(wù),在執(zhí)行完目標方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。聲明式事務(wù)最大的優(yōu)點就是不需要通過編程的方式管理事務(wù),這樣就不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼,只需在配置文件中做相關(guān)的事務(wù)規(guī)則聲明(或通過基于@Transactional注解的方式),便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中。

簡單地說,編程式事務(wù)侵入到了業(yè)務(wù)代碼里面,但是提供了更加詳細的事務(wù)管理;而聲明式事務(wù)由于基于AOP,所以既能起到事務(wù)管理的作用,又可以不影響業(yè)務(wù)代碼的具體實現(xiàn)。

8、不用事務(wù)實現(xiàn)轉(zhuǎn)賬

我們還是以轉(zhuǎn)賬為實例。不用事務(wù)看如何實現(xiàn)轉(zhuǎn)賬。在數(shù)據(jù)庫中有如下表 account ,內(nèi)容如下:

  

有兩個用戶 Tom 和 Marry 。他們初始賬戶余額都為 10000。這時候我們進行如下業(yè)務(wù):Tom 向 Marry 轉(zhuǎn)賬 1000 塊。那么這在程序中可以分解為兩個步驟:

①、Tom 的賬戶余額 10000 減少 1000 塊,剩余 9000 塊。

②、Marry 的賬戶余額 10000 增加 1000 塊,變?yōu)?11000塊。

上面兩個步驟要么都執(zhí)行成功,要么都不執(zhí)行。我們通過 TransactionTemplate 編程式事務(wù)來控制:

第一步:創(chuàng)建Java工程并導(dǎo)入相應(yīng)的 jar 包

(這里不用事務(wù)其實不需要這么多jar包,為了后面的講解需要,我們一次性導(dǎo)入所有的jar包)  

第二步:編寫 Dao 層

AccountDao 接口:

package com.ys.dao;
public interface AccountDao {
    /**
     * 匯款
     * @param outer 匯款人
     * @param money 匯款金額
     */
    public void out(String outer,int money);
    /**
     * 收款
     * @param inner 收款人
     * @param money 收款金額
     */
    public void in(String inner,int money);
}

AccountDaoImpl 接口實現(xiàn)類

package com.ys.dao.impl;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.ys.dao.AccountDao;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    /**
     * 根據(jù)用戶名減少賬戶金額
     */
    @Override
    public void out(String outer, int money) {
        this.getJdbcTemplate().update("update account set money = money - ? where username = ?",money,outer);
    }
    /**
     * 根據(jù)用戶名增加賬戶金額
     */
    @Override
    public void in(String inner, int money) {
        this.getJdbcTemplate().update("update account set money = money + ? where username = ?",money,inner);
    }
}

第三步:實現(xiàn) Service 層

AccountService 接口

package com.ys.service;
public interface AccountService {
    /**
     * 轉(zhuǎn)賬
     * @param outer 匯款人
     * @param inner 收款人
     * @param money 交易金額
     */
    public void transfer(String outer,String inner,int money);
}

AccountServiceImpl 接口實現(xiàn)類

package com.ys.service.impl;
import com.ys.dao.AccountDao;
import com.ys.service.AccountService;
public class AccountServiceImpl implements AccountService{
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void transfer(String outer, String inner, int money) {
        accountDao.out(outer, money);
        accountDao.in(inner, money);
    }
}

第四步:Spring 全局配置文件 applicationContext.xml

<?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:context="http://www.springframework.org/schema/context"
       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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">   
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <bean id="accountDao" class="com.ys.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.ys.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
</beans>

第五步:測試

public class TransactionTest {
    @Test
    public void testNoTransaction(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService account = (AccountService) context.getBean("accountService");
        //Tom 向 Marry 轉(zhuǎn)賬1000
        account.transfer("Tom", "Marry", 1000);
    }
}

第六步:查看數(shù)據(jù)庫表 account  

上面的結(jié)果和我們想的一樣,Tom 賬戶 money 減少了1000塊。而 Marry 賬戶金額增加了1000塊。

這時候問題來了,比如在 Tom 賬戶 money 減少了1000塊正常。而 Marry 賬戶金額增加時發(fā)生了異常,實際應(yīng)用中比如斷電(這里我們?nèi)藶闃?gòu)造除數(shù)不能為0的異常),如下:

  

那么這時候我們執(zhí)行測試程序,很顯然會報錯,那么數(shù)據(jù)庫是什么情況呢?  

數(shù)據(jù)庫account :  

我們發(fā)現(xiàn),程序執(zhí)行報錯了,但是數(shù)據(jù)庫 Tom 賬戶金額依然減少了 1000 塊,但是 Marry 賬戶的金額卻沒有增加。這在實際應(yīng)用中肯定是不允許的,那么如何解決呢?

9、編程式事務(wù)處理實現(xiàn)轉(zhuǎn)賬(TransactionTemplate)

上面轉(zhuǎn)賬的兩步操作中間發(fā)生了異常,但是第一步依然在數(shù)據(jù)庫中進行了增加操作。實際應(yīng)用中不會允許這樣的情況發(fā)生,所以我們這里用事務(wù)來進行管理。

Dao 層不變,我們在 Service 層注入TransactionTemplate 模板,因為是用模板來管理事務(wù),所以模板需要注入事務(wù)管理器 DataSourceTransactionManager 。而事務(wù)管理器說到底還是用底層的JDBC在管理,所以我們需要在事務(wù)管理器中注入 DataSource。這幾個步驟分別如下:

AccountServiceImpl 接口:

package com.ys.service.impl;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.ys.dao.AccountDao;
import com.ys.service.AccountService;
public class AccountServiceImpl implements AccountService{
    private AccountDao accountDao;
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void transfer(final String outer,final String inner,final int money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                accountDao.out(outer, money);
                //int i = 1/0;
                accountDao.in(inner, money);
            }
        });
    }
}

Spring 全局配置文件 applicationContext.xml:

<?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:context="http://www.springframework.org/schema/context"
       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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">   
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <bean id="accountDao" class="com.ys.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.ys.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
        <property name="transactionTemplate" ref="transactionTemplate"></property>
    </bean>
    <!-- 創(chuàng)建模板 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="txManager"></property>
    </bean>
    <!-- 配置事務(wù)管理器 ,管理器需要事務(wù),事務(wù)從Connection獲得,連接從連接池DataSource獲得 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

測試文件保持不變,可以分兩次測試,第一次兩次操作沒有發(fā)生異常,然后數(shù)據(jù)庫正常改變了。第二次操作中間發(fā)生了異常,發(fā)現(xiàn)數(shù)據(jù)庫內(nèi)容沒變。

如果大家有興趣也可以試試底層的PlatformTransactionManager來進行事務(wù)管理,我這里給出主要代碼:

//定義一個某個框架平臺的TransactionManager,如JDBC、Hibernate
        DataSourceTransactionManager dataSourceTransactionManager =
                new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // 設(shè)置數(shù)據(jù)源
        DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定義事務(wù)屬性
        transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 設(shè)置傳播行為屬性
        TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // 獲得事務(wù)狀態(tài)
        try {
            // 數(shù)據(jù)庫操作
            accountDao.out(outer, money);
            int i = 1/0;
            accountDao.in(inner, money);
            dataSourceTransactionManager.commit(status);// 提交
        } catch (Exception e) {
            dataSourceTransactionManager.rollback(status);// 回滾
        }

10、聲明式事務(wù)處理實現(xiàn)轉(zhuǎn)賬(基于AOP的 xml 配置)  

Dao 層和 Service 層與我們最先開始的不用事務(wù)實現(xiàn)轉(zhuǎn)賬保持不變。主要是 applicationContext.xml 文件變化了。

我們在 applicationContext.xml 文件中配置 aop 自動生成代理,進行事務(wù)管理:

  • ①、配置管理器
  • ②、配置事務(wù)詳情
  • ③、配置 aop
<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <bean id="accountDao" class="com.ys.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="accountService" class="com.ys.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>
    <!-- 1 事務(wù)管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2 事務(wù)詳情(事務(wù)通知)  , 在aop篩選基礎(chǔ)上,比如對ABC三個確定使用什么樣的事務(wù)。例如:AC讀寫、B只讀 等
        <tx:attributes> 用于配置事務(wù)詳情(屬性屬性)
            <tx:method name=""/> 詳情具體配置
                propagation 傳播行為 , REQUIRED:必須;REQUIRES_NEW:必須是新的
                isolation 隔離級別
    -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>
    <!-- 3 AOP編程,利用切入點表達式從目標類方法中 確定增強的連接器,從而獲得切入點 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ys.service..*.*(..))"/>
    </aop:config>
</beans>

測試類這里我們就不描述了,也是分有異常和無異常進行測試,發(fā)現(xiàn)與預(yù)期結(jié)果是吻合的。

11、聲明式事務(wù)處理實現(xiàn)轉(zhuǎn)賬(基于AOP的 注解 配置) 

分為如下兩步:

  • ①、在applicationContext.xml配置事務(wù)管理器,將并事務(wù)管理器交予spring
  • ②、在目標類或目標方法添加注解即可 @Transactional

首先在 applicationContext.xml 文件中配置如下:

<!-- 1 事務(wù)管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2 將管理器交予spring
        * transaction-manager 配置事務(wù)管理器
        * proxy-target-class
            true : 底層強制使用cglib 代理
    -->
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

其次在目標類或者方法添加注解@Transactional。如果在類上添加,則說明類中的所有方法都添加事務(wù),如果在方法上添加,則只有該方法具有事務(wù)。

package com.ys.service.impl;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ys.dao.AccountDao;
import com.ys.service.AccountService;
@Transactional(propagation=Propagation.REQUIRED , isolation = Isolation.DEFAULT)
@Service("accountService")
public class AccountServiceImpl implements AccountService{
    @Resource(name="accountDao")
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void transfer(String outer, String inner, int money) {
        accountDao.out(outer, money);
        //int i = 1/0;
        accountDao.in(inner, money);
    }
}

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • 解決調(diào)用ftpClient.retrieveFileStream(String?remoteFilePath)第二次讀取為空問題

    解決調(diào)用ftpClient.retrieveFileStream(String?remoteFilePath)第二次讀

    這篇文章主要給大家介紹了關(guān)于如何解決調(diào)用ftpClient.retrieveFileStream(String?remoteFilePath)第二次讀取為空問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-08-08
  • SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn)

    SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn)

    這篇文章主要介紹了SPRINGMVC JSON數(shù)據(jù)交互如何實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Java開發(fā)人員需知的十大戒律

    Java開發(fā)人員需知的十大戒律

    這篇文章主要介紹了Java開發(fā)人員需知的十大戒律,較為詳細的總結(jié)分析了Java開發(fā)中常見的注意事項與編程技巧,需要的朋友可以參考下
    2015-10-10
  • springboot vue完成編輯頁面發(fā)送接口請求功能

    springboot vue完成編輯頁面發(fā)送接口請求功能

    這篇文章主要為大家介紹了springboot+vue完成編輯頁發(fā)送接口請求功能,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • JavaWeb?Servlet技術(shù)及其應(yīng)用實踐

    JavaWeb?Servlet技術(shù)及其應(yīng)用實踐

    這篇文章主要介紹了JavaWeb?Servlet技術(shù),Servlet指在服務(wù)器端執(zhí)行的一段Java代碼,可以接收用戶的請求和返回給用戶響應(yīng)結(jié)果,感興趣想要詳細了解可以參考下文
    2023-05-05
  • @RequestParam注解加與不加有什么區(qū)別

    @RequestParam注解加與不加有什么區(qū)別

    這篇文章主要介紹了@RequestParam注解加與不加有什么區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • 詳解Java中跳躍表的原理和實現(xiàn)

    詳解Java中跳躍表的原理和實現(xiàn)

    跳躍表(Skip list)是有序鏈表的擴展,簡稱跳表,它在原有的有序鏈表上增加了多級索引,通過索引來實現(xiàn)快速查找,實質(zhì)上是一種可以進行二分查找的有序鏈表。本文主要為大家介紹了跳躍表的原理和實現(xiàn),需要的可以參考一下
    2022-12-12
  • Springboot教程之如何設(shè)置springboot熱重啟

    Springboot教程之如何設(shè)置springboot熱重啟

    這篇文章主要介紹了Springboot教程之如何設(shè)置springboot熱重啟,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 利用Spring JPA中的@Version注解實現(xiàn)樂觀鎖

    利用Spring JPA中的@Version注解實現(xiàn)樂觀鎖

    樂觀鎖是數(shù)據(jù)庫和應(yīng)用程序中使用的一種并發(fā)控制策略,用于在多個事務(wù)嘗試更新單個記錄時確保數(shù)據(jù)完整性,Java Persistence API (JPA) 提供了一種借助@Version注解在 Java 應(yīng)用程序中實現(xiàn)樂觀鎖的機制,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下
    2023-11-11
  • java中字符串與日期的轉(zhuǎn)換實例

    java中字符串與日期的轉(zhuǎn)換實例

    java中字符串與日期的轉(zhuǎn)換實例,需要的朋友可以參考一下
    2013-05-05

最新評論