springboot 事务自调用失效


springboot 事务自调用失效

              

                                 

自调用失效

       

自调用失效:同一个类中,一个方法调用另一个方法,被调用方法上的事务不生效

失效原因:spring事务底层使用动态代理,若同一个类中的方法吊用另一个方法,则不存在对象之间的代理关系,被调用方法的事务失效

         

解决方法

接口:HelloService,
接口实现类:HelloServiceImpl
方法:fun、fun2,fun2调用fun

# 新建类实现fun调用fun2
新建类HelloServiceImpl2,方法fun2在HelloServiceImpl2中
在类中注入HelloServiceImpl对象实例,方法fun在HelloServiceImpl中,
在HelloServiceImpl2的fun2中,调用HelloServiceImpl的fun方法

# application.getBean
在fun2中使用application.getBean(HelloService.class)获取对象helloService,
然后使用helloService.fun实现方法调用

# AopUtils.currentProxy()
@EnableAspectJAutoProxy(exposeProxy = true),将exposeProxy = true
在fun2中使用((HelloService)AopContext.currentProxy()).fun()实现方法调用

        

             

                                 

自调用失效示例

        

                          

             

***********

pojo

          

Person

@Getter
@Setter
@ApiModel(value = "Person对象", description = "")
public class Person extends Model<Person> {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    private String name;

    private Integer age;


    @Override
    public Serializable pkVal() {
        return this.id;
    }

}

              
***********

config 层

           

DataConfig

@Configuration
@MapperScan("com.example.demo.dao")
public class DataConfig {

    @Bean
    public MybatisPlusInterceptor initMybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);

        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor =new OptimisticLockerInnerInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);

        return mybatisPlusInterceptor;
    }
}

           

***********

service 层

           

PersonService

public interface PersonService extends IService<Person> {

    void savePerson(Person person);
    void savePersonList(List<Person> personList);
}

            

***********

service.impl 层

           

PersonServiceImpl

@Service
public class PersonServiceImpl extends ServiceImpl<PersonMapper, Person> implements PersonService {

    @Resource
    private PersonMapper personMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void savePerson(Person person) {
        personMapper.insert(person);
        System.out.println(person.toString());
    }

    @Override
    public void savePersonList(List<Person> personList) {
        for (Person person : personList){
            savePerson(person);
        }
    }
}

       

***********

controller 层

PersonController

@RestController
@RequestMapping("/person")
public class PersonController {

    @Resource
    private PersonService personService;

    @RequestMapping("/hello")
    public String hello(){
        for (int i=0;i<1;i++){
            Person person = new Person();
            person.setName("瓜田李下 "+i);
            person.setAge(10+i);

            try {
                personService.savePerson(person);
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }

        return "hello";
    }

    @RequestMapping("/hello2")
    public String hello2(){
        List<Person> personList = new ArrayList<>();
        for (int i=0;i<1;i++){
            Person person = new Person();
            person.setName("瓜田李下 "+i);
            person.setAge(10+i);

            personList.add(person);
        }

        try {
            personService.savePersonList(personList);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

        return "success";
    }
}

        

***********

使用测试

           

localhost:8080/person/hello,控制台输出:

# 创建事务
2022-04-29 18:38:46.696 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [com.example.demo.service.impl.PersonServiceImpl.savePerson]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT

# 获取数据库连接
2022-04-29 18:38:46.794 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@11f05516] for JDBC transaction

# 切换到手动提交
2022-04-29 18:38:46.795 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11f05516] to manual commit
com.example.demo.pojo.Person@3f707b76

# 初始化事务提交
2022-04-29 18:38:46.849 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit

# 事务提交
2022-04-29 18:38:46.849 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Committing JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@11f05516]

# 释放事务
2022-04-29 18:38:46.855 DEBUG 1203 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11f05516] after transaction

         

localhost:8080/person/hello2,控制台输出:

com.example.demo.pojo.Person@72c88c46

没有执行事务操作

                   

                  

                                 

applicationContext

          

HelloServiceImpl:注入ApplicationContext对象

