Spring的事务管理(六)

1.事务管理的核心接口

1.1 PlatformTransactionManager管理事务

该接口主要用于管理事务,提供了3个操作事务的方法,具体如下

PlatformTransactionManager接口中管理事务的方法
方法名描述
TransactionStatus getTransaction(TransactionDefinition definition)用于获取事务状态信息
void commit(TransactionStatus status)用于提交事务
void rollback(TransactionStatus status)用于回滚事务

 

 

 

 

 

1.2 TransactionDefinition

TransactionDefinition 接口是事务定义(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法

获取事务相关信息的方法
方法名描述
String getName()获取事务对象名称
int getlsolationLevel()获取事务的隔离级别
int getPropagationBehavior()获取事务的传播行为
int getTimeout获取事务的超时时间
boolean isReadOnly()获取事务是否只读

 

 

 

 

 

 

 

事务的传播行为是指在同一个方法中,不同操作前后所使用的事务,传播行为有很多种,如图所示:

传播行为的种类
属性名称描述
PROPAGATION_REQUIREDREQUIRED表示当前方法必须运行在一个事务环境当中,如果当前方法已处于事务环境中,则可以直接使用该方法;否则会开启一个新事务后执行该方法
PROPAGATION_SUPPORTSSUPPORTS如果当前方法处于事务环境中,则使用当前事务,否则不使用事务
PROPAGATION_MANDATORYMANDATORY表示调用该方法的线程必须处于当前事务环境中,否则将抛异常
PROPAGATION_REQUIRES_NEWREQUIRES_NEW要求方法在新的事务环境中执行.如果当前方法已在事务环境中,则先暂停当前事务,在启动新的事务后执行该方法;如果当前方法不在事务环境中,则会启动一个新的事务后执行方法
PROPAGATION_NOT_SUPPORTEDNOT_SUPPORTED不支持当前事务,总是以非事务状态执行.如果调用该方法的线程处于事务环境中,则先暂停当前事务,然后执行该方法
PROPAGATION_NEVERNEVER不支持当前事务,总是以非事务状态执行.如果调用该方法的线程处于事务环境中,则抛异常
PROPAGATION_NESTEDNESTED即使当前执行的方法处于事务环境中,依然会启动一个新的事务,并且方法在嵌套的事务里执行;即使当前执行的方法不在事务环境中,也会启动一个新事务,然后执行该方法.

 

 

 

 

 

 

 

 

 

 

 

 

 

1.3 TransactionStatus

TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息,该接口中包含6个方法

TransactionStatus接口描述事务的状态信息
方法名描述
void flush()刷新事务
boolean hassavepoint()获取是否存在保存点
boolean is Completed()获取事务是否完成
boolean is NewTransaction()获取是否是新事务
boolean isRollbackOnly()获取是否回滚
void setRollbackOnly()设置事务回滚

 

 

 

 

 

 

 

 

2. 事务管理的方式

  • 编程式事务管理

通过编写代码实现的事务管理,包括定义事务的开始,正常执行后的事务提交和异常时的事务回滚

  • 声明式事务管理

通过AOP技术实现的事务管理,将事务管理作为一个"切面"代码单独编写,然后通过AOP技术将事务管理的"切面"代码织入到业务目标类中

2.1 声明式事务管理

通过两种方式来实现,一种是XML,一种是基于Annotation的方式

2.1.2 基于XML方式的声明式事务

<tx:method>元素的属性
属性名称描述
name该属性为必选属性,它指定了与事务属性相关的方法名.其属性值支持使用通配符,如*、get*、handle*、*Order
propagation用于指定事务的传播行为,默认值是REQUIRED
isolation该属性用于指定事务的隔离级别,其属性值可以为DEFAULT(默认值)、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE
read-only该属性用于指定事务是否只读,其默认值为false
timeout该属性用于指定事务的超时时间,其默认值为-1,即永不超时
rollback-for该属性用于指定触发事务回滚的异常类,在指定多个异常类时,用逗号分隔
no-rollback-for该属性用于指定不触发事务回滚的异常类,在指定多个异常类时,用逗号分隔

 

 

 

 

 

 

 

 

 

 

 

案例:模拟银行转账

(1)导入AOP需要的JAR包

(2)AccountDao接口中,创建转账方法transfer()

(3)AccountDaoImpl

/*
转账
inUser:收款人
outUser:汇款人
money:金额
*/
public void transfer(String outUser,String inUser,Double money){
//收款时,收款用户的余额=现有余额+所汇金额
this.jdbcTemplate.update("update account set balance=balance+?"+"where username=?",money,inUser);
//模拟系统运行时的突发性问题
int i=1/0;
//汇款时,汇款用户的余额=现有金额-所汇金额
this.jdbcTemplate.update("update account set balance=balance-?"
                         +"where username=?",money,outUser);
}

(4)修改applicationContext.xml,添加命名空间并编写事务管理的相关配置代码

​
<!--1.配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url-->
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<!--连接数据库的用户名-->
<property name="username" value="root"/>
<!--连接数据库的密码-->
<property name="password" value="root"/>
</bean>
<!--2.配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--默认必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--3.定义id为accountDao的Bean-->
<bean id="accountDao" class="com.itcast.jdbc.AccountDaoImpl">
<!--将jdbcTemplate注入到AccountDao实例中-->
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--4.事务管理器,依赖于数据源-->
<bean id="transactionManager" class="org.springframework.jdbc.dataSource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--name:*表示任意方法名称-->
​<tx:method name="*" propagation="REQUIRED"
                  isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式-->
<aop:config>
<!--切入点-->
<aop:pointcut expression="execution(* com.itcast.jdbc.*.*(..))" 
                    id="txPointCut"/>
<!--切面:将切入点与通知整合-->
<aop:advisor advice-ref="tx:Advice" pointcut-ref="txPointCut"/>
</aop:config>

(5)测试类TransactionTest

​//测试类
public class TransactionTest{
@Test
public  void xmlTest(){
//加载配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//获取AccountDao实例
AccountDao accountDao=(AccountDao )applicationContext.getBean("accountDao");
//调用实例中的转账方法
accountDao.transfer("Jack","Rose",100.0);
System.out.println("转账成功");
}
}

​

2.1.3 基于Annotation方式的声明式事务

两个步骤:

  • 在Spring容器中注册事务注解驱动,其代码如下
<tx:annotation-driven transaction-manager="transactionManager"/>
  • 在需要使用事务的SpringBean类或者Bean类的方法上添加注解@Transactional,如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效
@Transactional注解的参数及其描述
参数名称描述
value用于指定需要使用的事务管理器,默认为"",别名为transactionManager
transactionManager指定事务的限定符值,可用于确定目标事务管理器,匹配特定的限定值(或者Bean的name值),默认为"",其别名为value
isolation用于指定事务的隔离级别,默认为Isolation.DEFAULT(即底层事务的隔离级别)
noRollbackFor用于指定遇到特定异常时强制不回滚事务
noRollbackForClassName用于指定遇到特定的多个异常时强制不回滚事务.其属性值可以指定多个异常类名
propagation用于指定事务的传播行为,默认为Propagation.REQUIRED
read-only用于指定事务是否只读,默认为false
rollbackFor用于指定遇到特定异常时强制回滚事务
rollbackForClassName用于指定遇到特定的多个异常时强制回滚事务.其属性值可以指定多个异常类名
timeout用于指定事务的超时时长,默认为TransactionDefinition.TIMEOUT_DEFAULT(即底层事务系统的默认时间)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(1)创建一个Spring的配置文件applicationContext-annotation.xml,在该文件中声明事务管理器等配置信息

​
​
<!--1.配置数据源-->
<bean id="dataSource" 
<!--1.配置数据源-->
<bean id="datasource"class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<!--数据库驱动-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url-->
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<!--连接数据库的用户名-->
<property name="username" value="root"/>
<!--连接数据库的密码-->
<property name="password" value="root"/>
</bean>
<!--2.配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--默认必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
​
<!--3.定义id为accountDao的Bean-->
<bean id="accountDao" class="com.itcast.jdbc.AccountDaoImpl">
<!--将jdbcTemplate注入到accountDao实例中-->
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--4.事务管理器,依赖于数据源-->
<bean id="transactionManager" class="org.springframework.jdbc.core.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">
</bean>
<!--5.注册事务管理器驱动-->
<tx:annotation-driven transaction-Manager="transactionManager"/>
​
​

​

(2)在AccountDaoImpl类的transfer()方法上添加事务注解

​
/*
转账
inUser:收款人
outUser:汇款人
money:金额
*/
@Transactional(propagation=Propagation.REQUIRED,
               isolation=Isolation.DEFAULT,readOnly=false)
public void transfer(String outUser,String inUser,Double money){
//收款时,收款用户的余额=现有余额+所汇金额
this.jdbcTemplate.update("update account set balance=balance+?"+"where username=?",money,inUser);
//模拟系统运行时的突发性问题
int i=1/0;
//汇款时,汇款用户的余额=现有金额-所汇金额
this.jdbcTemplate.update("update account set balance=balance-?"
                         +"where username=?",money,outUser);
}

​

(3)创建测试方法annotationTest()

​
​//测试类
@Test
public void annotationTest{
//加载配置文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
//获取AccountDao实例
AccountDao accountDao=(AccountDao )applicationContext.getBean("accountDao");
//调用实例中的转账方法
accountDao.transfer("Jack","Rose",100.0);
System.out.println("转账成功");
}

​

​

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值