mybatis多线程如何保证事务统一

下面是mybatis多线程如何保证事务统一示例

@Service
public class TestServiceImpl implements TestService {

    @Autowired
    DataSource dataSource;

    @Autowired
    SqlSessionFactory sessionFactory;
    
    @Autowired
    SqlSessionTemplate sqlSessionTemplate;
    
    @Autowired
    TestServiceImpl testServiceImpl;

@Transactional(rollbackFor = Exception.class)
    public void tsetttt(){
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //int nThreads = Runtime.getRuntime().availableProcessors();
        int defaultMaxPoolSize = 6 ;
        int defaultCorePoolSize = 6;
        taskExecutor.setCorePoolSize(defaultCorePoolSize);
        taskExecutor.setMaxPoolSize(defaultMaxPoolSize);
        taskExecutor.setAllowCoreThreadTimeOut(true);
        taskExecutor.setQueueCapacity(10);
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setThreadFactory(new CustomizableThreadFactory("test-"));
        taskExecutor.afterPropertiesSet();

        //获取mybatis的sqlsession,主要是为了把SqlSessionHolder放入ThreadLocal
        //如果在这个事务里前面有查询语句了可以不用这一步
         SqlSession sqlSession = SqlSessionUtils.getSqlSession(sessionFactory,
            sqlSessionTemplate.getExecutorType(),
            sqlSessionTemplate.getPersistenceExceptionTranslator());
         SqlSessionUtils.closeSqlSession(sqlSession, sessionFactory);
         
        //获取主线程的spring事务holder
        ConnectionHolder conHolder =
                (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        //获取mybatis SqlSessionHolder
        SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
        

        List<String> strings = new ArrayList<>();
        strings.add("11111");
        strings.add("22222");
        List<Future<Integer>> futures = new ArrayList<>();
        for (String string : strings) {
            Future<Integer> future = billOutTaskExecutor.submit(() -> {
                //把主线程的spring 的 holder放入当前多线程ThreadLocal 这一步是使该线程已经存在事务
                TransactionSynchronizationManager.bindResource(dataSource, conHolder);
                //把主线程的SqlSessionHolder放入当前多线程ThreadLocal 这一步是使该线程已经存在session
                TransactionSynchronizationManager.bindResource(sessionFactory, holder);
                Integer updatefgfff = 0;
                try {
                    updatefgfff = testServiceImpl.updatefgfff(string);
                } catch (Exception e) {
                    log.error("Exception ", e);
                } finally {
                    //清除当前线程的ThreadLocal
                    TransactionSynchronizationManager.clear();
                    TransactionSynchronizationManager.unbindResource(dataSource);
                    TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory);
                }
                return updatefgfff;
            });
            futures.add(future);
        }

        for (Future<Integer> future : futures) {
            try {
                System.out.println(future.get());
            } catch (Exception e) {
                log.error("Exception: ", e);
            }
        }
        LambdaUpdateWrapper<Entity> objectLambdaUpdateWrapper = Wrappers.lambdaUpdate();
        xxxMapper.update(null, objectLambdaUpdateWrapper);
        System.out.println(1/0);
    }

    @Transactional(rollbackFor = Exception.class)
    public Integer updatefgfff(String ff){
        LambdaUpdateWrapper<Entity> objectLambdaUpdateWrapper1 = Wrappers.lambdaUpdate();
        
        int update;

         //多线程操作数据库一定要加锁,不然会报错 java.lang.ArrayIndexOutOfBoundsException: 2
        synchronized (BillInternalAccImpl_ply.class) {
            update = xxxMapper.update(null, objectLambdaUpdateWrapper1);
        }
         return update;
    }

}

参考
1,mybatis源码 :
org.mybatis.spring.SqlSessionUtils类里面的
getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator)

2,spring的事务代码:AbstractPlatformTransactionManager类
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)方法

下面这一段源码可以自己去看一下

mybatis源码:
public final class SqlSessionUtils {
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {

    notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED);
    notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);

    SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

    SqlSession session = sessionHolder(executorType, holder);
    if (session != null) {
      return session;
    }

    LOGGER.debug(() -> "Creating a new SqlSession");
    session = sessionFactory.openSession(executorType);

    registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

    return session;
  }
}
spring事务源码:
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    @Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

        //这一步是重点 
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();
        //这一步是判断是否已经存在事务
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}

}

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
  protected Object doGetTransaction() {
        DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
        txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
        ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.obtainDataSource());
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }
}

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
	   protected boolean isExistingTransaction(Object transaction) {
	        DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
	        return txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive();
	    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值