JTA事务多数据源建表:The command cannot be executed when global transaction is in the ACTIVE state

描述:

我遇到这个错误的场景是多数据源,读取第一个数据源的配置表信息,再切换到第二个数据源创建表的时候会报错(主数据源创建表不会报错,第二个数据源增删改查正常):XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state。

再交代一下数据源,事务方面的情况:两个数据源,使用hibernate的sessionFactory管理,事务由于项目使用了activity,使用的是JtaTransactionManager,具体的transactionManager为:bitronixTransactionManager。

解决过程:

报错提示很清晰明了global transaction 在active状态,网上查了不少资料,都是大同小异到处转抄的,并没有实际解决问题,无奈自己倒腾。

既然是事务,那就涉及事务传播,在org.springframework.transaction.TransactionDefinition中定义了几种事务传播行为,最开始想到的是自己手动提交事务,于是设置事务传播属性为:PROPAGATION_REQUIRES_NEW,但是问题依然存在,于是想到使用PROPAGATION_NOT_SUPPORTED,但是使用session提交的时候会抛出:找不到当前JTA transaction的异常。那我们最终可以绕过hibernate,使用jdbc来直接提交,问题得到解决。

下面附上关键代码:

		JtaTransactionManager tm = BeanFactory.getBean(BeanAttribute.TRANSACTION_MANAGER);
		DefaultTransactionDefinition def = BeanFactory.getObject(DefaultTransactionDefinition.class);

		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
		TransactionStatus status = tm.getTransaction(def);
		Connection connection=null;
		Statement statement=null;
		try {
			PoolingDataSource dataSource = BeanFactory.getBean("dataSource.1");
			connection = dataSource.getConnection();
			statement = connection.createStatement();
			statement.execute("CREATE TABLE second_datasource_table (" +
					"  `UUID` varchar(32) COLLATE utf8_bin NOT NULL," +
					"  `OPERSTATUS` varchar(1) COLLATE utf8_bin DEFAULT NULL," +
					"  PRIMARY KEY (`UUID`)" +
					") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT;");
			tm.commit(status);
		} catch (Exception e) {
			tracer.error(e);
			tm.rollback(status);
		} finally {
			if(statement!=null){
				try {
					statement.close();
				} catch (SQLException e) {
					tracer.error(e);
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					tracer.error(e);
				}
			}
		}

你可能感兴趣的:(java,java,global,transaction,多数据源建表)