001/*
002 *  Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.spring;
017
018import com.mybatisflex.core.datasource.FlexDataSource;
019import com.mybatisflex.core.transaction.TransactionContext;
020import com.mybatisflex.core.util.StringUtil;
021import org.apache.ibatis.transaction.Transaction;
022
023import javax.sql.DataSource;
024import java.sql.Connection;
025import java.sql.SQLException;
026
027/**
028 * spring 事务支持,解决 issues: https://gitee.com/mybatis-flex/mybatis-flex/issues/I7HJ4J
029 *
030 * @author life
031 * @author michael
032 */
033public class FlexSpringTransaction implements Transaction {
034
035    private final DataSource dataSource;
036    private Boolean isConnectionTransactional;
037    private Boolean autoCommit;
038    private Connection connection;
039
040    public FlexSpringTransaction(DataSource dataSource) {
041        this.dataSource = dataSource;
042    }
043
044    @Override
045    public Connection getConnection() throws SQLException {
046        if (isConnectionTransactional == null) {
047            connection = dataSource.getConnection();
048            isConnectionTransactional = StringUtil.hasText(TransactionContext.getXID());
049            autoCommit = connection.getAutoCommit();
050            return connection;
051        }
052        // 在事务中,通过 FlexDataSource 去获取
053        // FlexDataSource 内部会进行 connection 缓存以及多数据源下的 key 判断
054        else if (isConnectionTransactional) {
055            return dataSource.getConnection();
056        }
057        // 非事务,返回当前链接
058        else {
059            return connection;
060        }
061    }
062
063    @Override
064    public void commit() throws SQLException {
065        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
066            this.connection.commit();
067        }
068    }
069
070    @Override
071    public void rollback() throws SQLException {
072        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
073            this.connection.rollback();
074        }
075    }
076
077    @Override
078    public void close() throws SQLException {
079        if (this.connection != null && !this.isConnectionTransactional) {
080            connection.close();
081        }
082    }
083
084    @Override
085    public Integer getTimeout() throws SQLException {
086        return TimeoutHolder.getTimeToLiveInSeconds();
087    }
088}