Merge remote-tracking branch 'origin/main' into main

This commit is contained in:
life 2023-08-03 21:01:24 +08:00
commit 6c04a13cd8
23 changed files with 341 additions and 93 deletions

View File

@ -1,4 +1,4 @@
- **`update(entity)`**:根据主键来更新数据,若实体类属性数据为 `null`,该属性不会新到数据库。
- **`update(entity)`**:根据主键来更新数据,若实体类属性数据为 `null`,该属性不会新到数据库。
- **`update(entity, ignoreNulls)`**:根据主键来更新数据到数据库。
- **`updateByMap(entity, whereConditions)`**:根据 Map 构建的条件来更新数据。
- **`updateByMap(entity, ignoreNulls, whereConditions)`**:根据 Map 构建的条件来更新数据。

View File

@ -17,10 +17,10 @@ public class AccountController {
@Autowired
AccountMapper accountMapper;
@GetMapping("/accounts")
List<Account> selectList() {
//构造 QueryWrapper也支持使用 QueryWrapper.create() 构造,效果相同
QueryWrapper query = new QueryWrapper();
query.where(ACCOUNT.ID.ge(100));
@ -148,7 +148,7 @@ select(column("abc")) --> SELECT abc
,然后在自己的项目里进行自定义扩展。
| 支持的函数 | 函数说明 |
| 支持的函数 | 函数说明 |
| -------- | -------- |
| count | 查询数据总量 |
| distinct | 对指定列进行去重 |
@ -339,11 +339,11 @@ QueryWrapper wrapper = QueryWrapper.create()
其查询生成的 Sql 如下:
```sql
SELECT `id`,
(CASE WHEN `id` >= 2 THEN 'x2'
WHEN `id` >= 1 THEN 'x1'
ELSE 'x100'
END) AS `xName`
SELECT `id`,
(CASE WHEN `id` >= 2 THEN 'x2'
WHEN `id` >= 1 THEN 'x1'
ELSE 'x100'
END) AS `xName`
FROM `tb_account`
```
@ -374,12 +374,12 @@ QueryWrapper queryWrapper = QueryWrapper.create()
其查询生成的 Sql 如下:
```sql
SELECT *,
(CASE `id`
WHEN 100 THEN 100
WHEN 200 THEN 200
ELSE 300 END) AS `result`
FROM `tb_account`
SELECT *,
(CASE `id`
WHEN 100 THEN 100
WHEN 200 THEN 200
ELSE 300 END) AS `result`
FROM `tb_account`
WHERE `user_name` LIKE ?
```
@ -408,7 +408,7 @@ System.out.println(query.toSQL());
生成的 SQL 如下:
```sql
WITH CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100)
WITH CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100)
SELECT * FROM `tb_account` WHERE `sex` = 1
```
@ -432,8 +432,8 @@ System.out.println(query.toSQL());
生成的 SQL 如下:
```sql
WITH xxx(id, name)
AS (VALUES (a, b) UNION (SELECT * FROM `tb_article` WHERE `id` >= 200))
WITH xxx(id, name)
AS (VALUES (a, b) UNION (SELECT * FROM `tb_article` WHERE `id` >= 200))
SELECT * FROM `tb_account` WHERE `sex` = 1
```
@ -458,7 +458,7 @@ System.out.println(query.toSQL());
生成的 SQL 如下:
```sql
WITH RECURSIVE CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100)
WITH RECURSIVE CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100)
SELECT * FROM `tb_account` WHERE `sex` = 1
```
@ -485,9 +485,9 @@ System.out.println(query.toSQL());
生成的 SQL 如下:
```sql
WITH RECURSIVE
CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100),
xxx(id, name) AS (VALUES (a, b) UNION (SELECT * FROM `tb_article` WHERE `id` >= 200))
WITH RECURSIVE
CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100),
xxx(id, name) AS (VALUES (a, b) UNION (SELECT * FROM `tb_article` WHERE `id` >= 200))
SELECT * FROM `tb_account` WHERE `sex` = 1
```
@ -509,7 +509,7 @@ QueryWrapper queryWrapper=QueryWrapper.create()
```sql
SELECT * FROM tb_account
WHERE id >= ?
AND user_name LIKE ?
AND user_name LIKE ?
```
## where 动态条件 1
@ -526,7 +526,7 @@ QueryWrapper queryWrapper = QueryWrapper.create()
```sql
SELECT * FROM tb_account
WHERE user_name LIKE ?
WHERE user_name LIKE ?
```
## where 动态条件 2
@ -543,7 +543,7 @@ QueryWrapper queryWrapper = QueryWrapper.create()
```sql
SELECT * FROM tb_account
WHERE user_name LIKE ?
WHERE user_name LIKE ?
```
## where 动态条件 3
@ -560,7 +560,7 @@ QueryWrapper queryWrapper = QueryWrapper.create()
```sql
SELECT * FROM tb_account
WHERE id >= ?
WHERE id >= ?
```
## where 动态条件 4
@ -569,7 +569,7 @@ WHERE id >= ?
String name = null;
QueryWrapper queryWrapper = QueryWrapper.create()
.select().from(ACCOUNT)
.where(ACCOUNT.ID.ge(100))
.where(ACCOUNT.ID.ge(100))
.and(ACCOUNT.USER_NAME.like(name, If::hasText));
```
@ -577,7 +577,7 @@ QueryWrapper queryWrapper = QueryWrapper.create()
```sql
SELECT * FROM tb_account
WHERE id >= ?
WHERE id >= ?
```
## where select
@ -749,9 +749,9 @@ QueryWrapper queryWrapper = QueryWrapper.create()
其查询生成的 Sql 如下:
```sql
SELECT * FROM tb_account LEFT JOIN tb_article
ON tb_account.id = tb_article.account_id AND tb_account.age = ?
WHERE tb_account.age >= ?
SELECT * FROM tb_account LEFT JOIN tb_article
ON tb_account.id = tb_article.account_id AND tb_account.age = ?
WHERE tb_account.age >= ?
```
## join select
@ -772,12 +772,47 @@ QueryWrapper queryWrapper = QueryWrapper.create()
其查询生成的 Sql 如下:
```sql
SELECT * FROM tb_account
SELECT * FROM tb_account
LEFT JOIN (SELECT * FROM tb_article WHERE id >= ? ) AS a
ON tb_account.id = a.id
WHERE tb_account.age >= ?
ON tb_account.id = a.id
WHERE tb_account.age >= ?
```
## join 自己
```java
QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper.from(ACCOUNT)
.leftJoin(ACCOUNT).as("a1").on(ACCOUNT.ID.eq(ACCOUNT.PARENT_ID))
.leftJoin(ACCOUNT).as("a2").on(ACCOUNT.ID.eq(ACCOUNT.PARENT_ID))
.where(ACCOUNT.ID.ge(1));
```
其查询生成的 Sql 如下:
```sql
SELECT * FROM `tb_account`
LEFT JOIN `tb_account` AS `a1`
ON `a1`.`id` = `tb_account`.`parent_id`
LEFT JOIN `tb_account` AS `a2`
ON `a2`.`id` = `tb_account`.`parent_id`
WHERE `tb_account`.`id` >= ?
```
`tb_account` 表带有逻辑删除,那么其生成的 SQL 如下:
```sql
SELECT * FROM `tb_account`
LEFT JOIN `tb_account` AS `a1`
ON `a1`.`id` = `tb_account`.`parent_id` AND `a1`.`is_delete` = ?
LEFT JOIN `tb_account` AS `a2`
ON `a2`.`id` = `tb_account`.`parent_id` AND `a2`.`is_delete` = ?
WHERE `tb_account`.`id` >= ?
AND `tb_account`.`is_delete` = ?
```
> 关于逻辑删除更多文档请参考 [这里](../core/logic-delete.html)。
## union, union all
```java
@ -792,8 +827,8 @@ QueryWrapper query = new QueryWrapper()
其查询生成的 Sql 如下:
```sql
(SELECT id FROM tb_account ORDER BY id DESC)
UNION (SELECT id FROM tb_article)
(SELECT id FROM tb_account ORDER BY id DESC)
UNION (SELECT id FROM tb_article)
UNION ALL (SELECT id FROM tb_article)
```
@ -894,12 +929,12 @@ System.out.println(query.toSQL());
SQL 输入内容如下:
```sql
SELECT * FROM `tb_article`
LEFT JOIN `tb_account` AS `a` ON `a`.`id` = `tb_article`.`account_id`
WHERE `a`.`id` >= 100 AND
(`a`.`id` >= 100
OR `a`.`age` > 200
AND `tb_article`.`account_id` = 200
SELECT * FROM `tb_article`
LEFT JOIN `tb_account` AS `a` ON `a`.`id` = `tb_article`.`account_id`
WHERE `a`.`id` >= 100 AND
(`a`.`id` >= 100
OR `a`.`age` > 200
AND `tb_article`.`account_id` = 200
OR (`a`.`id` LIKE '%a%' )
)
```

View File

@ -7,7 +7,19 @@
- 熟悉 Spring Boot 及相关框架
- 熟悉 Java 构建工具,比如 Maven
## Hello World
> 当前章节涉及到的源码已经全部上传到https://gitee.com/Suomm/mybatis-flex-test ,在开始之前,
> 您也可以先下载到本地,导入到 idea 开发工具后,在继续看文档。
## Hello World 视频教程
<iframe width="100%" height="400px" src="//player.bilibili.com/player.html?aid=955526987&bvid=BV1yW4y1Z74j&cid=1187300793&page=1&autoplay=no" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
MyBatis-Flex 视频系列详情https://www.bilibili.com/video/BV1yW4y1Z74j
## Hello World 文档
**第 1 步:创建数据库表**

View File

@ -271,7 +271,7 @@ public interface BaseMapper<T> {
// === update ===
/**
* 根据主键来更新数据若实体类属性数据为 {@code null}该属性不会新到数据库
* 根据主键来更新数据若实体类属性数据为 {@code null}该属性不会新到数据库
*
* @param entity 数据内容必须包含有主键
* @return 受影响的行数

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.dialect;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.dialect.impl.DmDialect;
import com.mybatisflex.core.dialect.impl.OracleDialect;
import com.mybatisflex.core.util.ObjectUtil;
import org.apache.ibatis.util.MapUtil;
@ -109,6 +110,7 @@ public class DialectFactory {
case CSIIDB:
return new CommonsDialectImpl(KeywordWrap.BACK_QUOTE, LimitOffsetProcessor.MYSQL);
case DM:
return new DmDialect();
case ORACLE:
return new OracleDialect();
case GAUSS:

View File

@ -19,7 +19,6 @@ import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.util.StringUtil;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
/**
@ -110,14 +109,35 @@ public class KeywordWrap {
return prefix + keyword + suffix;
}
if (keywords.contains(keyword.toUpperCase(Locale.ENGLISH))) {
if (keywordsToUpperCase) {
return prefix + keyword.toUpperCase() + suffix;
} else {
return prefix + keyword + suffix;
}
}
return keyword;
keyword = keywordsToUpperCase ? keyword.toUpperCase() : keyword;
return keywords.contains(keyword) ? (prefix + keyword + suffix) : keyword;
}
public boolean isCaseSensitive() {
return caseSensitive;
}
public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
public boolean isKeywordsToUpperCase() {
return keywordsToUpperCase;
}
public void setKeywordsToUpperCase(boolean keywordsToUpperCase) {
this.keywordsToUpperCase = keywordsToUpperCase;
}
public Set<String> getKeywords() {
return keywords;
}
public String getPrefix() {
return prefix;
}
public String getSuffix() {
return suffix;
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.dialect.impl;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.util.CollectionUtil;
import java.util.Set;
public class DmDialect extends CommonsDialectImpl {
//https://docs.oracle.com/cd/A97630_01/appdev.920/a42525/apb.htm
public static final Set<String> keywords = CollectionUtil.newHashSet(
"ACCESS", "ELSE", "MODIFY", "START", "ADD", "EXCLUSIVE", "NOAUDIT", "SELECT",
"ALL", "EXISTS", "NOCOMPRESS", "SESSION", "ALTER", "FILE", "NOT", "SET", "AND", "FLOAT",
"NOTFOUND", "SHARE", "ANY", "FOR", "NOWAIT", "SIZE", "ARRAYLEN", "FROM", "NULL", "SMALLINT",
"AS", "GRANT", "NUMBER", "SQLBUF", "ASC", "GROUP", "OF", "SUCCESSFUL", "AUDIT", "HAVING",
"OFFLINE", "SYNONYM", "BETWEEN", "IDENTIFIED", "ON", "SYSDATE", "BY", "IMMEDIATE", "ONLINE",
"TABLE", "CHAR", "IN", "OPTION", "THEN", "CHECK", "INCREMENT", "OR", "TO", "CLUSTER", "INDEX",
"ORDER", "TRIGGER", "COLUMN", "INITIAL", "PCTFREE", "UID", "COMMENT", "INSERT", "PRIOR",
"UNION", "COMPRESS", "INTEGER", "PRIVILEGES", "UNIQUE", "CONNECT", "INTERSECT", "PUBLIC",
"UPDATE", "CREATE", "INTO", "RAW", "USER", "CURRENT", "IS", "RENAME", "VALIDATE", "DATE", "LEVEL",
"RESOURCE", "VALUES", "DECIMAL", "LIKE", "REVOKE", "VARCHAR", "DEFAULT", "LOCK", "ROW", "VARCHAR2",
"DELETE", "LONG", "ROWID", "VIEW", "DESC", "MAXEXTENTS", "ROWLABEL", "WHENEVER", "DISTINCT", "MINUS",
"ROWNUM", "WHERE", "DROP", "MODE", "ROWS", "WITH", "ADMIN", "CURSOR", "FOUND", "MOUNT", "AFTER", "CYCLE",
"FUNCTION", "NEXT", "ALLOCATE", "DATABASE", "GO", "NEW", "ANALYZE", "DATAFILE", "GOTO", "NOARCHIVELOG",
"ARCHIVE", "DBA", "GROUPS", "NOCACHE", "ARCHIVELOG", "DEC", "INCLUDING", "NOCYCLE", "AUTHORIZATION",
"DECLARE", "INDICATOR", "NOMAXVALUE", "AVG", "DISABLE", "INITRANS", "NOMINVALUE", "BACKUP", "DISMOUNT",
"INSTANCE", "NONE", "BEGIN", "DOUBLE", "INT", "NOORDER", "BECOME", "DUMP", "KEY", "NORESETLOGS", "BEFORE",
"EACH", "LANGUAGE", "NORMAL", "BLOCK", "ENABLE", "LAYER", "NOSORT", "BODY", "END", "LINK", "NUMERIC", "CACHE",
"ESCAPE", "LISTS", "OFF", "CANCEL", "EVENTS", "LOGFILE", "OLD", "CASCADE", "EXCEPT", "MANAGE", "ONLY", "CHANGE",
"EXCEPTIONS", "MANUAL", "OPEN", "CHARACTER", "EXEC", "MAX", "OPTIMAL", "CHECKPOINT", "EXPLAIN", "MAXDATAFILES",
"OWN", "CLOSE", "EXECUTE", "MAXINSTANCES", "PACKAGE", "COBOL", "EXTENT", "MAXLOGFILES", "PARALLEL", "COMMIT",
"EXTERNALLY", "MAXLOGHISTORY", "PCTINCREASE", "COMPILE", "FETCH", "MAXLOGMEMBERS", "PCTUSED", "CONSTRAINT",
"FLUSH", "MAXTRANS", "PLAN", "CONSTRAINTS", "FREELIST", "MAXVALUE", "PLI", "CONTENTS", "FREELISTS", "MIN",
"PRECISION", "CONTINUE", "FORCE", "MINEXTENTS", "PRIMARY", "CONTROLFILE", "FOREIGN", "MINVALUE", "PRIVATE",
"COUNT", "FORTRAN", "MODULE", "PROCEDURE", "PROFILE", "SAVEPOINT", "SQLSTATE", "TRACING", "QUOTA", "SCHEMA",
"STATEMENT_ID", "TRANSACTION", "READ", "SCN", "STATISTICS", "TRIGGERS", "REAL", "SECTION", "STOP", "TRUNCATE",
"RECOVER", "SEGMENT", "STORAGE", "UNDER", "REFERENCES", "SEQUENCE", "SUM", "UNLIMITED", "REFERENCING", "SHARED",
"SWITCH", "UNTIL", "RESETLOGS", "SNAPSHOT", "SYSTEM", "USE", "RESTRICTED", "SOME", "TABLES", "USING", "REUSE",
"SORT", "TABLESPACE", "WHEN", "ROLE", "SQL", "TEMPORARY", "WRITE", "ROLES", "SQLCODE", "THREAD", "WORK", "ROLLBACK",
"SQLERROR", "TIME", "ABORT", "BETWEEN", "CRASH", "DIGITS", "ACCEPT", "BINARY_INTEGER", "CREATE", "DISPOSE", "ACCESS",
"BODY", "CURRENT", "DISTINCT", "ADD", "BOOLEAN", "CURRVAL", "DO", "ALL", "BY", "CURSOR", "DROP", "ALTER", "CASE", "DATABASE",
"ELSE", "AND", "CHAR", "DATA_BASE", "ELSIF", "ANY", "CHAR_BASE", "DATE", "END", "ARRAY", "CHECK", "DBA", "ENTRY", "ARRAYLEN",
"CLOSE", "DEBUGOFF", "EXCEPTION", "AS", "CLUSTER", "DEBUGON", "EXCEPTION_INIT", "ASC", "CLUSTERS", "DECLARE", "EXISTS",
"ASSERT", "COLAUTH", "DECIMAL", "EXIT", "ASSIGN", "COLUMNS", "DEFAULT", "FALSE", "AT", "COMMIT", "DEFINITION", "FETCH",
"AUTHORIZATION", "COMPRESS", "DELAY", "FLOAT", "AVG", "CONNECT", "DELETE", "FOR", "BASE_TABLE", "CONSTANT", "DELTA", "FORM",
"BEGIN", "COUNT", "DESC", "FROM", "FUNCTION", "NEW", "RELEASE", "SUM", "GENERIC", "NEXTVAL", "REMR", "TABAUTH",
"GOTO", "NOCOMPRESS", "RENAME", "TABLE", "GRANT", "NOT", "RESOURCE", "TABLES", "GROUP", "NULL", "RETURN", "TASK", "HAVING",
"NUMBER", "REVERSE", "TERMINATE", "IDENTIFIED", "NUMBER_BASE", "REVOKE", "THEN", "IF", "OF", "ROLLBACK", "TO", "IN", "ON",
"ROWID", "TRUE", "INDEX", "OPEN", "ROWLABEL", "TYPE", "INDEXES", "OPTION", "ROWNUM", "UNION", "INDICATOR", "OR", "ROWTYPE",
"UNIQUE", "INSERT", "ORDER", "RUN", "UPDATE", "INTEGER", "OTHERS", "SAVEPOINT", "USE", "INTERSECT", "OUT", "SCHEMA", "VALUES",
"INTO", "PACKAGE", "SELECT", "VARCHAR", "IS", "PARTITION", "SEPARATE", "VARCHAR2", "LEVEL", "PCTFREE", "SET", "VARIANCE",
"LIKE", "POSITIVE", "SIZE", "VIEW", "LIMITED", "PRAGMA", "SMALLINT", "VIEWS", "LOOP", "PRIOR", "SPACE", "WHEN", "MAX", "PRIVATE",
"SQL", "WHERE", "MIN", "PROCEDURE", "SQLCODE", "WHILE", "MINUS", "PUBLIC", "SQLERRM", "WITH", "MLSLABEL", "RAISE", "START",
"WORK", "MOD", "RANGE", "STATEMENT", "XOR", "MODE", "REAL", "STDDEV", "NATURAL", "RECORD", "SUBTYPE", "GEN", "KP", "L",
"NA", "NC", "ND", "NL", "NM", "NR", "NS", "NT", "NZ", "TTC", "UPI", "O", "S", "XA"
);
public DmDialect() {
//达梦 默认情况下是支持 MySQL 的分页语法的
this(LimitOffsetProcessor.MYSQL);
}
public DmDialect(LimitOffsetProcessor limitOffsetProcessor) {
//只有以上的关键字时会添加 "" 包裹
this(new KeywordWrap(false, false, keywords, "\"", "\""), limitOffsetProcessor);
}
public DmDialect(KeywordWrap keywordWrap, LimitOffsetProcessor limitOffsetProcessor) {
super(keywordWrap, limitOffsetProcessor);
}
}

View File

@ -50,6 +50,8 @@ public enum LocalizedFormats implements Localizable {
ENTITY_VERSION_NULL("The version value of entity \"{0}\" must not be null."),
KEY_GENERATOR_BLANK("The name of key generator must not be null or blank."),
;
private final String sourceFormat;

View File

@ -111,6 +111,8 @@ public class FieldQueryManager {
} else if (fieldType == Set.class) {
return Collections.emptySet();
}
// avoid NPE
return ClassUtil.newInstance(fieldType);
}
if (ClassUtil.canInstance(fieldType.getModifiers())) {

View File

@ -15,9 +15,12 @@
*/
package com.mybatisflex.core.keygen;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.keygen.impl.FlexIDKeyGenerator;
import com.mybatisflex.core.keygen.impl.SnowFlakeIDKeyGenerator;
import com.mybatisflex.core.keygen.impl.UUIDKeyGenerator;
import com.mybatisflex.core.util.StringUtil;
import java.util.HashMap;
import java.util.Map;
@ -43,9 +46,12 @@ public class KeyGeneratorFactory {
* 获取 主键生成器
*
* @param name
* @return
* @return 主键生成器
*/
public static IKeyGenerator getKeyGenerator(String name) {
if (StringUtil.isBlank(name)){
throw FlexExceptions.wrap(LocalizedFormats.KEY_GENERATOR_BLANK);
}
return KEY_GENERATOR_MAP.get(name.trim());
}

View File

@ -16,7 +16,8 @@
package com.mybatisflex.core.logicdelete;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.TableInfo;
@ -41,10 +42,10 @@ public abstract class AbstractLogicDeleteProcessor implements LogicDeleteProcess
}
@Override
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo) {
queryWrapper.and(QueryCondition.create(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getLogicDeleteColumn()
, EQUALS
, getLogicNormalValue()));
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo, String joinTableAlias) {
QueryTable queryTable = new QueryTable(tableInfo.getSchema(), tableInfo.getTableName()).as(joinTableAlias);
QueryColumn queryColumn = new QueryColumn(queryTable, tableInfo.getLogicDeleteColumn());
queryWrapper.and(queryColumn.eq(getLogicNormalValue()));
}
}

View File

@ -44,11 +44,11 @@ public interface LogicDeleteProcessor {
/**
* 用于构建通过 {@link QueryWrapper} 查询数据时的内容
*
* @param queryWrapper 条件构造器
* @param queryWrapper 条件构造器
* @param tableInfo 表信息
* @param joinTableAlias join table 的别名
*/
void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo);
void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo, String joinTableAlias);
/**
* 获取逻辑删除列未删除标记值

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.logicdelete;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.table.TableInfo;
@ -35,8 +36,9 @@ public abstract class NullableColumnLogicDeleteProcessor extends AbstractLogicDe
}
@Override
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo) {
QueryColumn queryColumn = new QueryColumn(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getLogicDeleteColumn());
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo, String joinTableAlias) {
QueryTable queryTable = new QueryTable(tableInfo.getSchema(), tableInfo.getTableName()).as(joinTableAlias);
QueryColumn queryColumn = new QueryColumn(queryTable, tableInfo.getLogicDeleteColumn());
queryWrapper.and(queryColumn.isNull());
}

View File

@ -18,8 +18,6 @@ package com.mybatisflex.core.logicdelete.impl;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.logicdelete.AbstractLogicDeleteProcessor;
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;
@ -27,6 +25,7 @@ import static com.mybatisflex.core.constant.SqlConsts.SINGLE_QUOTE;
/**
* 默认逻辑删除处理器
* @author michael
*/
public class DefaultLogicDeleteProcessor extends AbstractLogicDeleteProcessor {
@ -40,13 +39,6 @@ public class DefaultLogicDeleteProcessor extends AbstractLogicDeleteProcessor {
return dialect.wrap(logicColumn) + EQUALS + prepareValue(getLogicDeletedValue());
}
@Override
public void buildQueryCondition(QueryWrapper queryWrapper, TableInfo tableInfo) {
queryWrapper.where(QueryCondition.create(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getLogicDeleteColumn()
, EQUALS
, getLogicNormalValue()));
}
@Override
public Object getLogicNormalValue() {
return FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete();

View File

@ -317,14 +317,14 @@ public class QueryConditionBuilder<Wrapper extends QueryWrapper> {
* @param queryWrapper
* @return
*/
public Wrapper in(Wrapper queryWrapper) {
public Wrapper in(QueryWrapper queryWrapper) {
if (queryWrapper != null) {
this.queryWrapper.addWhereQueryCondition(queryColumn.in(queryWrapper), connector);
}
return this.queryWrapper;
}
public <T> Wrapper in(Wrapper queryWrapper, Predicate<T> when) {
public <T> Wrapper in(QueryWrapper queryWrapper, Predicate<T> when) {
if (queryWrapper != null) {
this.queryWrapper.addWhereQueryCondition(queryColumn.in(queryWrapper, when), connector);
}
@ -398,14 +398,14 @@ public class QueryConditionBuilder<Wrapper extends QueryWrapper> {
*
* @param queryWrapper
*/
public Wrapper notIn(Wrapper queryWrapper) {
public Wrapper notIn(QueryWrapper queryWrapper) {
if (queryWrapper != null) {
this.queryWrapper.addWhereQueryCondition(queryColumn.notIn(queryWrapper), connector);
}
return this.queryWrapper;
}
public <T> Wrapper notIn(Wrapper queryWrapper, Predicate<T> when) {
public <T> Wrapper notIn(QueryWrapper queryWrapper, Predicate<T> when) {
if (queryWrapper != null) {
this.queryWrapper.addWhereQueryCondition(queryColumn.notIn(queryWrapper, when), connector);
}

View File

@ -28,6 +28,7 @@ import java.util.Objects;
*/
public class QueryTable implements CloneSupport<QueryTable> {
protected int tableDefHashCode = 0;
protected String schema;
protected String name;
protected String alias;
@ -36,6 +37,8 @@ public class QueryTable implements CloneSupport<QueryTable> {
}
public QueryTable(TableDef tableDef) {
// TableDef的标识符号,0:不确定标识
this.tableDefHashCode = tableDef.hashCode();
this.schema = tableDef.getSchema();
this.name = tableDef.getTableName();
}
@ -77,6 +80,13 @@ public class QueryTable implements CloneSupport<QueryTable> {
return StringUtil.isNotBlank(schema) ? schema + "." + name : name;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public QueryTable as(String alias) {
this.alias = alias;
@ -87,15 +97,16 @@ public class QueryTable implements CloneSupport<QueryTable> {
if (table == null) {
return false;
}
if (StringUtil.isNotBlank(alias)
&& StringUtil.isNotBlank(table.alias)
&& (Objects.equals(alias, table.alias))) {
if (StringUtil.isNotBlank(alias) && StringUtil.isNotBlank(table.alias) && (Objects.equals(alias, table.alias))) {
return false;
}
//比较对象都有tableDef标记,就用标记比对, 否则就用名称比对
if (tableDefHashCode != 0 && table.tableDefHashCode != 0) {
return tableDefHashCode == table.tableDefHashCode;
}
return Objects.equals(name, table.name);
}
Object[] getValueArray() {
return FlexConsts.EMPTY_ARRAY;
}
@ -110,14 +121,9 @@ public class QueryTable implements CloneSupport<QueryTable> {
return sql;
}
@Override
public String toString() {
return "QueryTable{" +
"schema='" + schema + '\'' +
", name='" + name + '\'' +
", alias='" + alias + '\'' +
'}';
return "QueryTable{" + "schema='" + schema + '\'' + ", name='" + name + '\'' + ", alias='" + alias + '\'' + '}';
}
@Override

View File

@ -39,7 +39,7 @@ public class StringQueryColumn extends QueryColumn {
@Override
String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
return content;
return content + WrapperUtil.buildAlias(alias, dialect);
}
@Override

View File

@ -779,7 +779,8 @@ public class TableInfo {
//逻辑删除
if (StringUtil.isNotBlank(getLogicDeleteColumnOrSkip())) {
LogicDeleteManager.getProcessor().buildQueryCondition(queryWrapper, this);
String joinTableAlias = CPI.getContext(queryWrapper, "joinTableAlias");
LogicDeleteManager.getProcessor().buildQueryCondition(queryWrapper, this, joinTableAlias);
}
//多租户
@ -800,11 +801,14 @@ public class TableInfo {
if (CollectionUtil.isNotEmpty(joins)) {
for (Join join : joins) {
QueryTable joinQueryTable = CPI.getJoinQueryTable(join);
//join select
if (joinQueryTable instanceof SelectQueryTable) {
QueryWrapper childQuery = ((SelectQueryTable) joinQueryTable).getQueryWrapper();
doAppendConditions(entity, childQuery);
} else {
}
//join table
else {
String nameWithSchema = joinQueryTable.getNameWithSchema();
if (StringUtil.isNotBlank(nameWithSchema)) {
TableInfo tableInfo = TableInfoFactory.ofTableName(nameWithSchema);
@ -812,8 +816,10 @@ public class TableInfo {
QueryCondition joinQueryCondition = CPI.getJoinQueryCondition(join);
QueryWrapper newWrapper = QueryWrapper.create()
.where(joinQueryCondition);
CPI.putContext(newWrapper, "joinTableAlias", joinQueryTable.getAlias());
tableInfo.appendConditions(entity, newWrapper);
CPI.setJoinQueryCondition(join, CPI.getWhereQueryCondition(newWrapper));
QueryCondition whereQueryCondition = CPI.getWhereQueryCondition(newWrapper);
CPI.setJoinQueryCondition(join, whereQueryCondition);
}
}
}

View File

@ -41,7 +41,7 @@ public class DateUtil {
public static final String dateMillisecondPattern = "yyyy-MM-dd HH:mm:ss SSS";
public static final String dateCSTPattern = "EEE MMM dd HH:mm:ss zzz yyyy";
private static final ThreadLocal<HashMap<String, SimpleDateFormat>> TL = ThreadLocal.withInitial(() -> new HashMap<>());
private static final ThreadLocal<HashMap<String, SimpleDateFormat>> TL = ThreadLocal.withInitial(HashMap::new);
private static final Map<String, DateTimeFormatter> dateTimeFormatters = new ConcurrentHashMap<>();

View File

@ -12,3 +12,5 @@ UPDATE_ONLY_SUPPORT_1_TABLE=\"UpdateByQuery\" \u4ec5\u652f\u6301\u4f20\u5165 1 \
UPDATE_OR_DELETE_NOT_ALLOW=\u6267\u884c "update" \u6216\u8005 "delete" \u7684 SQL \u65f6\uff0c\u4e0d\u5141\u8bb8\u5168\u8868\u64cd\u4f5c\uff0c\u5fc5\u987b\u8981\u6709 where \u6761\u4ef6\u3002
ENTITY_VERSION_NULL=\u4e50\u89c2\u9501\u5b9e\u4f53\u7c7b\u5fc5\u987b\u8bbe\u7f6e version \u7684\u503c\uff1a{0}\u3002
KEY_GENERATOR_BLANK=\u4e3b\u952e\u751f\u6210\u5668\u7684\u540d\u79f0\u4e0d\u80fd\u4e3a null \u6216\u8005\u7a7a\u5b57\u7b26\u4e32\u3002

View File

@ -116,6 +116,20 @@ public class AccountTester {
System.out.println(accounts);
}
/**
* issues https://gitee.com/mybatis-flex/mybatis-flex/issues/I7QD29
*/
@Test
public void testLeftJoinSelfForLogicDelete() {
QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper.from(ACCOUNT)
.leftJoin(ACCOUNT).as("a1").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.leftJoin(ACCOUNT).as("a2").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.ID.ge(1));
List<Article> accounts = articleMapper.selectListByQuery(queryWrapper);
System.out.println(accounts);
}
@Test
public void testSelectAsToDTO() {

View File

@ -2,6 +2,35 @@
# MyBatis-Flex is an elegant Mybatis Enhancement Framework.
<p align="center">
<a target="_blank" href="https://search.maven.org/search?q=mybatis-flex%20mybatis-flex">
<img src="https://img.shields.io/maven-central/v/com.mybatis-flex/parent?label=Maven%20Central" alt="Maven" />
</a>
<a target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0.txt">
<img src="https://img.shields.io/:license-Apache2-blue.svg" alt="Apache 2" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
<img src="https://img.shields.io/badge/JDK-8-green.svg" alt="jdk-8" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html">
<img src="https://img.shields.io/badge/JDK-11-green.svg" alt="jdk-11" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html">
<img src="https://img.shields.io/badge/JDK-17-green.svg" alt="jdk-17" />
</a>
<br />
<img src="https://img.shields.io/badge/SpringBoot-v2.x-blue">
<img src="https://img.shields.io/badge/SpringBoot-v3.x-blue">
<a target="_blank" href='https://github.com/noear/solon'><img src="https://img.shields.io/badge/Solon-v2.x-blue"></a>
<br />
<a target="_blank" href='https://gitee.com/mybatis-flex/mybatis-flex'>
<img src='https://gitee.com/mybatis-flex/mybatis-flex/badge/star.svg' alt='Gitee star'/>
</a>
<a target="_blank" href='https://github.com/mybatis-flex/mybatis-flex'>
<img src="https://img.shields.io/github/stars/mybatis-flex/mybatis-flex.svg?logo=github" alt="Github star"/>
</a>
</p>
## Features
- 1、MyBatis-Flex is very lightweight, and it only depends on Mybatis and no other third-party dependencies

View File

@ -3,6 +3,34 @@
# MyBatis-Flex 一个优雅的 MyBatis 增强框架
<p align="center">
<a target="_blank" href="https://search.maven.org/search?q=mybatis-flex%20mybatis-flex">
<img src="https://img.shields.io/maven-central/v/com.mybatis-flex/parent?label=Maven%20Central" alt="Maven" />
</a>
<a target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0.txt">
<img src="https://img.shields.io/:license-Apache2-blue.svg" alt="Apache 2" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html">
<img src="https://img.shields.io/badge/JDK-8-green.svg" alt="jdk-8" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html">
<img src="https://img.shields.io/badge/JDK-11-green.svg" alt="jdk-11" />
</a>
<a target="_blank" href="https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html">
<img src="https://img.shields.io/badge/JDK-17-green.svg" alt="jdk-17" />
</a>
<br />
<img src="https://img.shields.io/badge/SpringBoot-v2.x-blue">
<img src="https://img.shields.io/badge/SpringBoot-v3.x-blue">
<a target="_blank" href='https://gitee.com/noear/solon'><img src="https://img.shields.io/badge/Solon-v2.x-blue"></a>
<br />
<a target="_blank" href='https://gitee.com/mybatis-flex/mybatis-flex'>
<img src='https://gitee.com/mybatis-flex/mybatis-flex/badge/star.svg' alt='Gitee star'/>
</a>
<a target="_blank" href='https://github.com/mybatis-flex/mybatis-flex'>
<img src="https://img.shields.io/github/stars/mybatis-flex/mybatis-flex.svg?logo=github" alt="Github star"/>
</a>
</p>
## 特征