@Service
public class PersonServiceImpl extends ServiceImpl<PersonMapper, Person> implements PersonService {

    @Resource
    private PersonMapper personMapper;

    @Resource
    private ApplicationContext applicationContext;  //注入applicationContext对象

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void savePerson(Person person) {
        personMapper.insert(person);
        System.out.println(person.toString());
    }

    @Override
    public void savePersonList(List<Person> personList) {
        PersonService personService = applicationContext.getBean(PersonService.class);
                                                  //获取personService对象
        for (Person person : personList){
            personService.savePerson(person);     //通过personService进行方法调用
        }
    }
}

        

localhost:8080/person/hello,控制台输出:

2022-04-29 19:08:22.885 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [com.example.demo.service.impl.PersonServiceImpl.savePerson]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
2022-04-29 19:08:22.985 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] for JDBC transaction
2022-04-29 19:08:22.987 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] to manual commit
com.example.demo.pojo.Person@59f295be
2022-04-29 19:08:23.042 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit
2022-04-29 19:08:23.042 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Committing JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238]
2022-04-29 19:08:23.050 DEBUG 1391 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] after transaction

        

localhost:8080/person/hello2,控制台输出:

2022-04-29 19:08:28.476 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [com.example.demo.service.impl.PersonServiceImpl.savePerson]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
2022-04-29 19:08:28.477 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] for JDBC transaction
2022-04-29 19:08:28.477 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] to manual commit
com.example.demo.pojo.Person@545f5832
2022-04-29 19:08:28.486 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit
2022-04-29 19:08:28.487 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Committing JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238]
2022-04-29 19:08:28.493 DEBUG 1391 --- [nio-8080-exec-3] o.s.jdbc.support.JdbcTransactionManager  : Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@41f1f238] after transaction

此时,savePerson执行了事务操作

       

             

                                 

AopContext.currentProxy

        

引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

         

DataConfig

@Configuration
@MapperScan("com.example.demo.dao")
@EnableAspectJAutoProxy(exposeProxy = true)   //暴露代理
public class DataConfig {

    @Bean
    public MybatisPlusInterceptor initMybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);

        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor =new OptimisticLockerInnerInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);

        return mybatisPlusInterceptor;
    }
}

       

PersonServiceImpl:获取代理对象,通过代理对象调用方法

@Service
public class PersonServiceImpl extends ServiceImpl<PersonMapper, Person> implements PersonService {

    @Resource
    private PersonMapper personMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void savePerson(Person person) {
        personMapper.insert(person);
        System.out.println(person.toString());
    }

    @Override
    public void savePersonList(List<Person> personList) {
        for (Person person : personList){
            ((PersonService)AopContext.currentProxy()).savePerson(person);
        }
    }
}

      

localhost:8080/person/hello,控制台输出:

2022-04-29 19:20:56.404 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [com.example.demo.service.impl.PersonServiceImpl.savePerson]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
2022-04-29 19:20:56.504 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] for JDBC transaction
2022-04-29 19:20:56.506 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] to manual commit
com.example.demo.pojo.Person@5274eadf
2022-04-29 19:20:56.558 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit
2022-04-29 19:20:56.558 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Committing JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca]
2022-04-29 19:20:56.566 DEBUG 1553 --- [nio-8080-exec-2] o.s.jdbc.support.JdbcTransactionManager  : Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] after transaction

        

localhost:8080/person/hello2,控制台输出:

2022-04-29 19:20:59.104 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Creating new transaction with name [com.example.demo.service.impl.PersonServiceImpl.savePerson]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
2022-04-29 19:20:59.105 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Acquired Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] for JDBC transaction
2022-04-29 19:20:59.105 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Switching JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] to manual commit
com.example.demo.pojo.Person@7dd87670
2022-04-29 19:20:59.115 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Initiating transaction commit
2022-04-29 19:20:59.115 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Committing JDBC transaction on Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca]
2022-04-29 19:20:59.121 DEBUG 1553 --- [nio-8080-exec-1] o.s.jdbc.support.JdbcTransactionManager  : Releasing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@79889fca] after transaction

此时,savePerson方法触发了事务操作

         

                   

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值