mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-06 16:48:24 +08:00
feat: add BaseMapper.selectCursorByQuery()
This commit is contained in:
parent
dc39e6083b
commit
7eaab96e35
@ -27,6 +27,7 @@ import com.mybatisflex.core.table.TableInfoFactory;
|
||||
import com.mybatisflex.core.util.*;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.apache.ibatis.builder.annotation.ProviderContext;
|
||||
import org.apache.ibatis.cursor.Cursor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
@ -442,6 +443,17 @@ public interface BaseMapper<T> {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 query 来构建条件查询游标数据 Cursor
|
||||
* 该方法必须在事务中才能正常使用,非事务下无法获取数据
|
||||
*
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 游标数据 Cursor
|
||||
*/
|
||||
@SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
|
||||
Cursor<T> selectCursorByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据 query 来构建条件查询数据列表,要求返回的数据为 asType
|
||||
|
||||
@ -34,6 +34,7 @@ import org.apache.ibatis.executor.keygen.KeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
|
||||
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
||||
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
||||
import org.apache.ibatis.executor.statement.StatementHandler;
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
@ -93,6 +94,17 @@ public class FlexConfiguration extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement
|
||||
, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
|
||||
// ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler,
|
||||
// resultHandler, boundSql, rowBounds);
|
||||
ResultSetHandler resultSetHandler = new FlexResultSetHandler(executor, mappedStatement, parameterHandler,
|
||||
resultHandler, boundSql, rowBounds);
|
||||
return (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换为 FlexStatementHandler,主要用来为实体类的多主键做支持、和数据审计
|
||||
* FlexStatementHandler 和 原生的 RoutingStatementHandler 对比,没有任何性能影响
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.mybatisflex.core.mybatis;
|
||||
|
||||
import com.mybatisflex.core.transaction.TransactionContext;
|
||||
import org.apache.ibatis.cursor.Cursor;
|
||||
import org.apache.ibatis.cursor.defaults.DefaultCursor;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
||||
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class FlexResultSetHandler extends DefaultResultSetHandler {
|
||||
|
||||
public FlexResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) {
|
||||
super(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {
|
||||
return new FlexCursor<>(super.handleCursorResultSets(stmt));
|
||||
}
|
||||
|
||||
static class FlexCursor<T> extends DefaultCursor<T> {
|
||||
|
||||
private Cursor originalCursor;
|
||||
|
||||
public FlexCursor(Cursor cursor) {
|
||||
super(null, null, null, null);
|
||||
this.originalCursor = cursor;
|
||||
TransactionContext.holdCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
//非事务场景下,通过 releaseCursor 对 cursor 进行 close
|
||||
if (TransactionContext.getXID() == null) {
|
||||
TransactionContext.releaseCursor();
|
||||
}
|
||||
//else 在事务的场景下,由事务主动关闭
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return originalCursor.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsumed() {
|
||||
return originalCursor.isConsumed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentIndex() {
|
||||
return originalCursor.getCurrentIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
try {
|
||||
return originalCursor.iterator();
|
||||
} catch (IllegalStateException e) {
|
||||
if (TransactionContext.getXID() == null) {
|
||||
throw new IllegalStateException(e.getMessage() + " Cursor must use in transaction.");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
|
||||
@Override
|
||||
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
|
||||
try {
|
||||
// 需要 mybaits v3.5.13+
|
||||
// 需要 mybatis v3.5.13+
|
||||
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
||||
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, reader, environment, properties);
|
||||
return build(parser.parse());
|
||||
@ -59,7 +59,7 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
|
||||
@Override
|
||||
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
|
||||
try {
|
||||
// 需要 mybaits v3.5.13+
|
||||
// 需要 mybatis v3.5.13+
|
||||
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
||||
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, inputStream, environment, properties);
|
||||
return build(parser.parse());
|
||||
|
||||
@ -16,11 +16,16 @@
|
||||
package com.mybatisflex.core.transaction;
|
||||
|
||||
|
||||
import org.apache.ibatis.cursor.Cursor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TransactionContext {
|
||||
|
||||
private TransactionContext() {}
|
||||
|
||||
private static final ThreadLocal<String> XID_HOLDER = new ThreadLocal<>();
|
||||
private static final ThreadLocal<Cursor<?>> CURSOR_HOLDER = new ThreadLocal<>();
|
||||
|
||||
public static String getXID() {
|
||||
return XID_HOLDER.get();
|
||||
@ -28,10 +33,29 @@ public class TransactionContext {
|
||||
|
||||
public static void release() {
|
||||
XID_HOLDER.remove();
|
||||
releaseCursor();
|
||||
}
|
||||
|
||||
public static void hold(String xid) {
|
||||
public static void releaseCursor() {
|
||||
try {
|
||||
Cursor<?> cursor = CURSOR_HOLDER.get();
|
||||
if (cursor != null){
|
||||
try {
|
||||
cursor.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
CURSOR_HOLDER.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public static void holdXID(String xid) {
|
||||
XID_HOLDER.set(xid);
|
||||
}
|
||||
|
||||
public static void holdCursor(Cursor<?> cursor) {
|
||||
CURSOR_HOLDER.set(cursor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ public class TransactionalManager {
|
||||
} finally {
|
||||
//恢复上一级事务
|
||||
if (currentXID != null) {
|
||||
TransactionContext.hold(currentXID);
|
||||
TransactionContext.holdXID(currentXID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,7 +147,7 @@ public class TransactionalManager {
|
||||
|
||||
public static String startTransactional() {
|
||||
String xid = UUID.randomUUID().toString();
|
||||
TransactionContext.hold(xid);
|
||||
TransactionContext.holdXID(xid);
|
||||
return xid;
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ public class FlexTransactionManager extends AbstractPlatformTransactionManager {
|
||||
@Override
|
||||
protected void doResume(Object transaction, Object suspendedResources) throws TransactionException {
|
||||
String xid = (String) suspendedResources;
|
||||
TransactionContext.hold(xid);
|
||||
TransactionContext.holdXID(xid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -19,13 +19,16 @@ import com.mybatisflex.core.MybatisFlexBootstrap;
|
||||
import com.mybatisflex.core.audit.AuditManager;
|
||||
import com.mybatisflex.core.audit.ConsoleMessageCollector;
|
||||
import com.mybatisflex.core.audit.MessageCollector;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Db;
|
||||
import org.apache.ibatis.cursor.Cursor;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
|
||||
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
|
||||
|
||||
@ -138,8 +141,30 @@ public class EntityTestStarter {
|
||||
//
|
||||
// List<ArticleDTO> articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class);
|
||||
// System.out.println(articleDTOS);
|
||||
Page<ArticleDTO01> paginate = accountMapper.paginateAs(Page.of(1, 10), asWrapper, ArticleDTO01.class);
|
||||
System.out.println(paginate);
|
||||
// Page<ArticleDTO01> paginate = accountMapper.paginateAs(Page.of(1, 10), asWrapper, ArticleDTO01.class);
|
||||
// System.out.println(paginate);
|
||||
|
||||
Db.tx(new Supplier<Boolean>() {
|
||||
@Override
|
||||
public Boolean get() {
|
||||
Cursor<Account> accounts = accountMapper.selectCursorByQuery(asWrapper);
|
||||
System.out.println(accounts.isOpen());
|
||||
for (Account account : accounts) {
|
||||
System.out.println(accounts.isOpen());
|
||||
System.out.println(account);
|
||||
}
|
||||
System.out.println(accounts.isOpen());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Cursor<Account> accounts = accountMapper.selectCursorByQuery(asWrapper);
|
||||
// System.out.println(accounts.isOpen());
|
||||
// for (Account account : accounts) {
|
||||
// System.out.println(accounts.isOpen());
|
||||
// System.out.println(account);
|
||||
// }
|
||||
// System.out.println(accounts.isOpen());
|
||||
|
||||
|
||||
// QueryWrapper queryWrapper = new QueryWrapper();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user