Spring框架:第八章:声明式事务

简介: Spring框架:第八章:声明式事务

10、声明式事务

事务分为声明式和编程式两种:

声明式事务:声明式事务是指通过注解的形式对事务的各种特性进行控制和管理。

编码式(编程式)事务:指的是通过编码的方式实现事务的声明。

11.1、编码方式实现事务:

11.2、声明式事务环境搭建

11.2.1、准备测试数据库

##创建tx数据库
drop database if exists `tx`;
CREATE database `tx`;
##切换tx数据库
USE `tx`;
##删除用户表
DROP TABLE IF EXISTS `user`;
##创建用户表
CREATE TABLE `user` (
  `id` int primary key auto_increment,  
  `username` varchar(50) NOT NULL,
  `money` int(11) DEFAULT NULL
);
##插入数据
insert  into `user`(`username`,`money`) values ('张三',1000),('李四',1000);
##删除图书表
drop table if exists `book`;
##创建图书表
create table `book`(
    `id` int primary key auto_increment,
    `name` varchar(500) not null,
    `stock` int
);
##插入数据
insert into book(`name`,`stock`) values('java编程思想',100),('C++编程思想',100);
##查看数据
select * from book;
select * from user;

11.2.2、创建一个Java工程,导入Jar包

导入jar包:

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
druid-1.1.9.jar
mysql-connector-java-5.1.37-bin.jar
spring-aop-4.3.18.RELEASE.jar
spring-beans-4.3.18.RELEASE.jar
spring-context-4.3.18.RELEASE.jar
spring-core-4.3.18.RELEASE.jar
spring-expression-4.3.18.RELEASE.jar
spring-jdbc-4.3.18.RELEASE.jar
spring-orm-4.3.18.RELEASE.jar
spring-test-4.3.18.RELEASE.jar
spring-tx-4.3.18.RELEASE.jar

配置jdbc.properties属性配置文件:

url=jdbc:mysql://localhost:3306/tx
user=root
password=root
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10

配置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: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-4.3.xsd">
  <!-- 配置包扫描 -->
  <context:component-scan base-package="com"></context:component-scan>
  <!-- 加载jdbc.properties属性配置文件 -->
  <context:property-placeholder location="classpath:jdbc.properties"/>
  <!-- 配置数据库连接池 -->
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="username" value="${user}"/>
    <property name="password" value="${password}"/>
    <property name="url" value="${url}"/>
    <property name="driverClassName" value="${driverClassName}"/>
    <property name="initialSize" value="${initialSize}" />
    <property name="maxActive" value="${maxActive}"/>
  </bean>
  <!-- 配置jdbcTemplate工具类 -->
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
  </bean> 
</beans>

11.3、测试Service的默认事务

实验1:测试service服务层的默认事务

@Repository
public class BookDao {
  @Autowired
  JdbcTemplate jdbcTemplate;      
  public void updateBook() {
    jdbcTemplate.update("update book set name = '图书表被修改了'");
  }     
}
@Repository
public class UserDao {
  @Autowired
  JdbcTemplate jdbcTemplate;      
  public void updateUser() {
    jdbcTemplate.update("update user set username = '用户表被修改了'");
  }     
}
@Service
public class TransactionService {
  @Autowired
  private UserDao userDao;    
  @Autowired
  private BookDao bookDao;      
  public void multiUpdate() {
    userDao.updateUser();
    bookDao.updateBook();
  } 
}

异常的演示

@Service
public class TransactionService {
  @Autowired
  private UserDao userDao;
  @Autowired
  private BookDao bookDao;
  public void multiUpdate() {
    userDao.updateUser();
    int i = 12 / 0 ;
    bookDao.updateBook();
  }
}

Spring事务引入的分析------PlatformTransactionManager类简单介绍

事务管理器实现类

由于我们使用的是数据库连接池访问数据库,所以事务管理器使用的是DataSourceTransactionManager。

11.4、使用Spring的注解声明事务管制

实验2:测试Spring的声明式事务

