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

Spring事務(wù)管理的使用細(xì)則淺析

 更新時(shí)間:2023年02月27日 09:19:31   作者:Java Fans  
事務(wù)的作用就是為了保證用戶的每一個(gè)操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開(kāi)始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們?cè)谑褂肧pring開(kāi)發(fā)應(yīng)用時(shí),大部分情況下也都需要使用事務(wù)

  事務(wù)(Transaction)是訪問(wèn)數(shù)據(jù)庫(kù)的一個(gè)操作序列,這些操作要么都做,要么都不做,是一個(gè)不可分割的工作單元。通過(guò)事務(wù),數(shù)據(jù)庫(kù)能將邏輯相關(guān)的一組操作綁定在一起,以便保持?jǐn)?shù)據(jù)的完整性。

事務(wù)有4個(gè)重要特性,簡(jiǎn)稱 ACID。

  • A:Automicity,原子性,即事務(wù)中的所有操作要么全部執(zhí)行,要么全部不執(zhí)行。
  • C:Consistency,一致性,事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致?tīng)顟B(tài)變到另一個(gè)一致?tīng)顟B(tài)。
  • I:Isolation,隔離性,即一個(gè)事務(wù)的執(zhí)行不能被另一個(gè)事務(wù)影響。
  • D:Durabillity,持久性,即事務(wù)提交后將被永久保存。

  在Java EE開(kāi)發(fā)中,事務(wù)原本屬于 Dao 層中的范疇,但一般情況下需要將事務(wù)提升到業(yè)務(wù)層(Service層),以便能夠使用事務(wù)的特性來(lái)管理具體的業(yè)務(wù)。

Spring 事務(wù)管理接口

  Spring 的事務(wù)管理,主要用到兩個(gè)事務(wù)相關(guān)的接口。

1、事務(wù)管理器接口 PlatformTransactionManager

  事務(wù)管理器接口 PlatformTransactionManager 主要用于完成事務(wù)的提交、回滾,及獲取事務(wù)的狀態(tài)信息。PlatformTransactionManager 接口有兩個(gè)常用的實(shí)現(xiàn)類:

  • DataSourceTransactionManager實(shí)現(xiàn)類:使用JDBC或MyBatis進(jìn)行數(shù)據(jù)持久化時(shí)使用。
  • HibernateTransactionManager實(shí)現(xiàn)類:使用Hibernate進(jìn)行數(shù)據(jù)持久化時(shí)使用。

  關(guān)于Spring的事務(wù)提交與回滾方式,默認(rèn)是:發(fā)生運(yùn)行時(shí)異常時(shí)回滾,發(fā)生受檢查異常時(shí)提交, 也就是說(shuō)程序拋出runtime異常的時(shí)候才會(huì)進(jìn)行回滾,其他異常不回滾。

2、事務(wù)定義接口 TransactionDefinition

  事務(wù)定義接口 TransactionDefinition 中定義了事務(wù)描述相關(guān)的三類常量:事務(wù)隔離級(jí)別常量、事務(wù)傳播行為常量、事務(wù)默認(rèn)超時(shí)時(shí)限常量,及對(duì)它們的操作。

