Spring的事务管理

5.1 Spring事务管理概述

Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。
5.1.1 事务管理的核心接口
在Spring的所有JAR包中包含一个名为Spring-tx-4.3.6.RELEASE的JAR包,该包就是Spring提供的用于事务管理的依赖包。在该JAR包的org.Springframework.transaction包中有3个接口文件:PlatformTransactionManager、TransactionDefinition和TransactionStatus。
1.PlatformTransactionManager
PlatformTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。该接口中提供了3个事务操作的方法,具体如下。
•  TransactionStatus getTransaction(TransactionDefinition definition):用于获取事务状态信息。该方法会根据TransactionDefinition参数返回一个TransactionStatus对象。TransactionStatus对象表示一个事务,被关联在当前执行的线程上。
•  void commit(TransactionStatus status):用于提交事务。
•  void rollback(TransactionStatus status):用于回滚事务。
PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,它只需要事务管理提供上面的3个方法,但具体如何管理事务则由它的实现类来完成。
PlatformTransactionManager接口有许多不同的实现类,常见的几个实现类如下。
•  org.springframework.jdbc.datasource.DataSourceTransactionManager:用于配置JDBC数据源的事务管理器。
•  org.springframework.orm.Hibernate4.HibernateTransactionManager:用于配置Hibernate的事务管理器。
•  org.springframework.transaction.jta.JtaTransactionManager:用于配置全局事务管理器。
当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可。
2.TransactionDefinition
TransactionDefinition接口是事务定义(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法,具体如下:
•  string getName():获取事务对象名称。
•  int getlsolationLeve():获取事务的隔离级别。
•  int getPropagationBehavior():获取事务的传播行为。
•  int setTimeout():获取事务的超时时间。
•  boolean isReadOnly():获取事务是否只读。
上述方法中,事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为有很多种,具体如表5.1所示。
表5.1 传播行为的类
在这里插入图片描述
在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务。通常情况下,数据的查询不会影响原数据的改变,所以不需要进行事务管理,而对于数据的插入、更新和删除操作,必须进行事务管理。如果没有指定事务的传播行为,Spring默认传播行为是REQUIRED。
3.TransactionStatus
TransactionStatus接口是事务的状态,描述了某一时间点上事务的状态信息。该接口中包含6个方法,具体如下:
•  void flush():刷新事务。
•  boolean hasSavepoint():获取是否存在保存点。
•  boolean isCompleted():获取事务是否完成。
•  boolean isNewTransaction():获取是否是新事务。
•  boolean isRollbackOnly():获取是否回滚。
•  void setRollbackOnly():设置事务回滚。

5.1.2 事务管理的方式

Spring中的事务管理分为两种方式:一种是传统的编程序事务管理;另一种是声明式事务管理。
•  编程序事务管理:通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚。
•  声明式事务管理:通过AOP技术实现的事务管理,其主要思想是将事务管理作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”代码植入业务目标类中。
声明式事务管理最大的优点在于开发者无须通过编程的方式来管理事务,只需在配置文件中进行相关的事务规则声明,就可以将事务规则应用到业务逻辑中。这使得开发人员可以更加专注于核心业务逻辑代码的编写,在一定程度上减少了工作量,提高了开发效率。所以在实际开发中,通常都推荐使用声明式事务管理。

5.2 声明式事务管理

Spring的声明式事务管理可以通过两种方式来实现:一种是基于XML的方式;另一种是基于Annotation的方式。本节将对这两种声明式事务管理方式进行详细讲解。
5.2.1 基于XML方式的声明式事务
基于XML方式的声明式事务管理是通过在配置文件中配置事务规则的相关声明来实现的。
Spring 2.0以后,提供了tx命名空间来配置事务,tx命名空间下提供了tx:advice元素来配置事务的通知(增强处理)。当使用tx:advice元素配置了事务的增强处理后,就可以通过编写的AOP配置让Spring自动对目标生成代理。
配置tx:advice元素时,通常需要指定id和transaction-manager属性,其中id属性是配置文件中的唯一标识,transaction-manager属性用于指定事务管理器。除此之外,还需要配置一个tx:attributes子元素,该子元素可通过配置多个tx:method子元素来配置执行事务的细节。
关于tx:method元素的属性描述如表5.2所示。
表5.2 tx:method元素的属性


了解了如何在XML文件中配置事务后,接下来通过一个案例来演示如何通过XML方式实现Spring的声明式事务管理。
【示例5-1】本案例以第4章的项目代码和数据表为基础模拟一个会员赠送积分的功能,要求在赠送积分时通过Spring对事务进行控制,其具体实现步骤如下。
步骤01 在Eclipse中创建一个名为chapter05的Web项目,在项目的lib目录中导入chapter04项目中的所有JAR包,并将AOP所需JAR包也导入lib目录中。导入后的目录如图5.1所示。
在这里插入图片描述

图5.1 项目所需的JAR包
步骤02 在MySQL中,修改数据库db_spring中的数据表user,增加字段jf(积分),如图5.2所示。同时,为了后续操作数据表方便,在数据表user中设置所有用户的初始积分为1000,如图5.3所示。

图5.2 修改数据表
在这里插入图片描述

图5.3 设置jf(积分)初始值
在这里插入图片描述

步骤03 将chapter04项目中的代码和配置文件复制到chapter05项目的src目录下。接下来,在User类中增加jf(积分)成员和对应的getter()和setter()方法,如下所示。
在这里插入图片描述

在UserDao接口中创建一个赠送积分的方法transfer(),其代码如下所示。
在这里插入图片描述

在实现类UserDaoImpl中实现transfer()方法,编辑后的代码如下所示。
在这里插入图片描述

在上述代码中,使用了两个update()方法对user表中的数据执行接收积分和赠送积分的更新操作。在两个操作之间添加了一行代码“int i=1/0;”来模拟系统运行时的突发性问题。如果没有事务控制,那么在transfer()方法执行后,接收积分用户的积分会增加,而赠送积分用户的积分会因为系统出现问题而不变,这显然是有问题的;如果增加了事务控制,那么在transfer()方法操作执行后,接收积分用户的积分和赠送积分用户的积分在问题出现前后都应该保持不变。
步骤04 修改配置文件applicationContext.xml,添加命名空间并编写事务管理的相关配置代码,如文件5.1所示。
文件5.1 applicationContext.xml




在文件5.1中定义了id为transactionManager的事务管理器,接下来通过编写的通知来声明事务,最后通过声明AOP的方式让Spring自动生成代理。
步骤05 在com.ssm.jdbc包中创建测试类TransactionTest,并在类中编写测试方法xmlTest(),如文件5.2所示。
文件5.2 TransactionTest.java
在这里插入图片描述

在文件5.2中获取UserDao实例后,调用了实例中的赠送积分方法,由zhangsan向lisi转入100积分。如果事务代码起作用,那么在整个赠送积分方法执行完毕后,zhangsan和lisi的积分应该都是原来的值。
执行完文件5.2中的测试方法后,JUnit控制台的显示结果如图5.4所示。从中可以看到,JUnit控制台中报出了“/ y zero”的算术异常信息。
在执行赠送积分操作后,查看user表中的数据,依然如图5.3所示,即zhangsan和lisi的积分没有发生变化,这说明Spring中的事务管理配置已经生效。
在这里插入图片描述

图5.4 运行结果
5.2.2 基于Annotation方式的声明式事务
Spring的声明式事务管理还可以通过Annotation(注解)的方式来实现。这种方式的使用非常简单,开发者只需做两件事情:
(1)在Spring容器中注册事务注解驱动,其代码如下:

<tx:annotation-driven transaction-managers="transactionManager"/>

(2)在需要使用事务的Spring Bean类或者Bean类的方法上添加注解@Transactional。如果将注解添加在Bean类上,就表示事务的设置对整个Bean类的所有方法都起作用;如果将注解添加在Bean类中的某个方法上,就表示事务的设置只对该方法有效。
使用@Transactional注解时,可以通过其参数配置事务详情。@Transactional注解可配置的参数信息如表5.3所示。
表5.3 @Transactional注解的参数及其描述


从表5.3可以看出,@Transactional注解与tx:method元素中的事务属性基本是对应的,并且其含义也基本相似。
【示例5-2】为了让读者更加清楚地掌握@Transactiona注解的使用,接下来对5.2.1小节的案例进行修改,以Annotation方式实现项目中的事务管理,具体实现步骤如下。
步骤01 在src目录下创建一个Spring配置文件applicationContext-annotation.xml,在该文件中声明事务管理器等配置信息,如文件5.3所示。
文件5.3 applicationContext-annotation.xml


与基于XML方式的配置文件相比,文件5.3通过注册事务管理器驱动替换了文件5.1中的编写通知和编写aop的配置,这样大大减少了配置文件中的代码量。
注意
如果案例中使用了注解式开发,就需要在配置文件中开启注解处理器,指定扫描哪些包下的注解。这里没有开启注解处理器是因为在配置文件中已经配置了UserDaoImpl类的Bean,而@Transactional注解就配置在该Bean类中,所以可以直接生效。
步骤02 在UserDaoImpl类的transfer()方法上添加事务注解,添加后的代码如下所示。
在这里插入图片描述

上述方法已经添加了@Transactional注解,并且使用注解的参数配置了事务详情,各个参数之间要用英文逗号“,”进行分隔。
注意
在实际开发中,事务的配置信息通常是在Spring的配置文件中完成的,而在业务层类上只需使用@Transactional注解即可,不需要配置@Transactional注解的属性。
步骤03 在TransactionTest类中创建测试方法annotationTest(),编辑后的代码如下所示。
在这里插入图片描述

从上述代码可以看出,与XML方式的测试方法相比,该方法只是对配置文件的名称进行了修改。程序执行后,会出现与XML方式同样的执行结果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值