1、在需要事务的方法上加入注解。

/**
 * @Transactional 表示当前方法有事务
 */
@Transactional
public void multiUpdate() {
  userDao.updateUser();
  int i = 12 / 0 ;
  bookDao.updateBook();
}

2、配置事务管理器驱动

<!-- 事务管理器 -->
<bean id="transactionManager" 
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>  
</bean>

3、配置事务注解驱动

<!-- 
  <tx:annotation-driven/> 开启注解的事务驱动 启用代理
    transaction-manager="transactionManager" 配置事务管理器
    如果事务管理器的id值是transactionManager,则事务管理器属性可以省略
 -->
<tx:annotation-driven />

11.5、noRollbackFor和noRollbackForClassName测试不回滚的异常

实验3:noRollbackFor和noRollbackForClassName测试不回滚的异常

  /**
   * @Transactional 表示当前方法有事务<br/>
   *  默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
   * noRollbackFor=java.lang.ArithmeticException.class 表示算术异常不回滚事务<br/>
   * noRollbackFor= {java.lang.ArithmeticException.class,java.lang.NullPointerException.class}<br/>
   * noRollbackForClassName="java.lang.NullPointerException" 设置哪些类名的异常不回滚事务<br/>
   */
  @Transactional(noRollbackForClassName="java.lang.NullPointerException")
  public void multiUpdate() {
    userDao.updateUser();
//    int i = 12 / 0 ;
    Object object = null;
    System.out.println( object.toString() );
    bookDao.updateBook();
  }

11.6、自定义设置回滚异常

实验5:rollbackFor和rollbackForClassName回滚的异常

/**
 * @throws FileNotFoundException 
 * @Transactional 表示当前方法有事务<br/>
 *  默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
 * rollbackFor=FileNotFoundException.class 设置当抛出FileNotFoundException异常时,回滚事务<br/>
 * rollbackForClassName="java.io.FileNotFoundException" 设置当抛出FileNotFoundException异常时就会回滚事务<br/>
 */
@Transactional(rollbackForClassName="java.io.FileNotFoundException")
public void multiUpdate() throws FileNotFoundException {
  userDao.updateUser();
  int i = 12 ;
  if (i == 12) {
    throw new FileNotFoundException();
  }
  bookDao.updateBook();
}

11.7、事务的只读属性

实验4:测试readOnly只读属性

/**
 * @throws FileNotFoundException 
 * @Transactional 表示当前方法有事务<br/>
 *  默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
 * readOnly=false 表示当前方法可以执行读操作。也可以执行写操作(指的是sql语句)。<br/>
 * 修改、添加、删除、是写操作、select查询语句是读操作。<br/>
 * readOnly=true 表示当前方法只能执行查询操作<br/>
 */
@Transactional(readOnly=true)
public void multiUpdate() throws FileNotFoundException {
  userDao.updateUser();
  bookDao.updateBook();
}

只读的方法执行修改语句报错。

11.8、事务超时属性timeout(秒为单位)

/**
 * @throws FileNotFoundException 
 * @Transactional 表示当前方法有事务<br/>
 *  默认情况下。RuntimeException运行时异常和运行时子异常。都会回滚事务<br/>
 * timeout=3 表示3秒之后就超时,不允许再执行sql语句
 */
