Spring+Mybatis配置自定义线程事务管理

Mybatis配置文件可配置事务管理模式

XML 复制代码
<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <!-- 数据源配置 -->
        </dataSource>
    </environment>
</environments>

事务管理模式配置

1. JDBC 事务管理器(JDBC Transaction Manager)

特点:直接使用 JDBC 的事务管理机制

配置:通过 JdbcTransactionFactory 类实现

适用场景:简单的单数据源应用

2. 外部事务管理器(MANAGED Transaction Manager)

特点:将事务管理委托给外部容器(如 Spring、JBoss 等)

配置:通过 ManagedTransactionFactory 类实现

适用场景:集成到支持事务管理的框架中

3. 自定义事务管理器

特点:允许开发者实现自己的事务管理逻辑

配置:通过实现 TransactionFactory 接口来自定义事务行为

|---------|------|---------|------|
| 事务管理器 | 事务控制 | 提交回滚 | 适用场景 |
| JDBC | 直接控制 | 手动提交/回滚 | 简单应用 |
| MANAGED | 容器控制 | 容器自动管理 | 框架集成 |

自定义实现,基于JDBC的基础上

自定提交事务实现

java 复制代码
package com.lym.system.core.transaction;

import org.apache.ibatis.transaction.Transaction;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;


public class LymTransaction  implements Transaction {

    private final DataSource dataSource;
    private Connection connection;
    private boolean isConnectionTransactional;
    private boolean autoCommit;

//    public GyTransaction(DataSource dataSource) {
//        this.dataSource = dataSource;
//    }

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

    public Connection getConnection() throws SQLException {
        if (this.connection == null) {
            this.openConnection();
        }

        return this.connection;
    }

    private void openConnection() throws SQLException {
        this.connection = DataSourceUtils.getConnection(this.dataSource);
        this.connection.setAutoCommit(true);
        this.autoCommit = this.connection.getAutoCommit();
        this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
    }

    public void commit() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            this.connection.commit();
        }

    }

    public void rollback() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            this.connection.rollback();
        }

    }

    public void close() throws SQLException {
        if (this.connection != null) {
            this.connection.setAutoCommit(this.autoCommit);
            DataSourceUtils.releaseConnection(this.connection, this.dataSource);
        }

    }

    public Integer getTimeout() throws SQLException {
        ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
        return holder != null && holder.hasTimeout() ? holder.getTimeToLiveInSeconds() : null;
    }


}

手动控制事务提交实现

java 复制代码
package com.lym.system.core.transaction;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.transaction.Transaction;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;


public class LymThreadTransaction implements Transaction {
    private static final Log LOGGER = LogFactory.getLog(LymThreadTransaction.class);
    private final DataSource dataSource;
    private Connection connection;
    private boolean isConnectionTransactional;
    private boolean autoCommit;

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

    public Connection getConnection() throws SQLException {
        if (this.connection == null) {
            this.openConnection();
        }

        return this.connection;
    }

    private void openConnection() throws SQLException {
        this.connection = DataSourceUtils.getConnection(this.dataSource);
        this.autoCommit = this.connection.getAutoCommit();
        this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
    }

    public void commit() throws SQLException {
    }

    public void doCommit() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            this.connection.commit();
        }

    }

    public void doClose() throws SQLException {
        if (this.connection != null) {
            this.connection.setAutoCommit(this.autoCommit);
        }

        DataSourceUtils.releaseConnection(this.connection, this.dataSource);
    }

    public void rollback() throws SQLException {
        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
            this.connection.rollback();
        }

    }

    public void close() throws SQLException {
    }

    public Integer getTimeout() throws SQLException {
        ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
        return holder != null && holder.hasTimeout() ? holder.getTimeToLiveInSeconds() : null;
    }
}

事务管理器自定义实现

java 复制代码
package com.lym.system.core.transaction;

import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Properties;


public class LymTransactionFactory  implements TransactionFactory {
    private String dataSourceId;
    private ThreadLocal<Transaction> transactionLocal = new ThreadLocal();

    public LymTransactionFactory() {
    }

    public void setProperties(Properties props) {
    }

    public Transaction getTransaction() {
        return (Transaction)this.transactionLocal.get();
    }

    public void clear() {
        this.transactionLocal.set((Transaction) null);
    }

    public Transaction newTransaction(Connection conn) {
        throw new UnsupportedOperationException("New Spring transactions require a DataSource");
    }

    public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
        if (ManagerTransaction.isThreadTransaction()) {
            Transaction transaction = (Transaction)this.transactionLocal.get();
            if (transaction != null) {
                return transaction;
            } else {
                transaction = new LymThreadTransaction(dataSource);
                this.transactionLocal.set(transaction);
                ManagerTransaction.addTransactionFactory(this);
                return transaction;
            }
        } else {
            return new LymTransaction(dataSource);
        }
    }

    public String getDataSourceId() {
        return this.dataSourceId;
    }

    public void setDataSourceId(String dataSourceId) {
        this.dataSourceId = dataSourceId;
    }
}

线程事务管理器

java 复制代码
package com.lym.system.core.transaction;

