Spring事务配置&&回滚失效的原因之一

2019-06-21_18-34.png

包名的配置问题

execution(* com.keeep.isrvbase.service.*.*(..)) 
//表示匹配com.keeep.isrvbase.service包下的所有方法
execution(* com.keeep.isrvbase.service..*.*(..)) 
 //表示匹配com.savage.server包及其子包下的所有方法

Spring 事务的隔离性

事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化

MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED

脏读 : 一个事务读取到另一事务未提交的更新数据  
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说,后续读取可以读到另一事务已提交的更新数据.   
相反, "可重复读"在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据   
幻读 : 一个事务读到另一个事务已提交的insert数据

Spring事务的传播行为

事物传播行为介绍: 
@Transactional(propagation=Propagation.REQUIRED) 
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) 
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) 
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) 
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

事务配置

package com.keeep.isrvbase.pojo;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Table;

/**
 * 测试用例
 * @author congco
 */
@Setter
@Getter
@Table(name="tb_base_transaction_test")
public class TransactionTest {

    private Long id;

    private String name;

}

applicationContext-transaction.xml




    
    
        
    

    
    
        
            
            
            
            
            
            
        
    

    
        
        
        
        
    


mapper

package com.keeep.isrvbase.mapper;

import com.github.abel533.mapper.Mapper;
import com.keeep.isrvbase.pojo.TransactionTest;

/**
 * @author congco
 */
public interface TransactionTestMapper  extends Mapper {
}

service

package com.keeep.isrvbase.service;

import com.keeep.isrvbase.mapper.TransactionTestMapper;
import com.keeep.isrvbase.pojo.TransactionTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * created on 2020/4/10 上午11:58
 *
 * @author congco
 */
@Service
public class AnotherTransService {


    @Autowired
    private TransactionTestMapper mapper;
    public String testTrans() {
        try {
            TransactionTest test = new TransactionTest();
            test.setName("cong");
            this.mapper.insertSelective(test);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "over";
    }
}


//
package com.keeep.isrvbase.service.test;

import com.keeep.isrvbase.service.AnotherTransService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

/**
 * @author congco
 * @date 19-5-27 下午7:25
 */
@Service
public class TransactionTestService {


    @Autowired
    public AnotherTransService anotherTransService;

    public String queryName() {
        return "Hello Congco";
    }


    public String saveName() {
        try {
            System.out.println("开始事务");
            this.anotherTransService.testTrans();
            int i =1/0;
            this.anotherTransService.testTrans();
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        System.out.println("roll back");
        return "ok";
    }
}
 
    junit
    junit
    4.9
    test
   
   
    org.springframework
    spring-test
     3.2.4.RELEASE  
    provided
 

单元测试

package com.keeep.isrvbase.test;


import com.keeep.isrvbase.service.test.TransactionTestService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * created on 2020/4/10 上午11:21
 *
 * @author congco
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring/app*.xml")
public class TransactionTestServiceTest {

    @Autowired
    private TransactionTestService service;
    @Test
   public void queryName() {

        String name = this.service.queryName();
        System.out.println(name);
    }

    @Test
   public void saveName() {
        this.service.saveName();
    }
}

结果

GTWfmQ.png

GTWROg.png

数据库表没有插入新的数据

参考博客

  • Spring使用注解方式进行事务管理
  • Spring 事物机制总结
  • Spring AOP 中@Pointcut的用法

你可能感兴趣的:(Spring事务配置&&回滚失效的原因之一)