【1】事務(wù)隔離級(jí)別常量

  在應(yīng)用程序中,多個(gè)事務(wù)并發(fā)運(yùn)行,操作相同的數(shù)據(jù),可能會(huì)引起臟讀,不可重復(fù)讀,幻讀等問(wèn)題 。

  • 臟讀(Dirty reads):第一個(gè)事務(wù)訪問(wèn)并改寫了數(shù)據(jù),尚未提交事務(wù),這時(shí)第二個(gè)事務(wù)進(jìn)來(lái)了,讀取了剛剛改寫的數(shù)據(jù),如果這時(shí)第一個(gè)事務(wù)回滾了,這樣第二個(gè)事務(wù)讀取到的數(shù)據(jù)就是無(wú)效的“臟數(shù)據(jù)”。
  • 不可重復(fù)讀(Nonrepeatable read):第一個(gè)事務(wù)在其生命周期內(nèi)多次查詢同一個(gè)數(shù)據(jù),在兩次查詢之間,第二個(gè)事務(wù)訪問(wèn)并改寫了該數(shù)據(jù),導(dǎo)致第一個(gè)事務(wù)兩次查詢同一個(gè)數(shù)據(jù)得到的結(jié)果不一樣。
  • 幻讀(Phantom read)——幻讀與不可重復(fù)讀類似。它發(fā)生在第一個(gè)事務(wù)在生命周期進(jìn)行了兩次按同一查詢條件查詢數(shù)據(jù),第一次按該查詢條件讀取了幾行數(shù)據(jù),這時(shí)第二個(gè)事務(wù)進(jìn)來(lái)了,插入或刪除了一些數(shù)據(jù)時(shí),然后第一個(gè)事務(wù)再次按同一條件查詢,發(fā)現(xiàn)多了一些原本不存在的記錄或者原有的記錄不見(jiàn)了。

  為了解決并發(fā)問(wèn)題,TransactionDefinition 接口定義了5個(gè)事務(wù)隔離常量如下:

  • DEFAULT:采用數(shù)據(jù)庫(kù) 默認(rèn) 的事務(wù)隔離級(jí)別。不同數(shù)據(jù)庫(kù)不一樣,MySql的默認(rèn)為 REPEATABLE_READ(可重復(fù)讀);Oracle默認(rèn)為READ_COMMITTED(讀已提交)。
  • READ_UNCOMMITTED:讀未提交。允許另外一個(gè)事務(wù)讀取到當(dāng)前事務(wù)未提交的數(shù)據(jù),隔離級(jí)別最低,未解決任何并發(fā)問(wèn)題,會(huì)產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。
  • READ_COMMITTED:讀已提交,被一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取,另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。解決臟讀,但還存在不可重復(fù)讀與幻讀。
  • REPEATABLE_READ:可重復(fù)讀。解決了臟讀、不可重復(fù)讀,但還存在幻讀。
  • SERIALIZABLE:串行化。按時(shí)間順序一一執(zhí)行多個(gè)事務(wù),不存在并發(fā)問(wèn)題,最可靠,但性能與效率最低。

【2】事務(wù)傳播行為常量

  事務(wù)傳播行為是指處于不同事務(wù)中的方法在相互調(diào)用時(shí),執(zhí)行期間事務(wù)的維護(hù)情況。例如,當(dāng)一個(gè)事務(wù)方法B調(diào)用另一個(gè)事務(wù)方法A時(shí),應(yīng)當(dāng)明確規(guī)定事務(wù)如何傳播,比方可以規(guī)定A方法繼續(xù)在B方法的現(xiàn)有事務(wù)中運(yùn)行,也可以規(guī)定A方法開(kāi)啟一個(gè)新事務(wù),在新事務(wù)中運(yùn)行,現(xiàn)有事務(wù)先掛起,等A方法的新事務(wù)執(zhí)行完畢后再恢復(fù)。TransactionDefinition 接口一共定義了 七種 傳播行為常量說(shuō)明如下。

  • PROPAGATION_ REQUIRED:指定的方法必須在事務(wù)內(nèi)執(zhí)行。若當(dāng)前存在事務(wù),就加入到當(dāng)前事務(wù)中;若當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新事務(wù)。這種傳播行為是最常見(jiàn)的選擇,也是 Spring 默認(rèn)的事務(wù)傳播行為。如該傳播行為加在actionB ()方法上,該方法將被actionA ()調(diào)用,若actionA ()方法在執(zhí)行時(shí)就是在事務(wù)內(nèi)的,則actionB ()方法的執(zhí)行也加入到該事務(wù)內(nèi)執(zhí)行。若actionA ()方法沒(méi)有在事務(wù)內(nèi)執(zhí)行,則actionB ()方法會(huì)創(chuàng)建一個(gè)事務(wù),并在其中執(zhí)行。
  • PROPAGATION_ SUPPORTS:指定的方法支持當(dāng)前事務(wù),但若當(dāng)前沒(méi)有事務(wù),也可以以非事務(wù)方式執(zhí)行。
  • PROPAGATION_ MANDATORY:指定的方法必須在當(dāng)前事務(wù)內(nèi)執(zhí)行,若當(dāng)前沒(méi)有事務(wù),則直接拋出異常。
  • PROPAGATION_ REQUIRES_NEW:總是新建一個(gè)事務(wù),若當(dāng)前存在事務(wù),就將當(dāng)前事務(wù)掛起,直到新事務(wù)執(zhí)行完畢。
  • PROPAGATION_ NOT_SUPPORTED:指定的方法不能在事務(wù)環(huán)境中執(zhí)行,若當(dāng)前存在事務(wù),就將當(dāng)前事務(wù)掛起。
  • PROPAGATION_ NEVER:指定的方法不能在事務(wù)環(huán)境下執(zhí)行,若當(dāng)前存在事務(wù),就直接拋出異常。
  • PROPAGATION_ NESTED:指定的方法必須在事務(wù)內(nèi)執(zhí)行。若當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行;若當(dāng)前沒(méi)有事務(wù),則創(chuàng)建一個(gè)新事務(wù)。

