001/*
002 *  Copyright (c) 2022-2023, 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 java.sql.Connection;
024import java.sql.SQLException;
025
026/**
027 * spring 事务支持,解决 issues: https://gitee.com/mybatis-flex/mybatis-flex/issues/I7HJ4J
028 *
029 * @author life
030 * @author michael
031 */
032public class FlexSpringTransaction implements Transaction {
033
034    private final FlexDataSource dataSource;
035    private Boolean isConnectionTransactional;
036    private Boolean autoCommit;
037    private Connection connection;
038
039    public FlexSpringTransaction(FlexDataSource dataSource) {
040        this.dataSource = dataSource;
041    }
042
043    @Override
044    public Connection getConnection() throws SQLException {
045        if (isConnectionTransactional == null) {
046            connection = dataSource.getConnection();
047            isConnectionTransactional = StringUtil.isNotBlank(TransactionContext.getXID());
048            autoCommit = connection.getAutoCommit();
049            return connection;
050        }
051        // 在事务中,通过 FlexDataSource 去获取
052        // FlexDataSource 内部会进行 connection 缓存以及多数据源下的 key 判断
053        else if (isConnectionTransactional) {
054            return dataSource.getConnection();
055        }
056        // 非事务,返回当前链接
057        else {
058            return connection;
059        }
060    }
061
062    @Override
063    public void commit() throws SQLException {
064        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
065            this.connection.commit();
066        }
067    }
068
069    @Override
070    public void rollback() throws SQLException {
071        if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
072            this.connection.rollback();
073        }
074    }
075
076    @Override
077    public void close() throws SQLException {
078        if (this.connection != null && !this.isConnectionTransactional) {
079            connection.close();
080        }
081    }
082
083    @Override
084    public Integer getTimeout() throws SQLException {
085        return null;
086    }
087}