Spring之深入理解声明式事务

何为事务?

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

事务的四个属性

1、原子性(atomicity)

事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用

2、一致性(consistency)

一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中

3、隔离性(isolation)

可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

4、持久性(durability)

事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

Spring中的事务管理

Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

编程式事务管理

将事务管理代码嵌到业务方法中来控制事务的提交和回滚

缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过AOP方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

传播行为

REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行,否则就开启一个新的事务,并在自己的事务内运行,默认传播行为
REQUIRED_NEW 当前方法必须启动新事务,并在自己的事务内运行,如果有事务正在运行,则将它挂起
SUPPORTS 如果有事务在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中
NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
MANDATORY 当前的方法必须运行在事务内部,如果没有正在运行的事务,就会抛出异常
NEVER 当前方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。

示例:基于注解的声明式事务管理

创建配置类:

@Configuration
//开启事务支持
@EnableTransactionManagement
@ComponentScan("com.zl.springBase.tx")
public class TxConfig {
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("root");
return dataSource;
} @Bean
public JdbcTemplate jdbcTemplate() throws PropertyVetoException {
return new JdbcTemplate(dataSource());
} //将事务管理器注入到容器中
@Bean
public PlatformTransactionManager transactionManager() throws PropertyVetoException {
return new DataSourceTransactionManager(dataSource());
}
}

持久层

@Repository
public class UserDao {
@Autowired
public JdbcTemplate jdbcTemplate; public void insertUser(){
String sql = "insert into user values(?,?)";
jdbcTemplate.update(sql,"admin",18);
}
}

业务层

@Service
public class UserService {
@Autowired
public UserDao userDao; @Transactional
public void insertUser(){
userDao.insertUser();
int a = 1/0;
}
}

测试结果:如果业务层方法没有加@Transactional注解,则即使发生1/0的错误,事务也不会回滚,数据还是会被添加到数据库中。加上@Transactional注解后发生错误,事务就回滚了。

声明式事务原理分析

  1. @EnableTransactionManagement利用TransactionManagementConfigurationSelector给容器中导入了两个组件

    • AutoProxyRegistrar
    • ProxyTransactionManagementConfiguration
  2. AutoProxyRegistrar做了什么?
    • 给容器中注册了一个InfrastructureAdvisorAutoProxyCreator组件
    • 这个组件利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象。当代理对象执行目标方法,方法拦截器就会执行拦截。
  3. ProxyTransactionManagementConfiguration做了什么?
    • 给容器中注册事务增强器

      • 事务增强器要用到事务注解的信息,来解析事务
      • 还要用到TransactionInterceptor事务拦截器(保存了事务属性信息,和事务管理器),它是一个MethodInterceptor。
      • 在目标方法执行时,事务拦截器先获取事务相关属性,该获取事务管理器,然后执行目标方法,有异常,利用事务管理回滚操作;正常则提交事务。

八、Spring之深入理解声明式事务的更多相关文章

  1. spring boot中的声明式事务管理及编程式事务管理

    这几天在做一个功能,具体的情况是这样的: 项目中原有的几个功能模块中有数据上报的功能,现在需要在这几个功能模块的上报之后生成一条消息记录,然后入库,在写个接口供前台来拉取消息记录. 看到这个需求,首先 ...

  2. spring基于xml的声明式事务控制配置步骤

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. spring学习08(声明式事务)

    11.声明式事务 11.1 回顾事务 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性. 事务就是把一系列的动作当 ...

  4. Spring学习笔记3—声明式事务

    1 理解事务 事务:在软件开发领域,全有或全无的操作被称为事务.事务允许我们将几个操作组合成一个要么全部发生要么全部不发生的工作单元. 事务的特性: 原子性:事务是由一个或多个活动所组成的一个工作单元 ...

  5. spring事物配置,声明式事务管理和基于@Transactional注解的使用

    http://blog.csdn.net/bao19901210/article/details/41724355 http://www.cnblogs.com/leiOOlei/p/3725911. ...

  6. Spring第13篇—–Spring整合Hibernate之声明式事务管理

    不容置疑的我们可以知道Spring的事务管理是通过AOP(AOP把我们的事务管理织入到我们的业务逻辑里面了)的方式来实现的,因为事务方面的代码与spring的绑定并以一种样板式结构使用.(面向切面编程 ...

  7. spring基于XML的声明式事务控制

    <?xml version="1.0" encoding="utf-8" ?><beans xmlns="http://www.sp ...

  8. Spring学习笔记:声明式事务管理增删改查业务

    一.关于是事务 以方法为单位,进行事务控制:抛出异常,事务回滚. 最小的执行单位为方法.决定执行成败是通过是否抛出异常来判断的,抛出异常即执行失败 二.声明式事务: 声明式事务(declarative ...

  9. spring学习笔记(22)声明式事务配置,readOnly无效写无异常

    在上一节内容中.我们使用了编程式方法来配置事务,这种优点是我们对每一个方法的控制性非常强.比方我须要用到什么事务,在什么位置假设出现异常须要回滚等.能够进行非常细粒度的配置.但在实际开发中.我们可能并 ...

随机推荐

  1. PHP 源码学习 | 变量类型数据结构

    前段时间因为项目需要,研究了一下在 Windows 系统下进行 PHP 扩展的开发,对于 PHP 扩展的开发并不是一件容易的事情(话又说回来了,会者不难,难者不会,关键是自己不会).我当时的需求,主要 ...

  2. 跟着高淇学Python——第一到第三章总结

    2019/10/26 第一章:Python介绍 Python是一种解释型,面向对象的语言.特点是: 可读性强 简洁,简洁 面向对象 免费开源 可移植性和跨平台性 丰富的库 可扩展性 应用范围:1.人工 ...

  3. Kubernetes V1.15 二进制部署集群

    1. 架构篇 1.1 kubernetes 架构说明              1.2 Flannel网络架构图 1.3 Kubernetes工作流程             2. 组件介绍 2.1 ...

  4. keras使用多GPU并行训练模型 | keras multi gpu training

    本文首发于个人博客https://kezunlin.me/post/95370db7/,欢迎阅读最新内容! keras multi gpu training Guide multi_gpu_model ...

  5. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  6. Python远程linux执行命令

    1.远程登录到linux上,使用到的模块paramiko #远程登陆操作系统 def ssh(sys_ip,username,password,cmds): try #创建ssh客户端 client ...

  7. DevOps 工程师成长日记系列一:必备知识与技能组合

    原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-366097df7737 ...

  8. centos7中python3.6报错ModuleNotFoundError: No module named '_ssl' 或者 Max retries exceeded with url: / (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",))

    如果在运行爬虫时报此错:requests.exceptions.SSLError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max r ...

  9. 使用Socket下载图片

    Socket下载一张图片 Socket下载一页图片 Socket下载一张图片 在百度搜索头像,挑一张 复制图片的路径打开,并保存这个url 把这个url的域名和路径分开 首先导入socket模块 第一 ...

  10. Shell命令-系统信息及显示之df、top

    文件及内容处理 - df.top 1. df:报告文件系统磁盘空间的使用情况 df命令的功能说明 df 命令用于显示目前在Linux系统上的文件系统的磁盘使用情况统计. df命令的语法格式 df [O ...