【3】默認(rèn)事務(wù)超時(shí)時(shí)限

  常量 TIMEOUT_DEFAULT 定義了事務(wù)底層默認(rèn)的超時(shí)時(shí)限,及不支持事務(wù)超時(shí)時(shí)限設(shè)置的none值。該值一般使用默認(rèn)值即可。

Spring 事務(wù)管理的實(shí)現(xiàn)方法

  Spring 支持編程式事務(wù)和聲明式事務(wù)。

  編程式事務(wù) 直接在主業(yè)務(wù)代碼中精確定義事務(wù)的邊界,事務(wù)以硬編碼的方式嵌入到了主業(yè)務(wù)代碼里面,好處是能提供更加詳細(xì)的事務(wù)管理,但由于編程式事務(wù)主業(yè)務(wù)與事務(wù)代碼混在一起,不易分離,耦合度高,不利于維護(hù)與重用。

  聲明式事務(wù) 則基于 AOP 方式,能將主業(yè)務(wù)操作與事務(wù)規(guī)則進(jìn)行解耦。能在不影響業(yè)務(wù)代碼的具體實(shí)現(xiàn)情況下實(shí)現(xiàn)事務(wù)管理。所以比較常用的是聲明式事務(wù)。聲明式事務(wù)又有兩種具體的實(shí)現(xiàn)方式:基于XML配置文件的方式 和 基于注解的方式。

1、沒(méi)有事務(wù)管理的情況分析

  項(xiàng)目案例: 模擬支付寶轉(zhuǎn)賬,張三、李四原本各有賬戶余額 2000 元,張三轉(zhuǎn)賬 500 元給李四,但轉(zhuǎn)賬過(guò)程中出現(xiàn)了異常。

  實(shí)現(xiàn)步驟:

【1】在 MySQL 中創(chuàng)建數(shù)據(jù)庫(kù)表,代碼如下:

create table alipay(
	aliname varchar (60),
	amount double
);

【2】在 dao 層創(chuàng)建 IAccountDao 接口,代碼如下

package com.hh.dao;
public interface AlipayDao {
	public void transfer(String fromA,String toB,int amount);
}

【3】創(chuàng)建 IAccountDao 接口的實(shí)現(xiàn)類 IAccountDaoImpl,代碼如下:

package com.hh.dao;
import org.springframework.jdbc.core.JdbcTemplate;
public class AlipayDaoImpl implements AlipayDao{
	JdbcTemplate jdbcTemplate;	
	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	@Override
	public void transfer(String fromA, String toB, int amount) {
		jdbcTemplate.update("update alipay set amount=amount-? where aliname=?",amount,fromA);
		Integer.parseInt("a");
		jdbcTemplate.update("update alipay set amount=amount+? where aliname=?",amount,toB);
	}
}

  這個(gè) transfer 方法主要實(shí)現(xiàn)兩個(gè)操作:

  操作一:轉(zhuǎn)出操作,張三的賬戶錢減少;

  操作二:轉(zhuǎn)入操作,里斯的賬戶錢增加;

  但兩個(gè)操作中間模擬出現(xiàn)了差錯(cuò)(異常),這將導(dǎo)致張三的錢少了,而李四的錢卻沒(méi)有增加。

