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.core.mybatis;
017
018import com.mybatisflex.core.transaction.TransactionContext;
019import org.apache.ibatis.cursor.Cursor;
020import org.apache.ibatis.executor.Executor;
021import org.apache.ibatis.executor.parameter.ParameterHandler;
022import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
023import org.apache.ibatis.mapping.BoundSql;
024import org.apache.ibatis.mapping.MappedStatement;
025import org.apache.ibatis.session.ResultHandler;
026import org.apache.ibatis.session.RowBounds;
027
028import java.sql.SQLException;
029import java.sql.Statement;
030import java.util.Iterator;
031
032public class FlexResultSetHandler extends DefaultResultSetHandler {
033
034    public FlexResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler
035        , ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) {
036        super(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
037    }
038
039
040    /**
041     * 从写 handleCursorResultSets, 用于适配在事务下自动关闭 Cursor
042     */
043    @Override
044    public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {
045        Cursor<E> defaultCursor = super.handleCursorResultSets(stmt);
046
047        //in transaction
048        if (TransactionContext.getXID() != null) {
049            return new FlexCursor<>(defaultCursor);
050        }
051
052        return defaultCursor;
053    }
054
055
056    static class FlexCursor<T> implements Cursor<T> {
057
058        private final Cursor<T> originalCursor;
059
060        public FlexCursor(Cursor<T> cursor) {
061            this.originalCursor = cursor;
062            TransactionContext.holdCursor(cursor);
063        }
064
065        @Override
066        public void close() {
067            // do nothing
068            // 由 TransactionContext 去关闭
069        }
070
071        @Override
072        public boolean isOpen() {
073            return originalCursor.isOpen();
074        }
075
076        @Override
077        public boolean isConsumed() {
078            return originalCursor.isConsumed();
079        }
080
081        @Override
082        public int getCurrentIndex() {
083            return originalCursor.getCurrentIndex();
084        }
085
086        @Override
087        public Iterator<T> iterator() {
088            return originalCursor.iterator();
089        }
090
091    }
092
093}