Merge remote-tracking branch 'origin/main'

This commit is contained in:
Suomm 2023-06-20 19:45:26 +08:00
commit d32f3ec83d
36 changed files with 573 additions and 315 deletions

View File

@ -1,3 +1,18 @@
mybatis-flex v1.4.1 20230620:
新增:分页查询 Page 对象添加否优化 count 查询的选项,感谢 @王帅
新增:添加 LogicDeleteProcessor.java 用于构建自定义的逻辑删除功能
优化:完善后添加类的相关注释、版权信息等内容,感谢 @王帅
优化QueryColumn 添加构造方法 QueryColumn(String tableName, String name)
修复Oracle 下的 as 关键字错误的问题
修复:多表联查时,逻辑删除字段和租户字段,只过滤主表,未过滤子表的问题 #I7EV67
修复:低版本 spring-cloud 使用 bootstrap.yml 拉取不到 nacos 中多数据源配置的问题,感谢 @王帅
修复:使用 druid-spring-boot-starter 时 mybatis-flex 多数据源不生效,感谢 @王帅
文档:更新 APT 文档,添加实体类不在同一个包说明,感谢 @王帅
文档:添加找不到依赖 faq 说明,感谢 @王帅
文档:逻辑删除添加关于 LogicDeleteProcessor 的相关文档
mybatis-flex v1.4.0 20230618:
新增LogicDeleteManager用于处理跳过逻辑删除的场景
新增BaseMapper 新增 insertWithPk 方法,用于插入带有主键的 Entity 数据

View File