【4】添加 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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">	
	<!-- 配置數(shù)據(jù)源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/usersdb </value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>root</value>
		</property>
	</bean>	
	<!-- 配置jdbcTemplate模板 注入dataSource -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />	
	</bean>	
	<!-- 配置DAO,注入jdbcTemplate屬性值 -->
	<bean id="userDao" class="com.hh.dao.UserDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"/>
	</bean>	
	<!-- 配置DAO,注入jdbcTemplate屬性值 -->
	<bean id="alipayDao" class="com.hh.dao.AlipayDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"/>
	</bean>
</beans>

【5】添加測(cè)試類 TestAlipay

package com.hh.test;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hh.dao.AlipayDao;
public class TestAlipay {
	public static void main(String[] args) {
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		AlipayDao alipayDao=(AlipayDao) context.getBean("alipayDao");
		alipayDao.transfer("張三", "李四", 500);
	}
}

2、通過(guò)配置 XML 實(shí)現(xiàn)事務(wù)管理

  下面進(jìn)行事務(wù)管理方面的改進(jìn),目標(biāo)是把類 AlipayDaoImpl 里的整個(gè) transfer( ) 方法作為事務(wù)管理,這樣 transfer( ) 里的所有操作(包括轉(zhuǎn)出/轉(zhuǎn)入操作)都納入同一個(gè)事務(wù),從而使 transfer( ) 里的所有操作要么一起成功,要么一起失敗。這里利用了 Spring 的事務(wù)管理機(jī)制進(jìn)行處理。

項(xiàng)目案例: 模擬支付寶轉(zhuǎn)賬,張三、李四原本各有賬戶余額 2000 元,張三轉(zhuǎn)賬 500 元給李四,但轉(zhuǎn)賬過(guò)程中間出現(xiàn)異常,導(dǎo)致數(shù)據(jù)不一致 ,現(xiàn)應(yīng)用 Spring 的事務(wù)管理,配置 XML,避免不一致的情況。

實(shí)現(xiàn)步驟:

【1】修改 Spring 配置文件,內(nèi)容如下:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">	
	<!-- 配置數(shù)據(jù)源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/usersdb </value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>root</value>
		</property>
	</bean>	
	<!-- 配置jdbcTemplate模板 注入dataSource -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />	
	</bean>	
	<!-- 配置DAO,注入jdbcTemplate屬性值 -->
	<bean id="alipayDao" class="com.lifeng.dao.AlipayDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"/>
	</bean>
	<!-- 定義事務(wù)管理器 -->
	<bean id="txManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 編寫事務(wù)通知 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED" 	isolation="DEFAULT"	 read-only="false" />			
			<!-- 
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="search*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="select*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="find*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="get*" propagation="SUPPORTS"  read-only="true"/> -->	
		</tx:attributes>
	</tx:advice>	
	<!-- 編寫AOP,讓spring自動(dòng)將事務(wù)切入到目標(biāo)切點(diǎn) -->
	<aop:config>
		<!-- 定義切入點(diǎn) -->
		<aop:pointcut id="txPointcut"
			expression="execution(* com.lifeng.dao.*.*(..))" />
		<!-- 將事務(wù)通知與切入點(diǎn)組合 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
	</aop:config>	
</beans>

  這里可以把事務(wù)功能理解為切面,通過(guò)aop配置實(shí)現(xiàn)事務(wù)(切面)自動(dòng)切入到切入點(diǎn)(目標(biāo)方法),從而將目標(biāo)方法(切入點(diǎn))納入事務(wù)管理,而目標(biāo)方法本身可以不用管事務(wù),專心做自已的主業(yè)務(wù)功能就行了

【2】其它程序代碼不變,運(yùn)行測(cè)試。

  測(cè)試時(shí)盡管轉(zhuǎn)賬中間出現(xiàn)了異常,但是張三、李四的錢都沒(méi)變化,保持了一致性,這樣就達(dá)到了目的,證明了 transfer 方法中的兩個(gè)操作都納入了同一個(gè)事務(wù)。發(fā)生異常時(shí),事務(wù)回滾,保證了數(shù)據(jù)的一致性。

  上面配置中:

