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>
相关文章
|
7天前
|
Java 数据库连接 数据库
spring复习05,spring整合mybatis,声明式事务
这篇文章详细介绍了如何在Spring框架中整合MyBatis以及如何配置声明式事务。主要内容包括:在Maven项目中添加依赖、创建实体类和Mapper接口、配置MyBatis核心配置文件和映射文件、配置数据源、创建sqlSessionFactory和sqlSessionTemplate、实现Mapper接口、配置声明式事务以及测试使用。此外,还解释了声明式事务的传播行为、隔离级别、只读提示和事务超时期间等概念。
spring复习05,spring整合mybatis,声明式事务
|
9天前
|
Java 测试技术 数据库
Spring事务传播机制(最全示例)
在使用Spring框架进行开发时,`service`层的方法通常带有事务。本文详细探讨了Spring事务在多个方法间的传播机制,主要包括7种传播类型:`REQUIRED`、`SUPPORTS`、`MANDATORY`、`REQUIRES_NEW`、`NOT_SUPPORTED`、`NEVER` 和 `NESTED`。通过示例代码和数据库插入测试,逐一展示了每种类型的运作方式。例如,`REQUIRED`表示如果当前存在事务则加入该事务,否则创建新事务;`SUPPORTS`表示如果当前存在事务则加入,否则以非事务方式执行;`MANDATORY`表示必须在现有事务中运行,否则抛出异常;
42 4
Spring事务传播机制(最全示例)
|
5天前
|
Java Spring
Spring 事务传播机制是什么?
Spring 事务传播机制是什么?
14 4
|
10天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
527 8
|
7天前
|
XML 前端开发 Java
控制spring框架注解介绍
控制spring框架注解介绍
|
7天前
|
存储 NoSQL Java
Spring Session框架
Spring Session 是一个用于在分布式环境中管理会话的框架,旨在解决传统基于 Servlet 容器的会话管理在集群和云环境中的局限性。它通过将用户会话数据存储在外部介质(如数据库或 Redis)中,实现了会话数据的跨服务器共享,提高了应用的可扩展性和性能。Spring Session 提供了无缝集成 Spring 框架的 API,支持会话过期策略、并发控制等功能,使开发者能够轻松实现高可用的会话管理。
Spring Session框架
|
14天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
SQL Java 数据库
第一季:8spring支持的常用数据库事务传播属性和事务隔离级别【Java面试题】
第一季:8spring支持的常用数据库事务传播属性和事务隔离级别【Java面试题】
132 0
|
2月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
4月前
|
Java 开发者 Spring
spring事务类型,事务传递,隔离级别?
spring事务类型,事务传递,隔离级别?
下一篇
无影云桌面