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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章