@ -54,6 +54,51 @@ SELECT * FROM tb_account where id = ? and is_delete = 0
- selectCountBy**
- paginate
同时,比如 Left Join 或者子查询等,若 **子表也设置了逻辑删除字段** 那么子表也会添加相应的逻辑删除条件,例如:
```java
QueryWrapper query1 = QueryWrapper.create()
.select()
.from(ACCOUNT)
.leftJoin(ARTICLE).as("a").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.AGE.ge(10));
```
其执行的 SQL 如下:
```sql
SELECT * FROM `tb_account`
LEFT JOIN `tb_article` AS `a` ON `tb_account`.`id` = `a`.`account_id`
WHERE `tb_account`.`age` >= 10
AND `tb_account`.`is_delete` = 0 AND `a`.`is_delete` = 0
```
自动添加上 `tb_account.is_delete = 0 AND a.is_delete = 0` 条件。
示例 2
```java
QueryWrapper query2 = QueryWrapper.create()
.select()
.from(ACCOUNT)
.leftJoin(
//子查询
select().from(ARTICLE).where(ARTICLE.ID.ge(100))
).as("a").on(
ACCOUNT.ID.eq(raw("a.id"))
)
.where(ACCOUNT.AGE.ge(10));
```
其执行的 SQL 如下:
```sql
SELECT * FROM `tb_account`
LEFT JOIN (
SELECT * FROM `tb_article` WHERE `id` >= 100 AND `is_delete` = 0
) AS `a`
ON `tb_account`.`id` = a.id
WHERE `tb_account`.`age` >= 10 AND `tb_account`.`is_delete` = 0
```
## 逻辑删除的默认值配置
在某些场景下,我们可能希望数据库存入的逻辑删除中的值并非 0 和 1比如可能是 true 和 false 等,那么,我们可以通过配置 `FlexGlobalConfig`
@ -81,4 +126,39 @@ LogicDeleteManager.execWithoutLogicDelete(() ->
accountMapper.deleteById(1)
);
```
以上代码中,`accountMapper` 会直接对 `Account` 数据进行物理删除,忽略逻辑删除字段配置。
以上代码中,`accountMapper` 会直接对 `Account` 数据进行物理删除,忽略逻辑删除字段配置。
## 自定义逻辑删除处理功能
在社区中,有许多用户提出希望使用时间类型,当删除时,设置删除字段为`当前时间`,当正常时,设置为 `0` 或者 `null`
那么,我们可以通过 `LogicDeleteManager` 设置一个新的 `LogicDeleteProcessor`
`LogicDeleteProcessor` 接口的内容如下:
```java
public interface LogicDeleteProcessor {
/**
* 用户构建查询正常数据的条件
* @param logicColumn
* @param dialect
*/
String buildLogicNormalCondition(String logicColumn, IDialect dialect);
/**
* 用户与构建删除数据时的内容
* @param logicColumn
* @param dialect
*/
String buildLogicDeletedSet(String logicColumn, IDialect dialect);
/**
* 用于构建通过 QueryWrapper 查询数据时的内容
* @param queryWrapper
* @param tableInfo
*/
void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo);
}
```
具体实现可以参考:[DefaultLogicDeleteProcessorImpl](https://gitee.com/mybatis-flex/mybatis-flex/blob/main/mybatis-flex-core/src/main/java/com/mybatisflex/core/logicdelete/DefaultLogicDeleteProcessorImpl.java)

View File

@ -8,7 +8,7 @@ MyBatis-Flex 使用了 APT 技术,这两个类是自动生成的。
## 阿里镜像找不到依赖?
```txt
Could not find artifact com.mybatis-flex:mybatis-flex-spring-boot-starter:pom:1.4.0
Could not find artifact com.mybatis-flex:mybatis-flex-spring-boot-starter:pom:1.4.1
in alimaven (http://maven.aliyun.com/nexus/content/groups/public/)
```
@ -43,9 +43,7 @@ in alimaven (http://maven.aliyun.com/nexus/content/groups/public/)
HikariCP 的 5.x 版本。
- 2、主动添加了 MyBatis 或者 `mybatis-spring-boot-starter` 的依赖,导致版本不匹配。使用 SpringBoot
的情况下,应该引用 `mybatis-flex-spring-boot-starter` 就可以了,不需要再添加其他 MyBatis 依赖。
- 3、使用了 `druid-spring-boot-starter` 依赖,导致 flex 的 DataSource 无法被接管。应该使用 `druid`
就可以了,不要用 `druid-spring-boot-starter`
- 4、使用了 `MyBatis-Plus` 或者 `pagehelper-spring-boot-starter` 而被这些框架优先初始化 MyBatis MyBatis-Flex 未得到初始化。
- 3、使用了 `MyBatis-Plus` 或者 `pagehelper-spring-boot-starter` 而被这些框架优先初始化 MyBatis MyBatis-Flex 未得到初始化。
## SpringBoot 项目,启动报错 Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
@ -126,31 +124,6 @@ spring:
> 若把数据源配置到 `mybatis-flex.datasource` 下,使用 mybatis-flex 的数据源发现机制,
> 使用 druid 则可以不用配置 type更多文档参考[多数据源章节](./core/multi-datasource.md)。
## 使用 `druid-spring-boot-starter`,出现无法启动 或者 数据源识别错误的问题
在 MyBatis-Flex 不能使用 "druid-spring-boot-starter" 依赖,只能使用 "druid" 。
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
```
需要把以上的依赖,修改如下:
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
```
> 原因是druid-spring-boot-starter 内的 DruidDataSourceAutoConfigure 会去自动加载 spring.datasource 下的配置,当使用 MyBatis-Flex 的多数据源时,
> 这个配置已经不存在了。
## 与 PageHelper 集成出现错误
在社区中,一些老的项目在使用到了开源项目 PageHelper用于解决 xml 的分页问题,在和 MyBatis-flex 整合使用中,出现了一些错误,

View File

@ -27,12 +27,12 @@ Maven示例
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
<scope>provided</scope>
</dependency>
```
@ -46,7 +46,7 @@ Gradle示例
```groovy
// file: build.gradle
ext {
mybatis_flex_version = '1.4.0'
mybatis_flex_version = '1.4.1'
}
dependencies {
implementation("com.mybatis-flex:mybatis-flex-core:${mybatis_flex_version}")

View File

@ -12,12 +12,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
<scope>provided</scope>
</dependency>
```
@ -28,12 +28,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
<scope>provided</scope>
</dependency>
``````
@ -44,12 +44,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
<scope>provided</scope>
</dependency>
```
@ -70,7 +70,7 @@
<path>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</path>
</annotationProcessorPaths>
</configuration>

View File

@ -214,7 +214,7 @@ pom.xml 添加 `annotationProcessorPaths` 配置,
```
dependencies {
...
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.4.0'
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.4.1'
}
```

View File

@ -10,7 +10,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
```

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -22,13 +22,13 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -676,7 +676,7 @@ public interface BaseMapper<T> {
// 一般的分页场景中只有第一页的时候有必要去查询总量第二页以后是不需要的
if (page.getTotalRow() < 0) {
QueryWrapper countQueryWrapper;
if (page.isOptimizeCountSql()) {
if (page.needOptimizeCountQuery()) {
countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
} else {
countQueryWrapper = MapperUtil.rawCountQueryWrapper(queryWrapper);
@ -688,7 +688,7 @@ public interface BaseMapper<T> {
return page;
}
queryWrapper.limit(page.getOffset(), page.getPageSize());
queryWrapper.limit(page.offset(), page.getPageSize());
List<R> records;
if (asType != null) {

View File

@ -23,7 +23,7 @@ public class FlexConsts {
private FlexConsts() {}
public static final String NAME = "MyBatis-Flex";
public static final String VERSION = "1.4.0";
public static final String VERSION = "1.4.1";
public static final String DEFAULT_PRIMARY_FIELD = "id";

View File

@ -15,11 +15,11 @@
*/
package com.mybatisflex.core.dialect.impl;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.query.*;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowCPI;
@ -491,7 +491,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forDeleteEntityById(TableInfo tableInfo) {
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
//正常删除
if (StringUtil.isBlank(logicDeleteColumn)) {
@ -508,7 +508,7 @@ public class CommonsDialectImpl implements IDialect {
String[] primaryKeys = tableInfo.getPrimaryKeys();
sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this));
sql.append(SET).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicDeletedValue());
sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn));
sql.append(WHERE);
for (int i = 0; i < primaryKeys.length; i++) {
if (i > 0) {
@ -517,7 +517,7 @@ public class CommonsDialectImpl implements IDialect {
sql.append(wrap(primaryKeys[i])).append(EQUALS_PLACEHOLDER);
}
sql.append(AND).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicNormalValue());
sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn));
//租户ID
if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
@ -530,7 +530,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forDeleteEntityBatchByIds(TableInfo tableInfo, Object[] primaryValues) {
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
//正常删除
@ -548,7 +548,7 @@ public class CommonsDialectImpl implements IDialect {
StringBuilder sql = new StringBuilder();
sql.append(UPDATE);
sql.append(tableInfo.getWrapSchemaAndTableName(this));
sql.append(SET).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicDeletedValue());
sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn));
sql.append(WHERE);
sql.append(BRACKET_LEFT);
@ -580,7 +580,7 @@ public class CommonsDialectImpl implements IDialect {
}
}
sql.append(BRACKET_RIGHT).append(AND).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicNormalValue());
sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn));
if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
sql.append(AND).append(wrap(tableInfo.getTenantIdColumn())).append(IN).append(buildQuestion(tenantIdArgs.length));
@ -592,7 +592,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forDeleteEntityBatchByQuery(TableInfo tableInfo, QueryWrapper queryWrapper) {
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
//正常删除
if (StringUtil.isBlank(logicDeleteColumn)) {
@ -608,7 +608,7 @@ public class CommonsDialectImpl implements IDialect {
//ignore selectColumns
StringBuilder sqlBuilder = new StringBuilder(UPDATE).append(forHint(CPI.getHint(queryWrapper)));
sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this));
sqlBuilder.append(SET).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicDeletedValue());
sqlBuilder.append(SET).append(buildLogicDeletedSet(logicDeleteColumn));
buildJoinSql(sqlBuilder, queryWrapper, allTables);
@ -661,9 +661,9 @@ public class CommonsDialectImpl implements IDialect {
}
//逻辑删除条件已删除的数据不能被修改
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
if (StringUtil.isNotBlank(logicDeleteColumn)) {
sql.append(AND).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicNormalValue());
sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn));
}
@ -812,9 +812,9 @@ public class CommonsDialectImpl implements IDialect {
}
//逻辑删除的情况下需要添加逻辑删除的条件
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
if (StringUtil.isNotBlank(logicDeleteColumn)) {
sql.append(AND).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicNormalValue());
sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn));
}
//多租户
@ -834,7 +834,7 @@ public class CommonsDialectImpl implements IDialect {
sql.append(WHERE);
String[] primaryKeys = tableInfo.getPrimaryKeys();
String logicDeleteColumn = tableInfo.getLogicDeleteColumn();
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
if (StringUtil.isNotBlank(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) {
sql.append(BRACKET_LEFT);
@ -872,7 +872,7 @@ public class CommonsDialectImpl implements IDialect {
if (StringUtil.isNotBlank(logicDeleteColumn)) {
sql.append(AND).append(wrap(logicDeleteColumn)).append(EQUALS).append(getLogicNormalValue());
sql.append(AND).append(buildLogicNormalCondition(logicDeleteColumn));
}
if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
@ -973,24 +973,14 @@ public class CommonsDialectImpl implements IDialect {
return sb.toString();
}
protected Object getLogicNormalValue() {
Object normalValueOfLogicDelete = FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete();
if (normalValueOfLogicDelete instanceof Number
|| normalValueOfLogicDelete instanceof Boolean) {
return normalValueOfLogicDelete;
}
return SINGLE_QUOTE + normalValueOfLogicDelete + SINGLE_QUOTE;
protected String buildLogicNormalCondition(String logicColumn) {
return LogicDeleteManager.getProcessor().buildLogicNormalCondition(logicColumn,this);
}
protected Object getLogicDeletedValue() {
Object deletedValueOfLogicDelete = FlexGlobalConfig.getDefaultConfig().getDeletedValueOfLogicDelete();
if (deletedValueOfLogicDelete instanceof Number
|| deletedValueOfLogicDelete instanceof Boolean) {
return deletedValueOfLogicDelete;
}
return SINGLE_QUOTE + deletedValueOfLogicDelete + SINGLE_QUOTE;
protected String buildLogicDeletedSet(String logicColumn) {
return LogicDeleteManager.getProcessor().buildLogicDeletedSet(logicColumn,this);
}
}

View File

@ -0,0 +1,69 @@
/*
* 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.logicdelete;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.TableInfo;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS;
import static com.mybatisflex.core.constant.SqlConsts.SINGLE_QUOTE;
public class DefaultLogicDeleteProcessorImpl implements LogicDeleteProcessor {
@Override
public String buildLogicNormalCondition(String logicColumn, IDialect dialect) {
return dialect.wrap(logicColumn) + EQUALS + getLogicNormalValue();
}
@Override
public String buildLogicDeletedSet(String logicColumn, IDialect dialect) {
return dialect.wrap(logicColumn) + EQUALS + getLogicDeletedValue();
}
@Override
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo) {
queryWrapper.and(QueryCondition.create(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getLogicDeleteColumn()
, SqlConsts.EQUALS
, FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete()));
}
protected Object getLogicNormalValue() {
Object normalValueOfLogicDelete = FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete();
if (normalValueOfLogicDelete instanceof Number
|| normalValueOfLogicDelete instanceof Boolean) {
return normalValueOfLogicDelete;
}
return SINGLE_QUOTE + normalValueOfLogicDelete + SINGLE_QUOTE;
}
protected Object getLogicDeletedValue() {
Object deletedValueOfLogicDelete = FlexGlobalConfig.getDefaultConfig().getDeletedValueOfLogicDelete();
if (deletedValueOfLogicDelete instanceof Number
|| deletedValueOfLogicDelete instanceof Boolean) {
return deletedValueOfLogicDelete;
}
return SINGLE_QUOTE + deletedValueOfLogicDelete + SINGLE_QUOTE;
}
}

View File

@ -1,11 +1,34 @@
/*
* 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.logicdelete;
import java.util.function.Supplier;
public class LogicDeleteManager {
private static LogicDeleteProcessor processor = new DefaultLogicDeleteProcessorImpl();
private static final ThreadLocal<Boolean> skipFlags = new ThreadLocal<>();
public static LogicDeleteProcessor getProcessor() {
return processor;
}
public static void setProcessor(LogicDeleteProcessor processor) {
LogicDeleteManager.processor = processor;
}
/**
* 跳过逻辑删除字段处理直接进行数据库物理操作

View File

@ -0,0 +1,46 @@
/*
* 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.logicdelete;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.TableInfo;
public interface LogicDeleteProcessor {
/**
* 用户构建查询正常数据的条件
* @param logicColumn
* @param dialect
*/
String buildLogicNormalCondition(String logicColumn, IDialect dialect);
/**
* 用户与构建删除数据时的内容
* @param logicColumn
* @param dialect
*/
String buildLogicDeletedSet(String logicColumn, IDialect dialect);
/**
* 用于构建通过 QueryWrapper 查询数据时的内容
* @param queryWrapper
* @param tableInfo
*/
void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo);
}

View File

@ -1,169 +0,0 @@
/*
* 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.paginate;
import java.io.Serializable;
import java.util.List;
/**
* 分页接口
*
* @param <T> 数据类型
* @author 王帅
* @since 2023-06-18
*/
public interface IPage<T> extends Serializable {
/**
* 获取当前页码
*
* @return 页码
*/
int getPageNumber();
/**
* 设置当前页码
*
* @param pageNumber 页码
*/
void setPageNumber(int pageNumber);
/**
* 获取当前每页数据数量
*
* @return 每页数据数量
*/
int getPageSize();
/**
* 设置当前每页数据数量
*
* @param pageSize 每页数据数量
*/
void setPageSize(int pageSize);
/**
* 获取数据总数
*
* @return 数据总数
*/
long getTotalRow();
/**
* 设置数据总数
*
* @param totalRow 数据总数
*/
void setTotalRow(long totalRow);
/**
* 获取当前页的数据
*
* @return 当前页的数据
*/
List<T> getRecords();
/**
* 设置当前页的数据
*
* @param records 当前页的数据
*/
void setRecords(List<T> records);
/**
* 获取当前分页偏移量
*
* @return 偏移量
*/
default int getOffset() {
return getPageSize() * (getPageNumber() - 1);
}
/**
* 是否自动优化 COUNT 查询语句默认优化
*
* @return {@code true} 优化{@code false} 不优化
*/
default boolean isOptimizeCountSql() {
return true;
}
/**
* 设置是否自动优化 COUNT 查询语句
*
* @param optimizeCountSql 是否优化
*/
default void setOptimizeCountSql(boolean optimizeCountSql) {
// 默认总是优化
}
/**
* 获取总页数
*
* @return 总页数
*/
default long getTotalPage() {
// 实时计算总页数
int pageSize = getPageSize();
if (pageSize == 0) {
return 0L;
}
long totalRow = getTotalRow();
long totalPage = totalRow / pageSize;
if (totalRow % pageSize != 0) {
totalPage++;
}
return totalPage;
}
/**
* 设置总页数
*
* @param totalPage 总页数
*/
default void setTotalPage(long totalPage) {
// 总页数是实时计算的所以这里设置了也没用
}
/**
* 是否存在上一页
*
* @return {@code true} 存在上一页{@code false} 不存在上一页
*/
default boolean hasPrevious() {
return getPageNumber() > 1;
}
/**
* 是否存在下一页
*
* @return {@code true} 存在下一页{@code false} 不存在下一页
*/
default boolean hasNext() {
return getPageNumber() < getTotalPage();
}
/**
* 当前页是否为空
*
* @return {@code true} 空页{@code false} 非空页
*/
default boolean isEmpty() {
return getTotalRow() == 0 || getPageNumber() > getTotalPage();
}
}

View File

@ -15,12 +15,18 @@
*/
package com.mybatisflex.core.paginate;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
public class Page<T> implements IPage<T> {
/**
* 分页对象
*
* @param <T> 对象类型
*/
public class Page<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int INIT_VALUE = -1;
@ -31,7 +37,7 @@ public class Page<T> implements IPage<T> {
private long totalPage = INIT_VALUE;
private long totalRow = INIT_VALUE;
private boolean optimizeCountSql = true;
private boolean optimizeCountQuery = true;
public static <T> Page<T> of(int pageNumber, int pageSize) {
return new Page<>(pageNumber, pageSize);
@ -56,7 +62,6 @@ public class Page<T> implements IPage<T> {
this.setTotalRow(totalRow);
}
public Page(List<T> records, int pageNumber, int pageSize, long totalRow) {
this.setRecords(records);
this.setPageNumber(pageNumber);
@ -65,22 +70,22 @@ public class Page<T> implements IPage<T> {
}
@Override
public boolean isOptimizeCountSql() {
return optimizeCountSql;
}
@Override
public void setOptimizeCountSql(boolean optimizeCountSql) {
this.optimizeCountSql = optimizeCountSql;
}
@Override
/**
* 获取当前页的数据
*
* @return 当前页的数据
*/
public List<T> getRecords() {
return records;
}
@Override
/**
* 设置当前页的数据
*
* @param records 当前页的数据
*/
public void setRecords(List<T> records) {
if (records == null) {
records = Collections.emptyList();
@ -88,12 +93,21 @@ public class Page<T> implements IPage<T> {
this.records = records;
}
@Override
/**
* 获取当前页码
*
* @return 页码
*/
public int getPageNumber() {
return pageNumber;
}
@Override
/**
* 设置当前页码
*
* @param pageNumber 页码
*/
public void setPageNumber(int pageNumber) {
if (pageNumber < 1) {
throw new IllegalArgumentException("pageNumber must greater than or equal 1current value is: " + pageNumber);
@ -102,12 +116,21 @@ public class Page<T> implements IPage<T> {
}
@Override
/**
* 获取当前每页数据数量
*
* @return 每页数据数量
*/
public int getPageSize() {
return pageSize;
}
@Override
/**
* 设置当前每页数据数量
*
* @param pageSize 每页数据数量
*/
public void setPageSize(int pageSize) {
if (pageSize < 0) {
throw new IllegalArgumentException("pageSize must greater than or equal 0current value is: " + pageSize);
@ -116,22 +139,39 @@ public class Page<T> implements IPage<T> {
this.calcTotalPage();
}
@Override
/**
* 获取数据总数
*
* @return 数据总数
*/
public long getTotalPage() {
return totalPage;
}
@Override
/**
* 设置总页数
*
* @param totalPage 总页数
*/
public void setTotalPage(long totalPage) {
this.totalPage = totalPage;
}
@Override
/**
* 获取数据总数
*
* @return 数据总数
*/
public long getTotalRow() {
return totalRow;
}
@Override
/**
* 设置数据总数
*
* @param totalRow 数据总数
*/
public void setTotalRow(long totalRow) {
this.totalRow = totalRow;
this.calcTotalPage();
@ -148,17 +188,67 @@ public class Page<T> implements IPage<T> {
}
}
@Override
/**
* 当前页是否为空
*
* @return {@code true} 空页{@code false} 非空页
*/
public boolean isEmpty() {
return getTotalRow() == 0 || getPageNumber() > getTotalPage();
}
@Override
/**
* 是否存在下一页
*
* @return {@code true} 存在下一页{@code false} 不存在下一页
*/
public boolean hasNext() {
return getTotalPage() != 0 && getPageNumber() < getTotalPage();
}
/**
* 是否存在上一页
*
* @return {@code true} 存在上一页{@code false} 不存在上一页
*/
public boolean hasPrevious() {
return getPageNumber() > 1;
}
/**
* 获取当前分页偏移量
*
* @return 偏移量
*/
public int offset() {
return getPageSize() * (getPageNumber() - 1);
}
/**
* 设置是否自动优化 COUNT 查询语句
*
* @param optimizeCountQuery 是否优化
*/
public void setOptimizeCountQuery(boolean optimizeCountQuery) {
this.optimizeCountQuery = optimizeCountQuery;
}
/**
* 是否自动优化 COUNT 查询语句默认优化
*
* @return {@code true} 优化{@code false} 不优化
*/
public boolean needOptimizeCountQuery() {
return optimizeCountQuery;
}
public <R> Page<R> map(Function<? super T, ? extends R> mapper) {
Page<R> newPage = new Page<>();
newPage.pageNumber = pageNumber;

View File

@ -423,9 +423,9 @@ public class EntitySqlProvider {
if (CollectionUtil.isNotEmpty(queryTables)) {
tableInfos = new ArrayList<>();
for (QueryTable queryTable : queryTables) {
String tableName = queryTable.getName();
if (StringUtil.isNotBlank(tableName)) {
TableInfo tableInfo = TableInfoFactory.ofTableName(tableName);
String tableNameWithSchema = queryTable.getNameWithSchema();
if (StringUtil.isNotBlank(tableNameWithSchema)) {
TableInfo tableInfo = TableInfoFactory.ofTableName(tableNameWithSchema);
if (tableInfo != null) {
tableInfos.add(tableInfo);
}

View File

@ -71,6 +71,10 @@ public class QueryTable implements CloneSupport<QueryTable> {
this.name = name;
}
public String getNameWithSchema() {
return StringUtil.isNotBlank(schema) ? schema + "." + name : name;
}
public QueryTable as(String alias) {
this.alias = alias;
@ -84,8 +88,7 @@ public class QueryTable implements CloneSupport<QueryTable> {
if (StringUtil.isNotBlank(alias)
&& StringUtil.isNotBlank(table.alias)
&& (Objects.equals(alias, table.alias))) {
return false;
return false;
}
return Objects.equals(name, table.name);
}

View File

@ -441,7 +441,7 @@ public interface RowMapper {
// 一般的分页场景中只有第一页的时候有必要去查询总量第二页以后是不需要的
if (page.getTotalRow() < 0) {
QueryWrapper countQueryWrapper;
if (page.isOptimizeCountSql()) {
if (page.needOptimizeCountQuery()) {
countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
} else {
countQueryWrapper = MapperUtil.rawCountQueryWrapper(queryWrapper);
@ -453,7 +453,7 @@ public interface RowMapper {
return page;
}
queryWrapper.limit(page.getOffset(), page.getPageSize());
queryWrapper.limit(page.offset(), page.getPageSize());
page.setRecords(selectListByQuery(schema, tableName, queryWrapper));

View File

@ -128,6 +128,10 @@ public class TableInfo {
return tableName;
}
public String getTableNameWithSchema() {
return StringUtil.isNotBlank(schema) ? schema + "." + tableName : tableName;
}
public String getWrapSchemaAndTableName(IDialect dialect) {
if (StringUtil.isNotBlank(schema)) {
return dialect.wrap(dialect.getRealSchema(schema)) + "." + dialect.wrap(dialect.getRealTable(tableName));
@ -164,10 +168,14 @@ public class TableInfo {
this.dataSource = dataSource;
}
public String getLogicDeleteColumn() {
public String getLogicDeleteColumnOrSkip() {
return LogicDeleteManager.getLogicDeleteColumn(logicDeleteColumn);
}
public String getLogicDeleteColumn() {
return logicDeleteColumn;
}
public void setLogicDeleteColumn(String logicDeleteColumn) {
this.logicDeleteColumn = logicDeleteColumn;
}
@ -624,6 +632,7 @@ public class TableInfo {
}
private static final String APPEND_CONDITIONS_FLAG = "appendConditions";
private static final String APPEND_JOIN_FLAG = "appendJoins";
public void appendConditions(Object entity, QueryWrapper queryWrapper) {
@ -666,9 +675,8 @@ public class TableInfo {
}
//逻辑删除
if (StringUtil.isNotBlank(getLogicDeleteColumn())) {
queryWrapper.and(QueryCondition.create(schema, tableName, logicDeleteColumn, SqlConsts.EQUALS
, FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete()));
if (StringUtil.isNotBlank(getLogicDeleteColumnOrSkip())) {
LogicDeleteManager.getProcessor().buildQueryCondition(queryWrapper, this);
}
//多租户
@ -689,6 +697,31 @@ public class TableInfo {
}
}
//join
if (!Boolean.TRUE.equals(CPI.getContext(queryWrapper, APPEND_JOIN_FLAG))) {
List<Join> joins = CPI.getJoins(queryWrapper);
if (CollectionUtil.isNotEmpty(joins)) {
for (Join join : joins) {
QueryTable joinQueryTable = CPI.getJoinQueryTable(join);
if (joinQueryTable instanceof SelectQueryTable) {
QueryWrapper childQuery = ((SelectQueryTable) joinQueryTable).getQueryWrapper();
doAppendConditions(entity, childQuery);
} else {
String nameWithSchema = joinQueryTable.getNameWithSchema();
if (StringUtil.isNotBlank(nameWithSchema)) {
TableInfo tableInfo = TableInfoFactory.ofTableName(nameWithSchema);
if (tableInfo != null) {
CPI.putContext(queryWrapper, APPEND_CONDITIONS_FLAG, Boolean.FALSE);
CPI.putContext(queryWrapper, APPEND_JOIN_FLAG, Boolean.TRUE);
tableInfo.appendConditions(entity, queryWrapper);
}
}
}
}
}
}
//union
List<UnionWrapper> unions = CPI.getUnions(queryWrapper);
if (CollectionUtil.isNotEmpty(unions)) {
@ -704,9 +737,17 @@ public class TableInfo {
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
if (queryTables != null && !queryTables.isEmpty()) {
for (QueryTable queryTable : queryTables) {
TableInfo tableInfo = TableInfoFactory.ofTableName(queryTable.getName());
if (tableInfo != null) {
tableInfo.appendConditions(entity, queryWrapper);
if (queryTable instanceof SelectQueryTable) {
QueryWrapper childQuery = ((SelectQueryTable) queryTable).getQueryWrapper();
doAppendConditions(entity, childQuery);
} else {
String nameWithSchema = queryTable.getNameWithSchema();
if (StringUtil.isNotBlank(nameWithSchema)) {
TableInfo tableInfo = TableInfoFactory.ofTableName(nameWithSchema);
if (tableInfo != null) {
tableInfo.appendConditions(entity, queryWrapper);
}
}
}
}
}
@ -986,7 +1027,7 @@ public class TableInfo {
* @param entityObject
*/
public void initLogicDeleteValueIfNecessary(Object entityObject) {
if (StringUtil.isBlank(getLogicDeleteColumn())) {
if (StringUtil.isBlank(getLogicDeleteColumnOrSkip())) {
return;
}

View File

@ -101,7 +101,7 @@ public class TableInfoFactory {
public static TableInfo ofEntityClass(Class<?> entityClass) {
return MapUtil.computeIfAbsent(entityTableMap, entityClass, aClass -> {
TableInfo tableInfo = createTableInfo(entityClass);
tableInfoMap.put(tableInfo.getTableName(), tableInfo);
tableInfoMap.put(tableInfo.getTableNameWithSchema(), tableInfo);
return tableInfo;
});
}

View File

@ -55,10 +55,10 @@ public class AccountSqlTester {
TableManager.setDynamicTableProcessor(new DynamicTableProcessor() {
@Override
public String process(String tableName) {
return tableName+"_01";
return tableName + "_01";
}
});
TableManager.setDynamicTableProcessor(original -> original+"_01");
TableManager.setDynamicTableProcessor(original -> original + "_01");
System.out.println(query.toSQL());
}
@ -72,8 +72,8 @@ public class AccountSqlTester {
.where(ACCOUNT01.ID.ge(100))
.and(ACCOUNT.SEX.eq(1));
TableManager.setDynamicTableProcessor(original -> original+"_01");
TableManager.setDynamicTableProcessor(original -> original+"_01");
TableManager.setDynamicTableProcessor(original -> original + "_01");
TableManager.setDynamicTableProcessor(original -> original + "_01");
System.out.println(query.toSQL());
}
@ -263,6 +263,8 @@ public class AccountSqlTester {
System.out.println(sql);
}
//https://gitee.com/mybatis-flex/mybatis-flex/issues/I7EAY9
@Test
public void testGroup_I7EAY9() {
QueryWrapper query = QueryWrapper.create()
@ -330,6 +332,10 @@ public class AccountSqlTester {
System.out.println(sql);
}
@Test
public void testOrderBySql() {
QueryWrapper queryWrapper = QueryWrapper.create()

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -0,0 +1,91 @@
/**
* 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.test;
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.query.QueryWrapper;
import com.mybatisflex.mapper.ArticleMapper;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.List;
import static com.mybatisflex.core.query.QueryMethods.raw;
import static com.mybatisflex.core.query.QueryMethods.select;
import static com.mybatisflex.test.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.test.table.ArticleTableDef.ARTICLE;
/**
* test https://gitee.com/mybatis-flex/mybatis-flex/issues/I7EV67
*/
public class JoinWithDeleteColumnTestStarter {
public static void main(String[] args) {
DataSource dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("data.sql")
.build();
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
.addMapper(AccountMapper.class)
.addMapper(MyAccountMapper.class)
.addMapper(ArticleMapper.class)
.start();
//开启审计功能
AuditManager.setAuditEnable(true);
//设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
AccountMapper accountMapper = bootstrap.getMapper(AccountMapper.class);
QueryWrapper query1 = QueryWrapper.create()
.select()
.from(ACCOUNT)
.leftJoin(ARTICLE).as("a").on(
ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)
)
.where(ACCOUNT.AGE.ge(10));
List<AccountDTO> accountDTOS1 = accountMapper.selectListByQueryAs(query1, AccountDTO.class);
System.out.println(accountDTOS1);
System.out.println(">>>>>>>>>");
QueryWrapper query2 = QueryWrapper.create()
.select()
.from(ACCOUNT)
.leftJoin(
select().from(ARTICLE).where(ARTICLE.ID.ge(100))
).as("a").on(
ACCOUNT.ID.eq(raw("a.id"))
)
.where(ACCOUNT.AGE.ge(10));
List<AccountDTO> accountDTOS2 = accountMapper.selectListByQueryAs(query2, AccountDTO.class);
System.out.println(accountDTOS2);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -144,7 +144,7 @@ class UserMapperTest {
.leftJoin(ROLE).as("r").on(USER_ROLE.ROLE_ID.eq(ROLE.ROLE_ID));
System.err.println(queryWrapper.toSQL());
Page<UserVO> page = Page.of(1, 1);
page.setOptimizeCountSql(false);
page.setOptimizeCountQuery(false);
int pageNumber = 0;
do {
page.setPageNumber(page.getPageNumber() + 1);

View File

@ -4,7 +4,7 @@
<parent>
<artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -55,7 +55,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>mybatis-flex-test</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,13 +20,13 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</dependency>
<dependency>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.4.0</version>
<version>1.4.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -60,7 +60,7 @@
<path>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
</path>
</annotationProcessorPaths>
</configuration>

View File

@ -7,7 +7,7 @@
<groupId>com.mybatis-flex</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.4.0</version>
<version>1.4.1</version>
<name>mybatis-flex</name>
<url>https://mybatis-flex.com</url>