mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 17:48:25 +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 com.mybatisflex.core.util.*;
|
||||||
import org.apache.ibatis.annotations.*;
|
import org.apache.ibatis.annotations.*;
|
||||||
import org.apache.ibatis.builder.annotation.ProviderContext;
|
import org.apache.ibatis.builder.annotation.ProviderContext;
|
||||||
|
import org.apache.ibatis.cursor.Cursor;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -442,6 +443,17 @@ public interface BaseMapper<T> {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 query 来构建条件查询游标数据 Cursor
|
||||||
|
* 该方法必须在事务中才能正常使用,非事务下无法获取数据
|
||||||
|
*
|
||||||
|
* @param queryWrapper 查询条件
|
||||||
|
* @return 游标数据 Cursor
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery")
|
||||||
|
Cursor<T> selectCursorByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 query 来构建条件查询数据列表,要求返回的数据为 asType
|
* 根据 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.NoKeyGenerator;
|
||||||
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
|
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
|
||||||
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
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.executor.statement.StatementHandler;
|
||||||
import org.apache.ibatis.mapping.*;
|
import org.apache.ibatis.mapping.*;
|
||||||
import org.apache.ibatis.session.*;
|
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,主要用来为实体类的多主键做支持、和数据审计
|
||||||
* FlexStatementHandler 和 原生的 RoutingStatementHandler 对比,没有任何性能影响
|
* 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
|
@Override
|
||||||
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
|
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
|
||||||
try {
|
try {
|
||||||
// 需要 mybaits v3.5.13+
|
// 需要 mybatis v3.5.13+
|
||||||
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
||||||
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, reader, environment, properties);
|
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, reader, environment, properties);
|
||||||
return build(parser.parse());
|
return build(parser.parse());
|
||||||
@ -59,7 +59,7 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
|
|||||||
@Override
|
@Override
|
||||||
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
|
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
|
||||||
try {
|
try {
|
||||||
// 需要 mybaits v3.5.13+
|
// 需要 mybatis v3.5.13+
|
||||||
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
// https://github.com/mybatis/mybatis-3/commit/d7826d71a7005a8b4d4e0e7a020db0f6c7e253a4
|
||||||
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, inputStream, environment, properties);
|
XMLConfigBuilder parser = new XMLConfigBuilder(FlexConfiguration.class, inputStream, environment, properties);
|
||||||
return build(parser.parse());
|
return build(parser.parse());
|
||||||
|
|||||||
@ -16,11 +16,16 @@
|
|||||||
package com.mybatisflex.core.transaction;
|
package com.mybatisflex.core.transaction;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.ibatis.cursor.Cursor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class TransactionContext {
|
public class TransactionContext {
|
||||||
|
|
||||||
private TransactionContext() {}
|
private TransactionContext() {}
|
||||||
|
|
||||||
private static final ThreadLocal<String> XID_HOLDER = new ThreadLocal<>();
|
private static final ThreadLocal<String> XID_HOLDER = new ThreadLocal<>();
|
||||||
|
private static final ThreadLocal<Cursor<?>> CURSOR_HOLDER = new ThreadLocal<>();
|
||||||
|
|
||||||
public static String getXID() {
|
public static String getXID() {
|
||||||
return XID_HOLDER.get();
|
return XID_HOLDER.get();
|
||||||
@ -28,10 +33,29 @@ public class TransactionContext {
|
|||||||
|
|
||||||
public static void release() {
|
public static void release() {
|
||||||
XID_HOLDER.remove();
|
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);
|
XID_HOLDER.set(xid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void holdCursor(Cursor<?> cursor) {
|
||||||
|
CURSOR_HOLDER.set(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,7 +113,7 @@ public class TransactionalManager {
|
|||||||
} finally {
|
} finally {
|
||||||
//恢复上一级事务
|
//恢复上一级事务
|
||||||
if (currentXID != null) {
|
if (currentXID != null) {
|
||||||
TransactionContext.hold(currentXID);
|
TransactionContext.holdXID(currentXID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ public class TransactionalManager {
|
|||||||
|
|
||||||
public static String startTransactional() {
|
public static String startTransactional() {
|
||||||
String xid = UUID.randomUUID().toString();
|
String xid = UUID.randomUUID().toString();
|
||||||
TransactionContext.hold(xid);
|
TransactionContext.holdXID(xid);
|
||||||
return xid;
|
return xid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public class FlexTransactionManager extends AbstractPlatformTransactionManager {
|
|||||||
@Override
|
@Override
|
||||||
protected void doResume(Object transaction, Object suspendedResources) throws TransactionException {
|
protected void doResume(Object transaction, Object suspendedResources) throws TransactionException {
|
||||||
String xid = (String) suspendedResources;
|
String xid = (String) suspendedResources;
|
||||||
TransactionContext.hold(xid);
|
TransactionContext.holdXID(xid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -19,13 +19,16 @@ import com.mybatisflex.core.MybatisFlexBootstrap;
|
|||||||
import com.mybatisflex.core.audit.AuditManager;
|
import com.mybatisflex.core.audit.AuditManager;
|
||||||
import com.mybatisflex.core.audit.ConsoleMessageCollector;
|
import com.mybatisflex.core.audit.ConsoleMessageCollector;
|
||||||
import com.mybatisflex.core.audit.MessageCollector;
|
import com.mybatisflex.core.audit.MessageCollector;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
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.EmbeddedDatabaseBuilder;
|
||||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
|
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
|
||||||
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
|
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
|
||||||
|
|
||||||
@ -138,8 +141,30 @@ public class EntityTestStarter {
|
|||||||
//
|
//
|
||||||
// List<ArticleDTO> articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class);
|
// List<ArticleDTO> articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class);
|
||||||
// System.out.println(articleDTOS);
|
// System.out.println(articleDTOS);
|
||||||
Page<ArticleDTO01> paginate = accountMapper.paginateAs(Page.of(1, 10), asWrapper, ArticleDTO01.class);
|
// Page<ArticleDTO01> paginate = accountMapper.paginateAs(Page.of(1, 10), asWrapper, ArticleDTO01.class);
|
||||||
System.out.println(paginate);
|
// 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();
|
// QueryWrapper queryWrapper = new QueryWrapper();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user