自動(dòng)搭建網(wǎng)站源碼優(yōu)就業(yè)seo
spring事務(wù)管理(以轉(zhuǎn)賬為例)
概述
Spring事務(wù)管理提供了一種在應(yīng)用程序中管理事務(wù)的機(jī)制,它抽象了底層的事務(wù)管理細(xì)節(jié),使得開(kāi)發(fā)者可以更加專注于業(yè)務(wù)邏輯的實(shí)現(xiàn),而不必過(guò)多關(guān)心事務(wù)的處理。以下是Spring事務(wù)管理的一般概述:
-
事務(wù)的概念: 事務(wù)是一組操作,它們被看作一個(gè)不可分割的工作單元,要么全部執(zhí)行成功,要么全部不執(zhí)行。在數(shù)據(jù)庫(kù)中,事務(wù)通常用于確保數(shù)據(jù)庫(kù)的一致性和完整性。
-
Spring事務(wù)抽象: Spring提供了一個(gè)強(qiáng)大的事務(wù)管理抽象,它包括兩個(gè)核心概念:事務(wù)管理器(TransactionManager) 和 事務(wù)定義(TransactionDefinition)。
-
事務(wù)管理器(TransactionManager): 是一個(gè)接口,它負(fù)責(zé)事務(wù)的啟動(dòng)、提交和回滾。Spring有多個(gè)實(shí)現(xiàn)類,可以適用于不同的事務(wù)管理場(chǎng)景。
-
事務(wù)定義(TransactionDefinition): 定義了事務(wù)的屬性,如隔離級(jí)別、傳播行為、超時(shí)等。Spring允許通過(guò)XML或注解的方式來(lái)配置事務(wù)的屬性。
-
-
聲明式事務(wù)管理: Spring支持聲明式事務(wù)管理,這意味著你可以通過(guò)配置文件或注解的方式來(lái)聲明事務(wù),而不必在代碼中顯式編寫(xiě)事務(wù)管理的邏輯。
-
XML配置方式: 通過(guò)XML配置文件中的
和
元素來(lái)聲明事務(wù)。 -
注解配置方式: 使用
@Transactional
注解來(lái)標(biāo)注需要事務(wù)管理的方法,然后通過(guò)配置啟用注解驅(qū)動(dòng)事務(wù)管理。
-
-
編程式事務(wù)管理: 除了聲明式事務(wù)管理外,Spring還支持編程式事務(wù)管理,這意味著你可以在代碼中顯式控制事務(wù)的開(kāi)始、提交和回滾。
-
使用
TransactionTemplate
類: Spring提供了TransactionTemplate
類,它封裝了事務(wù)的基本操作,你可以在代碼中使用它來(lái)編程式地管理事務(wù)。
-
-
事務(wù)傳播行為: 在Spring中,事務(wù)的傳播行為(Transaction Propagation Behavior)定義了在一個(gè)事務(wù)方法被另一個(gè)事務(wù)方法調(diào)用時(shí),應(yīng)該如何處理事務(wù)。Spring定義了七種事務(wù)傳播行為:
-
PROPAGATION_REQUIRED(默認(rèn)):
-
如果當(dāng)前存在事務(wù),則加入該事務(wù);如果不存在事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。這是最常見(jiàn)的傳播行為。
-
-
PROPAGATION_SUPPORTS:
-
如果當(dāng)前存在事務(wù),則加入該事務(wù);如果不存在事務(wù),則以非事務(wù)的方式執(zhí)行。
-
-
PROPAGATION_MANDATORY:
-
如果當(dāng)前存在事務(wù),則加入該事務(wù);如果不存在事務(wù),則拋出異常。要求外部調(diào)用方必須在事務(wù)中調(diào)用。
-
-
PROPAGATION_REQUIRES_NEW:
-
無(wú)論當(dāng)前是否存在事務(wù),都創(chuàng)建一個(gè)新的事務(wù)。如果有事務(wù)存在,將它掛起。
-
-
PROPAGATION_NOT_SUPPORTED:
-
以非事務(wù)的方式執(zhí)行操作,如果當(dāng)前存在事務(wù),則將其掛起。
-
-
PROPAGATION_NEVER:
-
以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),則拋出異常。
-
-
PROPAGATION_NESTED:
-
如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)嵌套事務(wù),并且它是當(dāng)前事務(wù)的一個(gè)保存點(diǎn)(savepoint)。如果不存在事務(wù),則行為類似于
PROPAGATION_REQUIRED
。
-
-
-
事務(wù)隔離級(jí)別: 事務(wù)隔離級(jí)別定義了在多個(gè)事務(wù)同時(shí)執(zhí)行時(shí),一個(gè)事務(wù)對(duì)數(shù)據(jù)的修改對(duì)其他事務(wù)的可見(jiàn)性程度。Spring定義了五個(gè)事務(wù)隔離級(jí)別,每個(gè)級(jí)別都有不同的特性和影響:
-
READ_UNCOMMITTED(讀取未提交):
-
特性:允許一個(gè)事務(wù)讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)。
-
可能問(wèn)題:臟讀、不可重復(fù)讀、幻讀。
-
-
READ_COMMITTED(讀取已提交):
-
特性:一個(gè)事務(wù)只能讀取已經(jīng)提交的另一個(gè)事務(wù)的數(shù)據(jù)。
-
可能問(wèn)題:不可重復(fù)讀、幻讀。
-
-
REPEATABLE_READ(可重復(fù)讀):
-
特性:確保事務(wù)可以多次從相同的數(shù)據(jù)集讀取相同的數(shù)據(jù),即使其他事務(wù)正在修改這些數(shù)據(jù)。
-
可能問(wèn)題:幻讀。
-
-
SERIALIZABLE(序列化):
-
特性:事務(wù)是串行執(zhí)行的,所有的事務(wù)都按順序依次執(zhí)行,不允許并發(fā)執(zhí)行。
-
可能問(wèn)題:性能較低,但避免了臟讀、不可重復(fù)讀、幻讀。
-
-
DEFAULT:
-
使用數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別,通常是數(shù)據(jù)庫(kù)的默認(rèn)配置。
-
-
-
事務(wù)回滾規(guī)則: Spring允許你配置哪些異常觸發(fā)事務(wù)回滾,哪些異常不觸發(fā)事務(wù)回滾。
-
分布式事務(wù): Spring提供對(duì)分布式事務(wù)的支持,通過(guò)
JtaTransactionManager
實(shí)現(xiàn)了對(duì)JTA事務(wù)的集成。
PlatformTransactionManager概述
Spring的事務(wù)管理模塊定義了一個(gè)平臺(tái)事務(wù)管理器(PlatformTransactionManager)接口,該接口有多種實(shí)現(xiàn),以適應(yīng)不同的事務(wù)管理機(jī)制。主要的實(shí)現(xiàn)類包括:
-
DataSourceTransactionManager: 用于基于JDBC的事務(wù)管理,適用于關(guān)系型數(shù)據(jù)庫(kù),如MySQL、PostgreSQL等。
-
HibernateTransactionManager: 用于基于Hibernate的事務(wù)管理,適用于使用Hibernate框架的應(yīng)用。
-
JtaTransactionManager: 用于基于Java EE的JTA(Java Transaction API)事務(wù)管理,適用于復(fù)雜的分布式事務(wù)場(chǎng)景。
-
JpaTransactionManager: 用于基于JPA(Java Persistence API)的事務(wù)管理,適用于使用JPA的應(yīng)用。
-
WebLogicJtaTransactionManager: 專門用于WebLogic服務(wù)器上的JTA事務(wù)管理。
實(shí)體類domain層
package domain; ? public class account {private String name;private int gold; ?public account(String name, int gold) {this.name = name;this.gold = gold;} ?public account() {} ?public String getName() {return name;} ?public void setName(String name) {this.name = name;} ?public int getGold() {return gold;} ?public void setGold(int gold) {this.gold = gold;} ?@Overridepublic String toString() {return "account{" +"name='" + name + '\'' +", gold=" + gold +'}';} } ?
Dao層
接口
package dao; ? public interface accountDao {public void out(String man,int money);轉(zhuǎn)出public void in(String man,int money);轉(zhuǎn)入 ? ? } ?
實(shí)現(xiàn)類
package dao.Impl; ? import dao.accountDao; import org.springframework.jdbc.core.JdbcTemplate; ? public class accountImpl implements accountDao {JdbcTemplate jdbcTemplate ; ? ? ? public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { ? ? ? ? this.jdbcTemplate = jdbcTemplate; ? ? } ? ? ? @Override ? ? public void out(String man, int money) { ? ? ? ? jdbcTemplate.update("update account set gold=gold-? where name=?",money,man); ? ? } ? ? ? @Override ? ? public void in(String man,int money) { ? ? ? ? jdbcTemplate.update("update account set gold=gold+? where name=?",money,man); ? ? } ? ? }
service層
接口
package dao; ? public interface accountDao {public void out(String man,int money);public void in(String man,int money); ? ? } ?
實(shí)現(xiàn)類
package service.Impl; ? import dao.accountDao; import service.accountService; ? public class accountServiceImpl implements accountService { ?accountDao accountdao; ?public void setAccountdao(accountDao accountdao) {this.accountdao = accountdao;} ?@Overridepublic void transfer(String outman, String inman, int money) {accountdao.out(outman,money);int i=1/0;accountdao.in(inman,money);} }
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:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置數(shù)據(jù)源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean> <!-- ? 配置事務(wù)管理平臺(tái)--> 這里是基于springjdbc模板實(shí)現(xiàn)的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean> <!-- ? 通知--><tx:advice id="myAdvice" transaction-manager="transaction"><tx:attributes> <!-- ? ? ? ? ? 哪些方法被增強(qiáng)--><tx:method name="transfer"isolation="READ_COMMITTED"propagation="REQUIRED" read-only="false" ? 因?yàn)檗D(zhuǎn)賬肯定需要修改 所以不是只讀/></tx:attributes></tx:advice> <!-- ? 配置事務(wù)的aop織入--><aop:config><aop:advisor advice-ref="myAdvice"pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/></aop:config> </beans>
注解式聲明式事務(wù)管理
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:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置數(shù)據(jù)源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean> <!-- ? 配置事務(wù)管理平臺(tái)--> 這里是基于springjdbc模板實(shí)現(xiàn)的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean>新加<tx:annotation-driven transaction-manager="transaction"></tx:annotation-driven><context:component-scan base-package="org.dao.Impl" /><context:component-scan base-package="org.service.Impl" />組件掃描<aop:aspectj-autoproxy></aop:aspectj-autoproxy> ? 啟用 AspectJ 自動(dòng)代理<context:annotation-config></context:annotation-config>啟用注解驅(qū)動(dòng)的配置,包括支持注解驅(qū)動(dòng)的 AOP。在這個(gè)上下文中,主要是為了支持 @Transactional 注解,它用于啟用聲明式事務(wù)管理。在這個(gè)配置中,它會(huì)啟用對(duì)帶有 @Repository, @Service, @Controller 和其他注解的類的處理,以及其他一些注解相關(guān)的功能。
@Transactional() 等價(jià)于
<!-- 通知--> <tx:advice id="myAdvice" transaction-manager="transaction"> tx:attributes <!-- 哪些方法被增強(qiáng)--> <tx:method name="transfer" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false" 因?yàn)檗D(zhuǎn)賬肯定需要修改 所以不是只讀 /> /tx:attributes /tx:advice <!-- 配置事務(wù)的aop織入--> aop:config <aop:advisor advice-ref="myAdvice" pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/> /aop:config </beans>
總結(jié)
轉(zhuǎn)賬這個(gè)例子 就是主動(dòng)設(shè)計(jì)的錯(cuò)誤是臟讀 如果轉(zhuǎn)賬時(shí)出現(xiàn)網(wǎng)絡(luò) 錯(cuò)誤 一方轉(zhuǎn)出了錢 ,一方?jīng)]有收到錢,此時(shí)是不合理的,所以需要事務(wù)管理