<tx:method name="*" propagation="REQUIRED" 
		isolation="DEFAULT"	 read-only="false" />

  表示匹配的切點(diǎn)方法都進(jìn)行事務(wù)管理,這里*表示匹配所有切點(diǎn)方法,propagation="REQUIRED"表示匹配的切點(diǎn)方法必須在事務(wù)內(nèi)執(zhí)行,isolation="DEFAULT"表示事務(wù)隔離級(jí)別默認(rèn),對(duì)于MySQL數(shù)據(jù)庫(kù),隔離級(jí)別為REPEATABLE_READ(可重復(fù)讀)。read-only="false"表示非只讀。

  這個(gè)配置粒度太大,所有方法都同一種事務(wù)管理模式,要想不同的方法實(shí)現(xiàn)不一樣的事務(wù)管理,還得細(xì)化配置。項(xiàng)目中常見(jiàn)的細(xì)化配置如下面代碼所示。

	<!-- 編寫通知 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="search*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="select*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="find*" propagation="SUPPORTS"  read-only="true"/>
			<tx:method name="get*" propagation="SUPPORTS"  read-only="true"/>
		</tx:attributes>
	</tx:advice>

  這樣,不同的方法匹配不同的事務(wù)管理模式。

  <tx:method name=“save*” propagation=“REQUIRED” />表示凡是以save開(kāi)頭的切點(diǎn)方法必須在事務(wù)內(nèi)執(zhí)行,其他增刪改都一樣的意思,查的話就不同<tx:method name=“select*” propagation=“SUPPORTS” read-only=“true”/>表示心是以select開(kāi)頭的切點(diǎn)方法支持當(dāng)前事務(wù),但若當(dāng)前沒(méi)有事務(wù),也可以以非事務(wù)方式執(zhí)行,read-only="true"表示只讀,其他幾個(gè)類似。

3、利用注解實(shí)現(xiàn)事務(wù)管理

  上面是利用XML配置文件實(shí)現(xiàn)事務(wù)管理的辦法,下面來(lái)學(xué)習(xí)用注解實(shí)現(xiàn)事務(wù)管理。

  使用@Transactional注解在類或方法上,即可實(shí)現(xiàn)事務(wù)管理。 @Transactional注解的屬性有下面這些(可選):

  • propagation:用于設(shè)置事務(wù)傳播的屬性,該屬性類型為propagation枚舉,默認(rèn)值為Propagation.REQUIRED。
  • isolation:用于設(shè)置事務(wù)的隔離級(jí)別,該屬性類型為Isolation枚舉,默認(rèn)值為Isolation.DEFAULT。
  • readOnly:用于設(shè)置該方法對(duì)數(shù)據(jù)庫(kù)的操作是否是只讀的,該屬性為boolean,默認(rèn)值false。
  • timeout:用于設(shè)置本操作與數(shù)據(jù)庫(kù)連接的超時(shí)時(shí)限。單位為秒,類型為int,默認(rèn)值為-1,即沒(méi)有時(shí)限。
  • rollbackFor:指定需要回滾的異常類,類型為 Class[],默認(rèn)值為空數(shù)組。當(dāng)然,若只有一個(gè)異常類時(shí),可以不使用數(shù)組。
  • rollbackForClassName:指定需要回滾的異常類類名,類型為 String[],默認(rèn)值為空數(shù)組。當(dāng)然,若只有一個(gè)異常類時(shí),可以不使用數(shù)組。
  • noRollbackFor:指定不需要回滾的異常類。類型為Class[],默認(rèn)值為空數(shù)組。當(dāng)然,若只有一個(gè)異常類時(shí),可以不使用數(shù)組。
  • noRollbackForClassName:指定不需要回滾的異常類類名。類型為String[],默認(rèn)值為空數(shù)組。當(dāng)然,若只有一個(gè)異常類時(shí),可以不使用數(shù)組。

  需要注意的是,@Transactional 若用在方法上,只能用于public方法上。對(duì)于其他非 public方法,如果加上了注解 @Transactional,雖然 Spring 不會(huì)報(bào)錯(cuò),但不會(huì)將指定事務(wù)織入到該方法中。因?yàn)镾pring會(huì)忽略掉所有非public方法上的 @Transaction 注解。若 @Transaction 注解在類上,則表示該類上所有的方法均將在執(zhí)行時(shí)織入事務(wù)。

