springboot加mybatis线程中编程式事务回滚问题

spring boot加mybatis编程式事务在线程中回滚事务时,每隔一段时间会出现执行回滚方法依旧会提交事务问题

在Service层的线程方法,为了保证数据添加的正确所以加了锁。
线程里面有两个方法,为了保证添加时候数据正确,所以如果有方法出现错误就会实现事务回滚。
package com.pt.service;

import com.pt.dao.TicketInspectRecordDao;
import com.pt.model.TicketInspectRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.util.Date;

@Service
public class TicketInspectRecordService {

    @Autowired
    private TicketProductService ticketProductService;
    @Autowired
    private SchedulingService schedulingService;

    @Autowired
    private TicketInspectRecordDao ticketInspectRecordDao;

    @Autowired
    private PlatformTransactionManager transactionManager;

    private Integer stock = 0;

    private final static Object obj = new Object();

    private String msg = "false";

    public String ticket(Integer sd_id) {
        if (sd_id != null) {
            this.stock = schedulingService.findStock(sd_id);
        }
        if (this.stock > 0) {
            TicketInspectRecord ticketInspectRecord = new TicketInspectRecord();
            ticketInspectRecord.setTir_tcr_id(1);
            ticketInspectRecord.setTir_tp_id(1);
            ticketInspectRecord.setTir_u_id(1);
            ticketInspectRecord.setTir_date(new Date());
            Thread thread = new Thread() {
                @Override
                public void run() {
                    synchronized (obj) {
                        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                        TransactionStatus status = transactionManager.getTransaction(def);
                        try {
                            ticketInspectRecordDao.inTicket(ticketInspectRecord);
                            ticketInspectRecordDao.uStock(sd_id);//这一句必报错误,然后进入rollback方法
                            msg = "true";
                            transactionManager.commit(status);
                        } catch (Exception e) {
                            e.printStackTrace();
                            transactionManager.rollback(status);
                            msg = "false";
                        }
                    }
                }
            };
            thread.start();
            try {
                thread.join();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        return msg;
    }

}

奇怪的是在执行回滚的时候,有时候即便回滚了,方法ticketInspectRecordDao.inTicket(ticketInspectRecord)依旧会向数据库里插入数据,但是这种情况不是一直都会,项目重启的时候或者隔一段时间重新运行一次,就会出现这种情况。
研究了很久了,一直搞不明白问题在哪里

#Java##Spring#
全部评论
我自己排查了好久,发现在执行rollback方法的时候,它会DataSourceTransactionManager.class的doCleanupAfterCompletion方法,在里面有一步执行了 con.setAutoCommit(true)的时候,事务就自己提交上去了。 但是还是那个问题,奇怪的是它并不是一直都有这个情况出现,是我在重启项目,或者隔个几分钟重新执行一次这方法时,事务才会自己提交,但是在提交了事务之后我又重新运行几遍代码,都没有问题
点赞 回复
分享
发布于 2019-08-16 16:36

相关推荐

点赞 2 评论
分享
牛客网
牛客企业服务