Spring系列第44篇:详解spring声明式事务(@Transactional)

声明式事务注解方式5个步骤


1、启用Spring的注释驱动事务管理功能

在spring配置类上加上@EnableTransactionManagement注解

@EnableTransactionManagement

public class MainConfig4 {

}

简要介绍一下原理:当spring容器启动的时候,发现有@EnableTransactionManagement注解,此时会拦截所有bean的创建,扫描看一下bean上是否有@Transaction注解(类、或者父类、或者接口、或者方法中有这个注解都可以),如果有这个注解,spring会通过aop的方式给bean生成代理对象,代理对象中会增加一个拦截器,拦截器会拦截bean中public方法执行,会在方法执行之前启动事务,方法执行完毕之后提交或者回滚事务。稍后会专门有一篇文章带大家看这块的源码。

如果有兴趣的可以自己先去读一下源码,主要是下面这个这方法会

org.springframework.transaction.interceptor.TransactionInterceptor#invoke

再来看看 EnableTransactionManagement 的源码

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Import(TransactionManagementConfigurationSelector.class)

public @interface EnableTransactionManagement {

/**

* spring是通过aop的方式对bean创建代理对象来实现事务管理的

* 创建代理对象有2种方式,jdk动态代理和cglib代理

  • proxyTargetClass:为true的时候,就是强制使用cglib来创建代理

*/

boolean proxyTargetClass() default false;

/**

* 用来指定事务拦截器的顺序

* 我们知道一个方法上可以添加很多拦截器,拦截器是可以指定顺序的

* 比如你可以自定义一些拦截器,放在事务拦截器之前或者之后执行,就可以通过order来控制

*/

int order() default Ordered.LOWEST_PRECEDENCE;

}

2、定义事务管理器

事务交给spring管理,那么你肯定要创建一个或者多个事务管理者,有这些管理者来管理具体的事务,比如启动事务、提交事务、回滚事务,这些都是管理者来负责的。

spring中使用PlatformTransactionManager这个接口来表示事务管理者。

PlatformTransactionManager多个实现类,用来应对不同的环境

JpaTransactionManager:如果你用jpa来操作db,那么需要用这个管理器来帮你控制事务。

DataSourceTransactionManager:如果你用是指定数据源的方式,比如操作数据库用的是:JdbcTemplate、mybatis、ibatis,那么需要用这个管理器来帮你控制事务。

HibernateTransactionManager:如果你用hibernate来操作db,那么需要用这个管理器来帮你控制事务。

JtaTransactionManager:如果你用的是java中的jta来操作db,这种通常是分布式事务,此时需要用这种管理器来控制事务。

比如:我们用的是mybatis或者jdbctemplate,那么通过下面方式定义一个事务管理器。

@Bean

public PlatformTransactionManager transactionManager(DataSource dataSource) {

return new DataSourceTransactionManager(dataSource);

}

3、需使用事务的目标上加@Transaction注解

  • @Transaction放在接口上,那么接口的实现类中所有public都被spring自动加上事务

  • @Transaction放在类上,那么当前类以及其下无限级子类中所有pubilc方法将被spring自动加上事务

  • @Transaction放在public方法上,那么该方法将被spring自动加上事务

  • 注意:@Transaction只对public方法有效

下面我们看一下@Transactional源码:

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Transactional {

/**

* 指定事务管理器的bean名称,如果容器中有多事务管理器PlatformTransactionManager,

* 那么你得告诉spring,当前配置需要使用哪个事务管理器

*/

@AliasFor(“transactionManager”)

String value() default “”;

/**

* 同value,value和transactionManager选配一个就行,也可以为空,如果为空,默认会从容器中按照类型查找一个事务管理器bean

*/

@AliasFor(“value”)

String transactionManager() default “”;

/**

* 事务的传播属性

*/

Propagation propagation() default Propagation.REQUIRED;

/**

* 事务的隔离级别,就是制定数据库的隔离级别,数据库隔离级别大家知道么?不知道的可以去补一下

*/

Isolation isolation() default Isolation.DEFAULT;

/**

* 事务执行的超时时间(秒),执行一个方法,比如有问题,那我不可能等你一天吧,可能最多我只能等你10秒

* 10秒后,还没有执行完毕,就弹出一个超时异常吧

*/

int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

/**

* 是否是只读事务,比如某个方法中只有查询操作,我们可以指定事务是只读的

* 设置了这个参数,可能数据库会做一些性能优化,提升查询速度

*/

boolean readOnly() default false;

/**

* 定义零(0)个或更多异常类,这些异常类必须是Throwable的子类,当方法抛出这些异常及其子类异常的时候,spring会让事务回滚

* 如果不配做,那么默认会在 RuntimeException 或者 Error 情况下,事务才会回滚

*/

Class<? extends Throwable>[] rollbackFor() default {};

/**

* 和 rollbackFor 作用一样,只是这个地方使用的是类名

*/

String[] rollbackForClassName() default {};

/**

* 定义零(0)个或更多异常类,这些异常类必须是Throwable的子类,当方法抛出这些异常的时候,事务不会回滚

*/

Class<? extends Throwable>[] noRollbackFor() default {};

/**

* 和 noRollbackFor 作用一样,只是这个地方使用的是类名

*/

String[] noRollbackForClassName() default {};

}

