验证码: 看不清楚,换一张 查询 注册会员,免验证
  • {{ basic.site_slogan }}
  • 打开微信扫一扫,
    您还可以在这里找到我们哟

    关注我们

Spring事务是怎么实现的

阅读:803 来源:乙速云 作者:代码code

Spring事务是怎么实现的

      Spring事务如何实现

      1.Spring事务底层是基于数据库事务和AOP机制的

      2.首先对于使用了@Transactional注解的Bean,Spring会创建一个代理对象作为Bean

      3.当调用代理对象的方法时,会先判断该方法上是否加了@Transactional注解

      4.如果加了,那么则利用事务管理器创建一个数据库连接

      5.并且修改数据库连接的autocommit属性为false,禁止此连接的自动提交,这是实现Spring事务非常重要的一步

      6.然后执行当前方法,方法中会执行sql

      7.执行完当前方法后,如果没有出现异常就直接提交事务

      8.如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务

      注:

      1.Spring事务的隔离级别对应的就是数据库的隔离级别

      2.Spring事务的传播机制是Spring事务自己实现的,也是Spring事务中最复杂的

      3.Spring事务的传播机制是基于数据库连接来做的,一个数据库连接就是一个事务,如果传播机制配置为需要新开一个事务,那么实际上就是先新建一个数据库连接,在此新数据库连接上执行sql

      Spring事务实现的几种方式

      事务几种实现方式

      (1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。

      (2)基于 TransactionProxyFactoryBean的声明式事务管理

      (3)基于 @Transactional 的声明式事务管理

      (4)基于Aspectj AOP配置事务

      编程式事务管理

      1、transactionTemplate

      此种方式是自动的事务管理,无需手动开启、提交、回滚。

      配置事务管理器

      
             
                     
             

      配置事务模板对象

      
             
                  
              

      测试

      @Controller
      @RequestMapping("/tx")
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
      public class TransactionController {
      
          @Resource
          public TransactionTemplate transactionTemplate;
      
          @Resource
          public DataSource dataSource;
      
          private static JdbcTemplate jdbcTemplate;
      
          private static final String INSERT_SQL = "insert into cc(id) values(?)";
          private static final String COUNT_SQL = "select count(*) from cc";
      
          @Test
          public void TransactionTemplateTest(){
              //获取jdbc核心类对象,进而操作数据库
              jdbcTemplate = new JdbcTemplate(dataSource);
              //通过注解 获取xml中配置的 事务模板对象
              transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
              //重写execute方法实现事务管理
              transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                  @Override
                  protected void doInTransactionWithoutResult(TransactionStatus status) {
                      jdbcTemplate.update(INSERT_SQL, "33");   //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
                  }
              });
              int i = jdbcTemplate.queryForInt(COUNT_SQL);
              System.out.println("表中记录总数:"+i);
          }
      
      }

      2、PlatformTransactionManager

      使用 事务管理器 PlatformTransactionManager 对象,PlatformTransactionManager是DataSourceTransactionManager实现的接口类

      此方式,可手动开启、提交、回滚事务。

      只需要:配置事务管理

      
             
                     
             

      测试

      @Controller
      @RequestMapping("/tx")
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
      public class TransactionController {
      
         @Resource
          public PlatformTransactionManager transactionManager;//这里就是将配置数据管理对象注入进来,
          
          @Resource
          public DataSource dataSource;
          
          private static JdbcTemplate jdbcTemplate;
      
          private static final String INSERT_SQL = "insert into cc(id) values(?)";
          private static final String COUNT_SQL = "select count(*) from cc";
      
          @Test
          public void showTransaction(){
              //定义使用隔离级别,传播行为
              DefaultTransactionDefinition def = new DefaultTransactionDefinition();
              def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
              def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
              //事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
              TransactionStatus transaction = transactionManager.getTransaction(def);
              jdbcTemplate = new JdbcTemplate(dataSource);
              int i = jdbcTemplate.queryForInt(COUNT_SQL);
              System.out.println("表中记录总数:"+i);
              try {
                  jdbcTemplate.update(INSERT_SQL,"2");
                  jdbcTemplate.update(INSERT_SQL,"是否");//出现异常,因为字段为int类型,会报异常,自动回滚
                  transactionManager.commit(transaction);
              }catch (Exception e){
                  e.printStackTrace();
                  transactionManager.rollback(transaction);
              }
              int i1 = jdbcTemplate.queryForInt(COUNT_SQL);
              System.out.println("表中记录总数:"+i1);
          }
      }

      声明式事务管理

      1、基于Aspectj AOP开启事务

      配置事务通知

      
             
                
                    
                
             

      配置织入

      
             
             
                
                
            

      一个完整的例子

      
      
                 
             
             
                     
             
          
          
      
             
             
                     
                     
                     
                     
      
                     
                     
                     
                     
                     
                     
                     
      
                     
                     
                  
                  
                  
                  
                  
             
      
      
             
                     
                     
             
      
             
             
                     
             
      
             
             
      
             
             
                     
             
      
              
             
                  
              
      
      
             
                
                    
                
             
             
      
             
                
                
            
      

      这样就算是给 cn.sys.service下所有的方法加入了事务

      也可以用springboot的配置类方式:

      package com.junjie.test;
      
      @Configurationpublic 
      class TxAnoConfig {    
          /*事务拦截类型*/    
          @Bean("txSource")
          public TransactionAttributeSource transactionAttributeSource() {   
              NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); 
              /*只读事务,不做更新操作*/        
              RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, Collections.singletonList(new RollbackRuleAttribute(Exception.class)));   
              requiredTx.setTimeout(60);   
              Map txMap = new HashMap<>();   
              txMap.put("*", requiredTx);  
              source.setNameMap(txMap);    
              return source; 
          }   
          /**     * 切面拦截规则 参数会自动从容器中注入     */    
          @Bean 
          public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) { 
              AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();  
              pointcutAdvisor.setAdvice(txInterceptor);    
              pointcutAdvisor.setExpression("execution (* com.cmb..*Controller.*(..))");   
              return pointcutAdvisor;   
          } 
          /*事务拦截器*/ 
          @Bean("txInterceptor")   
          TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx) {    
              return new TransactionInterceptor(tx, transactionAttributeSource()); 
          }
      }

      2、基于注解的 @Transactional 的声明式事务管理

      @Transactional
      public int saveRwHist(List list) {
      return rwDao.saveRwHist(list);
      }

      这个注解的开启需要在spring.xml里加上一个开启注解事务的配置

    分享到:
    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: hlamps#outlook.com (#换成@)。
    相关文章
    {{ v.title }}
    {{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
    你可能感兴趣
    推荐阅读 更多>