import org.apache.ibatis.transaction.Transaction;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class ManagerTransaction {
    private static ThreadLocal<Boolean> threadTransaction = new ThreadLocal();
    private static ThreadLocal<List<LymTransactionFactory>> threadTransactionFactories = new ThreadLocal();

    public ManagerTransaction() {
    }

    public static boolean isThreadTransaction() {
        return threadTransaction.get() == null ? false : (Boolean)threadTransaction.get();
    }

    public static void setThreadTransaction(boolean isThreadTransaction) {
        threadTransaction.set(isThreadTransaction);
    }

    public static synchronized void addTransactionFactory(LymTransactionFactory transactionFactory) {
        List<LymTransactionFactory> lst = (List<LymTransactionFactory>)threadTransactionFactories.get();
        if (lst == null) {
            lst = new ArrayList();
            threadTransactionFactories.set(lst);
        }

        ((List<LymTransactionFactory>)lst).add(transactionFactory);
    }

    public static synchronized void commitAndClose() throws SQLException {
        List<LymTransactionFactory> lst = (List<LymTransactionFactory>)threadTransactionFactories.get();
        if (lst != null) {
            Iterator<LymTransactionFactory> it = lst.iterator();

            while(true) {
                while(true) {
                    if (!it.hasNext()) {
                        return;
                    }

                    LymTransactionFactory factory = (LymTransactionFactory)it.next();

                    try {
                        Transaction transaction = factory.getTransaction();
                        if (transaction != null) {
                            if (transaction instanceof LymThreadTransaction) {
                                try {
                                    ((LymThreadTransaction)transaction).doCommit();
                                } finally {
                                    ((LymThreadTransaction)transaction).doClose();
                                }
                            } else {
                                try {
                                    transaction.commit();
                                } finally {
                                    transaction.close();
                                }
                            }
                            break;
                        }
                    } finally {
                        factory.clear();
                    }
                }

                it.remove();
            }
        }
    }

    public static synchronized void rollbackAndClose() throws SQLException {
        List<LymTransactionFactory> lst = (List<LymTransactionFactory>)threadTransactionFactories.get();
        if (lst != null) {
            Iterator<LymTransactionFactory> it = lst.iterator();

            while(true) {
                while(true) {
                    if (!it.hasNext()) {
                        threadTransactionFactories.set((List<LymTransactionFactory>) null);
                        return;
                    }

                    LymTransactionFactory factory = (LymTransactionFactory)it.next();

                    try {
                        Transaction transaction = factory.getTransaction();
                        if (transaction != null) {
                            if (transaction instanceof LymThreadTransaction) {
                                try {
                                    transaction.rollback();
                                } finally {
                                    ((LymThreadTransaction)transaction).doClose();
                                }
                            } else {
                                try {
                                    transaction.rollback();
                                } finally {
                                    transaction.close();
                                }
                            }
                            break;
                        }
                    } finally {
                        factory.clear();
                    }
                }

                it.remove();
            }
        }
    }
}

测试

java 复制代码
 ManagerTransaction.setThreadTransaction(true);
        try {
            Integer i = sysUserSerivce.addUserInfo(lymUserV);
            //打印数据和执行结果
            System.out.println(lymUserV);
            System.out.println(i);
            
            if (needRollback) {
                // 测试回滚功能
                ManagerTransaction.rollbackAndClose();
                return ResultUtils.success("已执行回滚测试");
            } else {
                // 正常提交事务
                ManagerTransaction.commitAndClose();
                Map map = new HashMap<>();
                map.put("message", "添加成功");
                return ResultUtils.success(map);
            }
        } catch (Exception e) {
            try {
                // 发生异常时回滚
                ManagerTransaction.rollbackAndClose();
            } catch (SQLException rollbackEx) {
                System.err.println("回滚时发生异常: " + rollbackEx.getMessage());
            }
            return ResultUtils.fail("操作失败:" + e.getMessage());
        } finally {
            // 关闭线程事务
            ManagerTransaction.setThreadTransaction(false);
        }

其他

当前模式实现基于spring+mybatis的配置基础上实现,未使用代理对象,容器管理,如使用springboot请使用直接使用编程式事务管理、声明式事务管理

相关推荐
Hacker_seagull2 小时前
Java 8安装详细教程
java·开发语言
高山上有一只小老虎2 小时前
小红的矩阵染色
java·算法·矩阵
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于SpringBoot Vue居家办公管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
小当家.1052 小时前
《Java操作Excel实战教程:Apache POI从入门到精通》
java·apache·excel
Gofarlic_OMS2 小时前
MATLAB许可证闲置自动检测与智能提醒
java·大数据·运维·开发语言·人工智能·算法·matlab
yaoxin5211232 小时前
293. Java Stream API - 从 HTTP 源创建 Stream
java·开发语言·http
哟哟耶耶2 小时前
java-MySql下载与配置环境变量
java·开发语言·mysql
间彧2 小时前
通过自定义ClassLoader实现热部署与类隔离
java
间彧2 小时前
在Spring框架中如何结合RefreshScope实现更优雅的热部署方案?
spring