参数介绍

| 参数 | 描述 |

| — | — |

| value | 指定事务管理器的bean名称,如果容器中有多事务管理器PlatformTransactionManager,那么你得告诉spring,当前配置需要使用哪个事务管理器 |

| transactionManager | 同value,value和transactionManager选配一个就行,也可以为空,如果为空,默认会从容器中按照类型查找一个事务管理器bean |

| propagation | 事务的传播属性,下篇文章详细介绍 |

| isolation | 事务的隔离级别,就是制定数据库的隔离级别,数据库隔离级别大家知道么?不知道的可以去补一下 |

| timeout | 事务执行的超时时间(秒),执行一个方法,比如有问题,那我不可能等你一天吧,可能最多我只能等你10秒 10秒后,还没有执行完毕,就弹出一个超时异常吧 |

| readOnly | 是否是只读事务,比如某个方法中只有查询操作,我们可以指定事务是只读的 设置了这个参数,可能数据库会做一些性能优化,提升查询速度 |

| rollbackFor | 定义零(0)个或更多异常类,这些异常类必须是Throwable的子类,当方法抛出这些异常及其子类异常的时候,spring会让事务回滚 如果不配做,那么默认会在 RuntimeException 或者 Error 情况下,事务才会回滚 |

| rollbackForClassName | 同 rollbackFor,只是这个地方使用的是类名 |

| noRollbackFor | 定义零(0)个或更多异常类,这些异常类必须是Throwable的子类,当方法抛出这些异常的时候,事务不会回滚 |

| noRollbackForClassName | 同 noRollbackFor,只是这个地方使用的是类名 |

4、执行db业务操作

在@Transaction标注类或者目标方法上执行业务操作,此时这些方法会自动被spring进行事务管理。

如,下面的insertBatch操作,先删除数据,然后批量插入数据,方法上加上了@Transactional注解,此时这个方法会自动受spring事务控制,要么都成功,要么都失败。

@Component

public class UserService {

@Autowired

private JdbcTemplate jdbcTemplate;

//先清空表中数据,然后批量插入数据,要么都成功要么都失败

@Transactional

public void insertBatch(String… names) {

jdbcTemplate.update(“truncate table t_user”);

for (String name : names) {

jdbcTemplate.update(“INSERT INTO t_user(name) VALUES (?)”, name);

}

}

}

5、启动spring容器,使用bean执行业务操作

@Test

public void test1() {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.register(MainConfig4.class);

context.refresh();

UserService userService = context.getBean(UserService.class);

userService.insertBatch(“java高并发系列”, “mysql系列”, “maven系列”, “mybatis系列”);

}

案例1


准备数据库

DROP DATABASE IF EXISTS javacode2018;

CREATE DATABASE if NOT EXISTS javacode2018;

USE javacode2018;

DROP TABLE IF EXISTS t_user;

CREATE TABLE t_user(

id int PRIMARY KEY AUTO_INCREMENT,

name varchar(256) NOT NULL DEFAULT ‘’ COMMENT ‘姓名’

);

spring配置类

package com.javacode2018.tx.demo4;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.annotation.EnableTransactionManagement;

import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;

@EnableTransactionManagement //@1

@Configuration

@ComponentScan

public class MainConfig4 {

//定义一个数据源

@Bean

public DataSource dataSource() {

org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();

dataSource.setDriverClassName(“com.mysql.jdbc.Driver”);

dataSource.setUrl(“jdbc:mysql://localhost:3306/javacode2018?characterEncoding=UTF-8”);

dataSource.setUsername(“root”);

dataSource.setPassword(“root123”);

dataSource.setInitialSize(5);

return dataSource;

}

//定义一个JdbcTemplate,用来执行db操作

@Bean

public JdbcTemplate jdbcTemplate(DataSource dataSource) {

return new JdbcTemplate(dataSource);

}

//定义我一个事物管理器

@Bean

public PlatformTransactionManager transactionManager(DataSource dataSource) { //@2

return new DataSourceTransactionManager(dataSource);

}

}

@1:使用@EnableTransactionManagement注解开启spring事务管理

@2:定义事务管理器

来个业务类

package com.javacode2018.tx.demo4;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import java.util.Map;

@Component

public class UserService {

@Autowired

private JdbcTemplate jdbcTemplate;

//先清空表中数据,然后批量插入数据,要么都成功要么都失败

@Transactional //@1

public int insertBatch(String… names) {

int result = 0;

jdbcTemplate.update(“truncate table t_user”);

for (String name : names) {

result += jdbcTemplate.update(“INSERT INTO t_user(name) VALUES (?)”, name);

}

return result;

}

//获取所有用户信息

public List<Map<String, Object>> userList() {

return jdbcTemplate.queryForList(“SELECT * FROM t_user”);

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

6110)]
[外链图片转存中…(img-2HocfpfA-1711997466110)]
[外链图片转存中…(img-TObGuPxt-1711997466110)]
[外链图片转存中…(img-gJP98cZp-1711997466110)]
[外链图片转存中…(img-65n6Y67s-1711997466111)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-5nB1LW8F-1711997466111)]

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-CGXwlxn0-1711997466111)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值