@Transactional(timeout=3)
public void multiUpdate() throws FileNotFoundException {
  userDao.updateUser();
  try {
    Thread.sleep(5000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  bookDao.updateBook();
}

当执行时间超过指定的秒钟后就会超时:

11.10、事务的传播特性propagation

什么是事务的传播行为:

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

事务的传播行为可以由传播属性指定。Spring定义了7种类传播行为。

事务的传播特性,有以下几种类型:

11.11、注解演示事物传播特性

UserService

BookService

TransactionService

实验1:大小事务传播特性都是REQUIRED

  @Transactional(propagation = Propagation.REQUIRED)
  public void multlTransaction() {
  @Transactional(propagation = Propagation.REQUIRED)
  public void updateBook() {
@Transactional(propagation=Propagation.REQUIRED)
public void updateUser() {

实验2:大小事务传播特性都是REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()

实验3:大事务是REQUIRED,小事务都是REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()

实验4:大事务是REQUIRED,小1REQUIRED,小2REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRED)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser()

实验5:大事务是REQUIRED,小1REQUIRES_NEW,小2REQUIRED

@Transactional(propagation = Propagation.REQUIRED)
public void multiUpdate()
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateBook()
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser()

12、xml配置式事务声明

复制原来注解事务管理的工程。去掉里面所有@Transactional的注解。

<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
  <!-- 配置包扫描 -->
  <context:component-scan base-package="com"></context:component-scan>
  <!-- 加载jdbc.properties属性配置文件 -->
  <context:property-placeholder location="classpath:jdbc.properties"/>
  <!-- 配置数据库连接池 -->
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="username" value="${user}"/>
    <property name="password" value="${password}"/>
    <property name="url" value="${url}"/>
    <property name="driverClassName" value="${driverClassName}"/>
    <property name="initialSize" value="${initialSize}" />
    <property name="maxActive" value="${maxActive}"/>
  </bean>
  <!-- 配置jdbcTemplate工具类 -->
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
  </bean>
  <!-- 
    配置事务管理器
   -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>
  <!-- 
    配置事务属性
   -->
  <tx:advice id="tx_advice" transaction-manager="transactionManager">
    <tx:attributes>
      <!-- 
        tx:method 给某个方法配置事务属性
          name就是方法的匹配规则(方法名)
          精确匹配
       -->
      <tx:method name="updateUser" propagation="REQUIRED"/>
      <!-- 
        给save*方法配置事务属性
          name="save*"  表示给save字符串打头的方法配置事务属性
       -->
      <tx:method name="save*" propagation="REQUIRED"/>
      <tx:method name="update*" propagation="REQUIRES_NEW"/>
      <tx:method name="delete*" propagation="REQUIRED"/>
      <tx:method name="multlTransaction" propagation="REQUIRES_NEW"/>
      <!-- 
        <tx:method name="*"/> 所有的方法
          read-only="true" 剩下的方法都是查询操作。
       -->
      <tx:method name="*" read-only="true"/>
    </tx:attributes>
  </tx:advice>
  <aop:config>
    <!-- 
      aop:advisor 配置通知
     -->
    <aop:advisor advice-ref="tx_advice" 
      pointcut="execution(public * com.service..*Service*.*(..))"/>
  </aop:config>
</beans>
相关文章
|
23天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
15天前
|
Java 开发者 Spring
Spring高手之路24——事务类型及传播行为实战指南
本篇文章深入探讨了Spring中的事务管理,特别是事务传播行为(如REQUIRES_NEW和NESTED)的应用与区别。通过详实的示例和优化的时序图,全面解析如何在实际项目中使用这些高级事务控制技巧,以提升开发者的Spring事务管理能力。
31 1
Spring高手之路24——事务类型及传播行为实战指南
|
27天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
43 1
Spring 框架:Java 开发者的春天
|
9天前
|
XML Java 数据库连接
Spring中的事务是如何实现的
Spring中的事务管理机制通过一系列强大的功能和灵活的配置选项,为开发者提供了高效且可靠的事务处理手段。无论是通过注解还是AOP配置,Spring都能轻松实现复杂的事务管理需求。掌握这些工具和最佳实践,能
15 3
|
20天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
37 2
|
19天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
77 1
|
27天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
Java Spring
spring框架之AOP模块(面向切面),附带通知类型---超详细介绍
spring框架之AOP模块(面向切面),附带通知类型---超详细介绍
123 0
|
缓存 监控 Java
Spring框架之AOP(面向切面编程)
Spring框架之AOP(面向切面编程)
58 0
|
4月前
|
分布式计算 Java MaxCompute
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
详解 Java 限流接口实现问题之在Spring框架中使用AOP来实现基于注解的限流问题如何解决
下一篇
无影云桌面