zoukankan      html  css  js  c++  java
  • 八、Spring之深入理解声明式事务

    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。
        • 在目标方法执行时,事务拦截器先获取事务相关属性,该获取事务管理器,然后执行目标方法,有异常,利用事务管理回滚操作;正常则提交事务。
  • 相关阅读:
    关于视图的说明和设计
    关于REST风格API的设计
    关于 Linux 操作
    文件删除
    文件写入有读取
    生成器,迭代器
    Linux防火墙相关命令
    Linux下安装Maven
    Linux下安装Nginx
    Word相关知识点
  • 原文地址:https://www.cnblogs.com/lee0527/p/11787742.html
Copyright © 2011-2022 走看看