項(xiàng)目案例: 模擬支付寶轉(zhuǎn)賬,張三李四原本各有賬戶余額2000元,張三轉(zhuǎn)賬500元給李四,但轉(zhuǎn)賬過(guò)程中間出現(xiàn)異常,應(yīng)用spring的事務(wù)管理,使用注解,避免不一致的情況。

實(shí)現(xiàn)步驟:

【1】修改 Spring 配置文件如下:

	<!-- 定義事務(wù)管理器 -->
	<bean id="txManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 開(kāi)啟事務(wù)注解驅(qū)動(dòng) -->
	<tx:annotation-driven transaction-manager="txManager"/></beans>

  可以發(fā)現(xiàn),配置文件比之前簡(jiǎn)化了很多,事務(wù)方面,只需定義好事務(wù)管理器,再開(kāi)啟事務(wù)注解驅(qū)動(dòng)就行了。其他的交給注解來(lái)解決。

【2】利用 @Transactional 注解修改轉(zhuǎn)賬方法。

  @Transactional 既可以用來(lái)修飾類,也可以修飾方法,如果修飾類,則表示事務(wù)的設(shè)置對(duì)整個(gè)類的所有方法都起作用,如果修飾在方法上,則只對(duì)該方法起作用,關(guān)鍵代碼如下。

public class AlipayDaoImpl implements AlipayDao{
@Override
	@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
	public void transfer(String fromA, String toB, int amount) {
		jdbcTemplate.update("update alipay set amount=amount-? where aliname=?",amount,fromA);
		Integer.parseInt("a");
		jdbcTemplate.update("update alipay set amount=amount+? where aliname=?",amount,toB);
	}

  將transfer方法注解為事務(wù)。

【3】運(yùn)行測(cè)試,發(fā)現(xiàn)數(shù)據(jù)庫(kù)同樣沒(méi)改變,所以注解事務(wù)起到作用了。

4、在業(yè)務(wù)層實(shí)現(xiàn)事務(wù)管理

  上面的案例是在DAO層實(shí)現(xiàn)事務(wù)管理,相對(duì)簡(jiǎn)單一些,但實(shí)際上開(kāi)發(fā)時(shí)需要在業(yè)務(wù)層實(shí)現(xiàn)事務(wù)管理,而不是在DAO層,為此,項(xiàng)目修改如下,特別要注意在業(yè)務(wù)層的事務(wù)管理實(shí)現(xiàn)。

項(xiàng)目案例: 模擬支付寶轉(zhuǎn)賬,張三李四原本各有賬戶余額2000元,張三轉(zhuǎn)賬500元給李四,但轉(zhuǎn)賬過(guò)程中間出現(xiàn)異常,在業(yè)務(wù)層應(yīng)用spring的事務(wù)管理,配置xml,避免不一致的情況。

實(shí)現(xiàn)步驟:

【1】修改DAO層,轉(zhuǎn)出轉(zhuǎn)入分拆成兩個(gè)方法。

	@Override
	public void tranferFrom(String fromA,int amount){
		jdbcTemplate.update("update alipay set amount=amount-? where aliname=?",amount,fromA);
	}
	@Override
	public void tranferTo(String toB,int amount){
		jdbcTemplate.update("update alipay set amount=amount+? where aliname=?",amount,toB);
	}

【2】新建包c(diǎn)om.hh.service,創(chuàng)建業(yè)務(wù)層AlipayService.java類,代碼如下:

public class AlipayService {
	private AlipayDao alipayDao;
		public void transfer(String fromA, String toB, int amount) {
		alipayDao.tranferFrom(fromA, amount);
		Integer.parseInt("a");
		alipayDao.tranferTo(toB, amount);
	}
}

  上述代碼相當(dāng)于把有異常問(wèn)題的 transfer( ) 方法遷移到業(yè)務(wù)層中來(lái)。

【3】修改配置文件。關(guān)鍵配置如下:

	<!-- 定義事務(wù)管理器 -->
	<bean id="txManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 編寫事務(wù)通知 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" propagation="REQUIRED" 	isolation="DEFAULT"	 read-only="false" />		
		</tx:attributes>
	</tx:advice>	
	<!-- 編寫AOP,讓spring自動(dòng)將事務(wù)切入到目標(biāo)切點(diǎn) -->
	<aop:config>
		<!-- 定義切入點(diǎn) -->
		<aop:pointcut id="txPointcut"
			expression="execution(* com.lifeng.service.*.*(..))" />
		<!-- 將事務(wù)通知與切入點(diǎn)組合 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
	</aop:config>

【4】修改測(cè)試類,代碼如下:

public class TestAlipay {
	public static void main(String[] args) {
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		AlipayService alipayService=(AlipayService) context.getBean("alipayService");
		alipayService.transfer("張三", "李四", 500);
	}
}

  測(cè)試結(jié)束,數(shù)據(jù)庫(kù)的數(shù)據(jù)保持不變,證明事務(wù)管理成功。

到此這篇關(guān)于Spring事務(wù)管理的使用細(xì)則淺析的文章就介紹到這了,更多相關(guān)Spring事務(wù)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談java中Map的用法

    淺談java中Map的用法

    Map簡(jiǎn)介:將鍵映射到值的對(duì)象。一個(gè)映射不能包含重復(fù)的鍵;每個(gè)鍵最多只能映射到一個(gè)值。此接口取代 Dictionary 類,后者完全是一個(gè)抽象類,而不是一個(gè)接口。
    2015-09-09
  • Spring中@Configuration注解的使用場(chǎng)景

    Spring中@Configuration注解的使用場(chǎng)景

    這篇文章主要介紹了Spring中@Configuration注解的使用場(chǎng)景,@Configuration注解是從Spring?3.0版本開(kāi)始加入的一個(gè)使Spring能夠支持注解驅(qū)動(dòng)開(kāi)發(fā)的標(biāo)注型注解,主要用于標(biāo)注在類上,需要的朋友可以參考下
    2023-11-11
  • Java容器ArrayList原理解析

    Java容器ArrayList原理解析

    這篇文章主要介紹了Java容器ArrayList原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Spring—@Value在static中引用方式

    Spring—@Value在static中引用方式

    這篇文章主要介紹了Spring—@Value在static中引用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 使用WebUploader實(shí)現(xiàn)上傳文件功能(一)

    使用WebUploader實(shí)現(xiàn)上傳文件功能(一)

    這篇文章主要為大家詳細(xì)介紹了使用WebUploader實(shí)現(xiàn)上傳文件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java集合中HashSet LinkedHashSet TreeSet三者異同面試精講

    java集合中HashSet LinkedHashSet TreeSet三者異同面試精講

    這篇文章主要為大家介紹了java集合中HashSet LinkedHashSet TreeSet三者異同面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • SpringBoot中jar打包并部署到Tomcat

    SpringBoot中jar打包并部署到Tomcat

    最近做了一個(gè)SpringBoot項(xiàng)目,今天介紹一下SpringBoot中jar打包并部署到Tomcat,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Spring?Security用戶定義?

    Spring?Security用戶定義?

    這篇文章主要介紹了Spring?Security用戶定義,大家都知道?Spring?Security的用戶定義有很多方式,其實(shí)主要有兩種,基于內(nèi)存的和基于數(shù)據(jù)庫(kù)的,下面我給大家簡(jiǎn)單介紹一下這兩種方式,需要的朋友可以參考下
    2022-02-02
  • 淺談Spring refresh的工作流程

    淺談Spring refresh的工作流程

    這篇文章主要介紹了淺談Spring refresh的工作流程,refresh 是 AbstractApplicationContext 中的一個(gè)方法,負(fù)責(zé)初始化 ApplicationContext容器,讓我們一起來(lái)學(xué)習(xí)一下吧
    2023-04-04
  • java遍歷讀取整個(gè)redis數(shù)據(jù)庫(kù)實(shí)例

    java遍歷讀取整個(gè)redis數(shù)據(jù)庫(kù)實(shí)例

    這篇文章主要介紹了java遍歷讀取整個(gè)redis數(shù)據(jù)庫(kù)實(shí)例,使用支持正則表達(dá)式的key搜索方法jedis.keys(“*”)實(shí)現(xiàn),需要的朋友可以參考下
    2014-05-05

最新評(píng)論