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.cursor.defaults.DefaultCursor; 021import org.apache.ibatis.executor.Executor; 022import org.apache.ibatis.executor.parameter.ParameterHandler; 023import org.apache.ibatis.executor.resultset.DefaultResultSetHandler; 024import org.apache.ibatis.mapping.BoundSql; 025import org.apache.ibatis.mapping.MappedStatement; 026import org.apache.ibatis.session.ResultHandler; 027import org.apache.ibatis.session.RowBounds; 028 029import java.sql.SQLException; 030import java.sql.Statement; 031import java.util.Iterator; 032 033public class FlexResultSetHandler extends DefaultResultSetHandler { 034 035 public FlexResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) { 036 super(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds); 037 } 038 039 @Override 040 public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException { 041 return new FlexCursor<>(super.handleCursorResultSets(stmt)); 042 } 043 044 static class FlexCursor<T> extends DefaultCursor<T> { 045 046 private Cursor originalCursor; 047 048 public FlexCursor(Cursor cursor) { 049 super(null, null, null, null); 050 this.originalCursor = cursor; 051 TransactionContext.holdCursor(cursor); 052 } 053 054 @Override 055 public void close() { 056 //非事务场景下,通过 releaseCursor 对 cursor 进行 close 057 if (TransactionContext.getXID() == null) { 058 TransactionContext.releaseCursor(); 059 } 060 //else 在事务的场景下,由事务主动关闭 061 } 062 063 @Override 064 public boolean isOpen() { 065 return originalCursor.isOpen(); 066 } 067 068 @Override 069 public boolean isConsumed() { 070 return originalCursor.isConsumed(); 071 } 072 073 @Override 074 public int getCurrentIndex() { 075 return originalCursor.getCurrentIndex(); 076 } 077 078 @Override 079 public Iterator<T> iterator() { 080 try { 081 return originalCursor.iterator(); 082 } catch (IllegalStateException e) { 083 if (TransactionContext.getXID() == null) { 084 throw new IllegalStateException(e.getMessage() + " Cursor must use in transaction."); 085 } 086 throw e; 087 } 088 } 089 } 090}