Activiti与Spring整合事务失效问题解决

文章转自 www.youngboy.vip

检查点

1. 检查Activiti事务配置

检查Activiti事务配置是否正确,如果是引入的是自动配置包应该是配置正确的

public SpringProcessEngineConfiguration processEngineConfiguration() {
        SpringProcessEngineConfiguration springProcessEngineConfiguration = new SpringProcessEngineConfiguration();
        springProcessEngineConfiguration.setAnnotationFontName("宋体");
        springProcessEngineConfiguration.setLabelFontName("宋体");
        springProcessEngineConfiguration.setActivityFontName("宋体");
        // 重点配置
        springProcessEngineConfiguration.setDataSource(dataSource);
        // 重点配置
        springProcessEngineConfiguration.setTransactionManager(transactionManager);
        springProcessEngineConfiguration.setDbIdentityUsed(false);
        springProcessEngineConfiguration.setIdGenerator(idGenerator);
        return springProcessEngineConfiguration;
    }

2. 检查连接池AutoCommit配置

如果autoCommit配置为true,事务会自动提交,流程数据就不会回滚

不能改autoCommit的解决方案

思路:拓展 mybatis 事务工厂,与spring事务整合

step1: spring管理事务类

public class SpringManagedTransaction implements Transaction {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringManagedTransaction.class);

    private final DataSource dataSource;

    private Connection connection;

    private boolean isConnectionTransactional;

    private boolean autoCommit;

    public SpringManagedTransaction(DataSource dataSource) {
        notNull(dataSource, "No DataSource specified");
        this.dataSource = dataSource;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Connection getConnection() throws SQLException {
        if (this.connection == null) {
            openConnection();
        }
        return this.connection;
    }

    /**
     * Gets a connection from Spring transaction manager and discovers if this {@code Transaction} should manage
     * connection or let it to Spring.
     * <p>
     * It also reads autocommit setting because when using Spring Transaction MyBatis thinks that autocommit is always
     * false and will always call commit/rollback so we need to no-op that calls.
     */
    private void openConnection() throws SQLException {
        this.connection = DataSourceUtils.getConnection(this.dataSource);
        this.autoCommit = false;
        connection.setAutoCommit(false);
        this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);

        LOGGER.debug("JDBC Connection [" + this.connection + "] 将"
            + (this.isConnectionTransactional ? " " : " not ") + "会被Spring管理");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void commit() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            LOGGER.debug("提交jdbc连接 [" + this.connection + "]");
            this.connection.commit();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void rollback() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            LOGGER.debug("回滚jdbc连接 [" + this.connection + "]");
            this.connection.rollback();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() {
        LOGGER.debug("关闭jdbc连接 [" + this.connection + "]");
//        try {
//            connection.setAutoCommit(true);
//        } catch (SQLException e) {
//            LOGGER.error("jdbc连接设置autoCommit失败",e);
//        }
        DataSourceUtils.releaseConnection(this.connection, this.dataSource);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Integer getTimeout() {
        ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (holder != null && holder.hasTimeout()) {
            return holder.getTimeToLiveInSeconds();
        }
        return null;
    }

}

step2: 创建Spring 事务工厂

public class SpringManagedTransactionFactory implements TransactionFactory {

    /**
     * {@inheritDoc}
     */
    @Override
    public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
        return new SpringManagedTransaction(dataSource);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Transaction newTransaction(Connection conn) {
        throw new UnsupportedOperationException("使用 Spring transactions 需要数据源,不支持从Connection获取事务");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setProperties(Properties props) {
        // not needed in this version
    }

}

step3: 配置到 SpringProcessEngineConfiguration

@Bean
    public SpringProcessEngineConfiguration processEngineConfiguration() {
        SpringProcessEngineConfiguration springProcessEngineConfiguration = new SpringProcessEngineConfiguration();
        springProcessEngineConfiguration.setAnnotationFontName("宋体");
        springProcessEngineConfiguration.setLabelFontName("宋体");
        springProcessEngineConfiguration.setActivityFontName("宋体");
        springProcessEngineConfiguration.setDataSource(dataSource);
        springProcessEngineConfiguration.setTransactionManager(transactionManager);
        springProcessEngineConfiguration.setDbIdentityUsed(false);
        springProcessEngineConfiguration.setIdGenerator(idGenerator);
        //设置事务工厂
        springProcessEngineConfiguration.setTransactionFactory(managedTransaction());
        return springProcessEngineConfiguration;
    }

	/**
	* 生成mybatis事务工厂
	*/
    private SpringManagedTransactionFactory managedTransaction() {
        SpringManagedTransactionFactory managedTransaction = new SpringManagedTransactionFactory();
        return managedTransaction;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章