精华内容
下载资源
问答
  • SpringBoot手动提交事务

    万次阅读 2019-09-06 11:06:48
    Springboot内部提供的事务管理器是根据autoconfigure来进行决定的。 比如当使用jpa的时候,也就是pom中加入了spring-boot-starter-data-jpa这个starter之后(之前我们分析过springboot的自动化配置原理)。 ...

    Springboot内部提供的事务管理器是根据autoconfigure来进行决定的。

    比如当使用jpa的时候,也就是pom中加入了spring-boot-starter-data-jpa这个starter之后(之前我们分析过springboot的自动化配置原理)。

    Springboot会构造一个JpaTransactionManager这个事务管理器。

    而当我们使用spring-boot-starter-jdbc的时候,构造的事务管理器则是DataSourceTransactionManager。

    这2个事务管理器都实现了spring中提供的PlatformTransactionManager接口,这个接口是spring的事务核心接口。

    这个核心接口有以下这几个常用的实现策略:

    HibernateTransactionManager

    DataSourceTransactionManager

    JtaTransactionManager

    JpaTransactionManager

    spring-boot-starter-data-jpa这个starter会触发HibernateJpaAutoConfiguration这个自动化配置类,HibernateJpaAutoConfiguration继承了JpaBaseConfiguration基础类。

    在JpaBaseConfiguration中构造了事务管理器:

    @Bean

    @ConditionalOnMissingBean(PlatformTransactionManager.class)

    public PlatformTransactionManager transactionManager() {

    return new JpaTransactionManager();

    }

    spring-boot-starter-jdbc会触发DataSourceTransactionManagerAutoConfiguration这个自动化配置类,也会构造事务管理器:

    @Bean

    @ConditionalOnMissingBean(PlatformTransactionManager.class)

    @ConditionalOnBean(DataSource.class)

    public DataSourceTransactionManager transactionManager() {

    return new DataSourceTransactionManager(this.dataSource);

    }

    Spring的事务管理器PlatformTransactionManager接口中定义了3个方法:

    // 基于事务的传播特性,返回一个已经存在的事务或者创建一个新的事务

    TransactionStatus getTransaction(TransactionDefinition definition) throwsTransactionException;

    // 提交事务

    void commit(TransactionStatus status) throws TransactionException;

    // 回滚事务

    void rollback(TransactionStatus status) throws TransactionException;

    其中TransactionDefinition接口表示跟spring兼容的事务属性,比如传播行为、隔离级别、超时时间、是否只读等属性。

    DefaultTransactionDefinition类是一个默认的TransactionDefinition实现,它的传播行为是PROPAGATION_REQUIRED(如果当前没事务,则创建一个,否则加入到当前事务中),隔离级别是数据库默认级别。

    TransactionStatus接口表示事务的状态,比如事务是否是一个刚构造的事务、事务是否已经完成等状态。

    下面这段代码就是传统事务的常见写法:

    transaction.begin();

    try {

    ...

    transaction.commit();

    catch(Exception e) {

    ...

    transaction.rollback();

    finally {

    }

    由于spring的事务操作被封装到了PlatformTransactionManager接口中,commit和rollback方法对应接口中的方法,begin方法在getTransaction方法中会被调用。

    细心的读者发现文章前面构造事务管理器的时候都会加上这段注解:

    @ConditionalOnMissingBean(PlatformTransactionManager.class)

    也就是说如果我们手动配置了事务管理器,Springboot就不会再为我们自动配置事务管理器。

    如果要使用多个事务管理器的话,那么需要手动配置多个:

    @Configuration

    public class DatabaseConfiguration {

    @Bean

    public PlatformTransactionManager transactionManager1(EntityManagerFactory entityManagerFactory) {

    return new JpaTransactionManager(entityManagerFactory);

    }

    @Bean

    public PlatformTransactionManager transactionManager2(DataSource dataSource) {

    return new DataSourceTransactionManager(dataSource);

    }

    }

    然后使用Transactional注解的时候需要声明是哪个事务管理器:

    @Transactional(value="transactionManager1")

    public void save() {

    doSave();

    }

    Spring给我们提供了一个TransactionManagementConfigurer接口,该接口只有一个方法返回PlatformTransactionManager。其中返回的PlatformTransactionManager就表示这是默认的事务处理器,这样在Transactional注解上就不需要声明是使用哪个事务管理器了。

     

    有很多情况我们同一个方法需要多次提交事务:这个时候就不能使用Transactional注解,需要自动提交事务,因为我们项目整合的是jpa

    @Autowired
    private PlatformTransactionManager transactionManager;
    public void test() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);//新发起一个事务
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            CicpxPolicyInfo policyInfo = new CicpxPolicyInfo();
            policyInfo.setPolicyNo("chenshiyan");
            policyInfo.setRequestNo("test");
            cicpxPolicyInfoDao.save(policyInfo);
            transactionManager.commit(status);
            CicpxPolicyInfo chenshiyan = cicpxPolicyInfoDao.findByPolicyNo("chenshiyan");
    
        }catch (Exception e){
            transactionManager.rollback(status);
        }
    }

    刚开始注入的是JpaTransactionManager,发现无法注入,改为PlatformTransactionManager即可;

    原文链接

    展开全文
  • 今天在工作中遇到了一个spring事务的问题: 在service方法内需要通过线程去执行添加用户积分和用户积分日志的情况,试了下通过@Transactional声明式事务不起作用,只能使用手动事务去控制 因此写了这篇博客,记录一下这...

    今天在工作中遇到了一个spring事务的问题: 在service方法内需要通过线程去执行添加用户积分和用户积分日志的情况,试了下通过@Transactional声明式事务不起作用,只能使用手动事务去控制

    因此写了这篇博客,记录一下这个情况,希望能帮助到大家

    一、事务的重要性,相信在实际开发过程中,都有很深的了解了。但是存在一个问题我们经常在开发的时候一般情况下都是用的注解的方式来进行事务的控制,说白了基于spring的7种事务控制方式来进行事务的之间的协调。

    二、spring的7中事务传播行为

    Propagation.REQUIRED 代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建事务,
    Propagation.SUPPORTS 代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则该方法在非事务的上下文中执行
    Propagation.MANDATORY 代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则抛出异常
    Propagation.REQUIRES_NEW 创建一个新的事务上下文,如果当前方法的调用者已经有了事务,则挂起调用者的事务,这两个事务不处于同一上下文,如果各自发生异常,各自回滚
    Propagation.NOT_SUPPORTED 该方法以非事务的状态执行,如果调用该方法的调用者有事务则先挂起调用者的事务
    Propagation.NEVER 该方法以非事务的状态执行,如果调用者存在事务,则抛出异常
    Propagation.NESTED 如果当前上下文中存在事务,则以嵌套事务执行该方法,也就说,这部分方法是外部方法的一部分,调用者回滚,则该方法回滚,但如果该方法自己发生异常,则自己回滚,不会影响外部事务,如果不存在事务,则与PROPAGATION_REQUIRED一样

    三、数据库四大特性和MySQL事务的隔离级别

    1)四大特性

    a、原子性(Atomicity)
      原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。

    b、 一致性(Consistency)
      一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

    c、隔离性(Isolation)
      隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

    d、 持久性(Durability)
      持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    2)隔离级别

    img

    a、脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。(读取未提交的数据)

    b、不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。(边读边写)

    c、幻读指两个事务同时发生,两个事务修改数据,读到的数据不是自己开始修改的数据。幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体。(同时写,同时读)

    3)数据库事务级别,默认使用Repeatable read级别,列表级别从下往上级别越低。查看级别

    select @@tx_isolation;
    

    四、扯远了,写上面spring事务和数据库事务隔离级别,主要的目的就是了解事务之间存在的传递关系,这样在控制的时候,spring会通过事务与事务之间关系,来达到回滚或者提交的效果。

    五、如果在没有办法使用注解的时候(比如多线程等),就要使用手动的方式来做事务管理了,这也就是编程式的事务管理。

    1)首先加入注解,这就是spring的jdbc框架中提供的事务管理方式

        @Autowired
        private PlatformTransactionManager platformTransactionManager;
    
        @Autowired
        private TransactionDefinition transactionDefinition;
    

    2)看一下源码(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)

            @Bean
            @ConditionalOnMissingBean({PlatformTransactionManager.class})
            public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
                DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
                if (this.transactionManagerCustomizers != null) {
                    this.transactionManagerCustomizers.customize(transactionManager);
                }
    
                return transactionManager;
            }
    

    img

    备注:有兴趣可以了解一下DataSourceTransactionManager的写法和原理。

            @Bean
            @ConditionalOnMissingBean
            public TransactionTemplate transactionTemplate() {
                return new TransactionTemplate(this.transactionManager);
            }
    

    img

    注意,这里的所有事务传播方式包括处理,都需要自己手动去处理。

    3)编写方式

    TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
    platformTransactionManager.commit(transactionStatus);
    platformTransactionManager.rollback(transactionStatus);
    

    说明:这里开发事务过后,返回一个事务状态,这个状态记录了东西,用来控制事务的管理,当然,多个事务之间的控制需要人为控制。

    img

    4)编程式的事务控制经量少用,因为控制程度上面来说spring的方式还是来的更加不错,编程式的方式,更多用于在需要事务的时候,没有办法加入事务,才采取手动控制事务的方式。

    使用示例 :

    1 在service内注入 这两个bean 
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    
    @Autowired
    private TransactionDefinition transactionDefinition;
    
    2在 service方法内创建TransactionStatus
    TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
    通过 platformTransactionManager.commit(transactionStatus); 提交事务
    通过 platformTransactionManager.rollback(transactionStatus); 回滚事务 
    
    示例代码: 
    
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    
    @Autowired
    private TransactionDefinition transactionDefinition;
    
    public void b(){
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
    
        UserIntegralInfo info = new UserIntegralInfo();
        info.setUserId(1L);
        info.setPoint(1);
        info.setOp("");
        info.setCurrIntegral(1);
        integralMapper.insert(info);
        platformTransactionManager.commit(transactionStatus);
        throw new RuntimeException();
    }
    
    展开全文
  • SpringBootTest @Log4j2 class QualisMasterPrintMapperBridgeTest { @Autowired private PlatformTransactionManager platformTransactionManager; @Autowired private TransactionDefinition ...
  • SpringBoot手动管理事务

    2021-07-31 13:56:02
    springboot 开启事务以及手动提交事务 需要在服务类上加上两个注解 @Autowired DataSourceTransactionManager dataSourceTransactionManager; @Autowired TransactionDefinition transactionDefinition; 手动开启...

    springboot 开启事务以及手动提交事务

    需要在服务类上加上两个注解

    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    

    手动开启事务

    TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);

    手动提交事务

    dataSourceTransactionManager.commit(transactionStatus);//提交

    手动回滚事务
    dataSourceTransactionManager.rollback(transactionStatus);//最好是放在catch 里面,防止程序异常而事务一直卡在哪里未提交

    package com.java.controller;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.stereotype.Controller;
    import org.springframework.transaction.TransactionDefinition;
    import org.springframework.transaction.TransactionException;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.RequestMapping;
     
    import com.java.entity.User;
    import com.java.service.impl.UserServiceImpl;
    @Controller
    @RequestMapping(value = "/p")
    public class tt {
    	@Autowired
    	public UserServiceImpl t;
    	@Autowired
    	DataSourceTransactionManager dataSourceTransactionManager;
    	@Autowired
    	TransactionDefinition transactionDefinition;
    	@RequestMapping(value = "/test")
    	public   void  jj(){
    		TransactionStatus transactionStatus=null;
    		try {
    			 transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    			User user=new User();
    			user.setId("12");
    			user.setUsername("nihao");
    			user.setPassword("12346");
    			t.insert(user);
    			System.out.println("加油");
    			dataSourceTransactionManager.commit(transactionStatus);//提交
    			TransactionStatus transactionStatus2 = dataSourceTransactionManager.getTransaction(transactionDefinition);
    			User user2=new User();
    			user2.setId("12");
    			user2.setUsername("nihao");
    			user2.setPassword("12346");
    			t.insert(user2);
    			dataSourceTransactionManager.commit(transactionStatus2);//提交
    			
    		} catch (Exception e) {
    			if(transactionStatus!=null){
    				dataSourceTransactionManager.rollback(transactionStatus);
    			}
    			
    			e.printStackTrace();
    		}
    	}
    	@RequestMapping(value = "/test2")
    	public   void  jj2(){
    		TransactionStatus transactionStatus=null;
    		try {
    			 transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    			User user=new User();
    			user.setId("12");
    			user.setUsername("nihao");
    			user.setPassword("12346");
    			t.insert(user);
    			System.out.println("加油");
    			/*dataSourceTransactionManager.commit(transactionStatus);//提交
    			TransactionStatus transactionStatus2 = dataSourceTransactionManager.getTransaction(transactionDefinition);*/
    			User user2=new User();
    			user2.setId("12");
    			user2.setUsername("nihao");
    			user2.setPassword("12346");
    			t.insert(user2);
    			dataSourceTransactionManager.commit(transactionStatus);//提交
    			
    		} catch (Exception e) {
    			if(transactionStatus!=null){
    				dataSourceTransactionManager.rollback(transactionStatus);
    			}
    			
    			e.printStackTrace();
    		}
    	}
    }
    
    展开全文
  • springboot 开启事务以及手动提交事务

    万次阅读 多人点赞 2019-03-26 14:55:19
    springboot 开启事务以及手动提交事务 需要在服务类上加上两个注解 @Autowired DataSourceTransactionManager dataSourceTransactionManager; @Autowired TransactionDefinition transactionDefinition; 手动开启...

    springboot 开启事务以及手动提交事务

    需要在服务类上加上两个注解

    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    

    手动开启事务
    TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    手动提交事务
    dataSourceTransactionManager.commit(transactionStatus);//提交
    手动回滚事务
    dataSourceTransactionManager.rollback(transactionStatus);//最好是放在catch 里面,防止程序异常而事务一直卡在哪里未提交

    展开全文
  • SpringBoot Mybatis 手动提交事务

    千次阅读 2020-05-19 17:56:15
    1.数据库配置文件mybatis-config-only.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" ...--先加载基.
  • springboot 手动开启事务,分段提交.

    千次阅读 2019-10-09 13:30:55
    List<OrdLogSyn> ordLogSynList = ordLogSynMapper.batchQuery("AP", "20190926", "0", "1000"); for (int i = 0; i < 2; i++) { DefaultTransactionDefinition def = new DefaultTra...
  • SpringBoot 开启事务以及手动提交事务

    千次阅读 2020-03-30 14:59:26
    SpringBoot 开启事务以及手动提交事务 需要在服务类上加上两个注解 @Autowired DataSourceTransactionManager dataSourceTransactionManager; @Autowired TransactionDefinition transactionDefinition; //手动开启...
  • SpringBoot 手动处理事务SpringBoot 手动处理事务,如要代码: import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionDefinition; ...
  • 主要介绍了springboot手动事务回滚的实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • springboot事务手动提交

    2021-02-02 15:16:58
    @Autowired private PlatformTransactionManager platformTransactionManager; @Transactional public void insert() { try { // 业务逻辑 ... // 事务手动回滚 platformTransactionManager.rollb
  • 手动回滚事务 有时我们需要捕获一些错误信息,又需要进行事务回滚,这时我们就需要用到Spring提供的事务切面支持类TransactionAspectSupport。 @Transactional(rollbackFor = Exception.class) @Override public ...
  • springboot手动事务回滚

    2020-07-22 21:25:02
    亲测在使用@...下面使用线程所机制,进行整体的事务提交事务回滚,代码如下: 在springboot启动类上加 @EnableTransactionManagement 注解 线程类中添加一下代码 @Autowired private DataExchangeLoadEv
  • @Service public class MyService{ @Autowired DataSourceTransactionManager transactionManager; public ResultMap lockStockWhenNewOrder(List<...获取事务定义 DefaultTransactionDefinition d.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,638
精华内容 1,855
关键字:

springboot手动提交事务

spring 订阅