!435 feat:优化 “JOIN 自己” 写法

Merge pull request !435 from 王帅/main
This commit is contained in:
Michael Yang 2024-03-14 01:46:51 +00:00 committed by Gitee
commit bf302cdb52
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
20 changed files with 255 additions and 424 deletions

View File

@ -866,34 +866,43 @@ 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));
AccountTableDef a1 = ACCOUNT.as("a1");
AccountTableDef a2 = ACCOUNT.as("a2");
ArticleTableDef ar = ARTICLE.as("ar");
QueryWrapper queryWrapper = new QueryWrapper()
.select(ar.CONTENT, a1.ID, a2.AGE)
.from(ar)
.leftJoin(a1).on(a1.ID.eq(ar.ACCOUNT_ID))
.leftJoin(a2).on(a2.ID.eq(ar.ACCOUNT_ID));
```
其查询生成的 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` >= ?
SELECT
` ar `.` content `,
` a1 `.` id `,
` a2 `.` age `
FROM
` tb_article ` AS ` ar `
LEFT JOIN ` tb_account ` AS ` a1 ` ON ` a1 `.` id ` = ` ar `.` account_id `
LEFT JOIN ` tb_account ` AS ` a2 ` ON ` a2 `.` id ` = ` ar `.` 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` = ?
SELECT
` ar `.` content `,
` a1 `.` id `,
` a2 `.` age `
FROM
` tb_article ` AS ` ar `
LEFT JOIN ` tb_account ` AS ` a1 ` ON (` a1 `.` id ` = ` ar `.` account_id `)
AND ` a1 `.` is_delete ` = 0
LEFT JOIN ` tb_account ` AS ` a2 ` ON (` a2 `.` id ` = ` ar `.` account_id `)
AND ` a2 `.` is_delete ` = 0
```
> 关于逻辑删除更多文档请参考 [这里](../core/logic-delete.html)。

View File

@ -47,4 +47,13 @@ public class #(tableDefClassName) extends TableDef {
super("#(schema)", "#(table.name)");
}
private #(tableDefClassName)(String schema, String name, String alisa) {
super(schema, name, alisa);
}
public #(tableDefClassName) as(String alias) {
String key = getNameWithSchema() + "." + alias;
return getCache(key, k -> new #(tableDefClassName)("#(schema)", "#(table.name)", alias));
}
}

View File

@ -19,7 +19,6 @@ package com.mybatisflex.core.activerecord.query;
import com.mybatisflex.core.constant.SqlConnector;
import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.query.*;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.util.LambdaGetter;
@ -44,9 +43,7 @@ public abstract class QueryModel<T extends QueryModel<T>> {
protected QueryWrapper queryWrapper() {
if (queryWrapper == null) {
TableInfo tableInfo = TableInfoFactory.ofEntityClass(getClass());
QueryTable queryTable = new QueryTable();
queryTable.setSchema(tableInfo.getSchema());
queryTable.setName(tableInfo.getTableName());
QueryTable queryTable = new QueryTable(tableInfo.getSchema(), tableInfo.getTableName());
queryWrapper = QueryWrapper.create().from(queryTable);
}
return queryWrapper;
@ -159,12 +156,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.LEFT_JOIN, entityClass, when);
}
public JoinBuilder<T> leftJoin(TableDef table) {
return joins(SqlConsts.LEFT_JOIN, new QueryTable(table), true);
public JoinBuilder<T> leftJoin(QueryTable table) {
return joins(SqlConsts.LEFT_JOIN, table, true);
}
public JoinBuilder<T> leftJoin(TableDef table, boolean when) {
return joins(SqlConsts.LEFT_JOIN, new QueryTable(table), when);
public JoinBuilder<T> leftJoin(QueryTable table, boolean when) {
return joins(SqlConsts.LEFT_JOIN, table, when);
}
public JoinBuilder<T> leftJoin(QueryWrapper table) {
@ -191,12 +188,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.RIGHT_JOIN, entityClass, when);
}
public JoinBuilder<T> rightJoin(TableDef table) {
return joins(SqlConsts.RIGHT_JOIN, new QueryTable(table), true);
public JoinBuilder<T> rightJoin(QueryTable table) {
return joins(SqlConsts.RIGHT_JOIN, table, true);
}
public JoinBuilder<T> rightJoin(TableDef table, boolean when) {
return joins(SqlConsts.RIGHT_JOIN, new QueryTable(table), when);
public JoinBuilder<T> rightJoin(QueryTable table, boolean when) {
return joins(SqlConsts.RIGHT_JOIN, table, when);
}
public JoinBuilder<T> rightJoin(QueryWrapper table) {
@ -223,12 +220,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.INNER_JOIN, entityClass, when);
}
public JoinBuilder<T> innerJoin(TableDef table) {
return innerJoin(table, true);
public JoinBuilder<T> innerJoin(QueryTable table) {
return joins(SqlConsts.INNER_JOIN, table, true);
}
public JoinBuilder<T> innerJoin(TableDef table, boolean when) {
return joins(SqlConsts.INNER_JOIN, new QueryTable(table), when);
public JoinBuilder<T> innerJoin(QueryTable table, boolean when) {
return joins(SqlConsts.INNER_JOIN, table, when);
}
public JoinBuilder<T> innerJoin(QueryWrapper table) {
@ -255,12 +252,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.FULL_JOIN, entityClass, when);
}
public JoinBuilder<T> fullJoin(TableDef table) {
return joins(SqlConsts.FULL_JOIN, new QueryTable(table), true);
public JoinBuilder<T> fullJoin(QueryTable table) {
return joins(SqlConsts.FULL_JOIN, table, true);
}
public JoinBuilder<T> fullJoin(TableDef table, boolean when) {
return joins(SqlConsts.FULL_JOIN, new QueryTable(table), when);
public JoinBuilder<T> fullJoin(QueryTable table, boolean when) {
return joins(SqlConsts.FULL_JOIN, table, when);
}
public JoinBuilder<T> fullJoin(QueryWrapper table) {
@ -287,12 +284,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.CROSS_JOIN, entityClass, when);
}
public JoinBuilder<T> crossJoin(TableDef table) {
return joins(SqlConsts.CROSS_JOIN, new QueryTable(table), true);
public JoinBuilder<T> crossJoin(QueryTable table) {
return joins(SqlConsts.CROSS_JOIN, table, true);
}
public JoinBuilder<T> crossJoin(TableDef table, boolean when) {
return joins(SqlConsts.CROSS_JOIN, new QueryTable(table), when);
public JoinBuilder<T> crossJoin(QueryTable table, boolean when) {
return joins(SqlConsts.CROSS_JOIN, table, when);
}
public JoinBuilder<T> crossJoin(QueryWrapper table) {
@ -319,12 +316,12 @@ public abstract class QueryModel<T extends QueryModel<T>> {
return joins(SqlConsts.JOIN, entityClass, when);
}
public JoinBuilder<T> join(TableDef table) {
return joins(SqlConsts.JOIN, new QueryTable(table), true);
public JoinBuilder<T> join(QueryTable table) {
return joins(SqlConsts.JOIN, table, true);
}
public JoinBuilder<T> join(TableDef table, boolean when) {
return joins(SqlConsts.JOIN, new QueryTable(table), when);
public JoinBuilder<T> join(QueryTable table, boolean when) {
return joins(SqlConsts.JOIN, table, when);
}
public JoinBuilder<T> join(QueryWrapper table) {

View File

@ -32,7 +32,7 @@ public class Joiner<M> {
}
public Joiner<M> as(String alias) {
join.getQueryTable().as(alias);
join.queryTable = join.getQueryTable().as(alias);
return this;
}

View File

@ -20,7 +20,6 @@ import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.*;
import java.util.Collection;
@ -75,19 +74,14 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
this.name = StringUtil.tryTrim(name);
}
public QueryColumn(TableDef tableDef, String name) {
this(tableDef, name, null);
}
public QueryColumn(TableDef tableDef, String name, String alias) {
public QueryColumn(QueryTable queryTable, String name, String alias) {
SqlUtil.keepColumnSafely(name);
this.returnCopyByAsMethod = true;
this.table = new QueryTable(tableDef);
this.name = name;
this.alias = alias;
this.table = queryTable;
this.name = StringUtil.tryTrim(name);
this.alias = StringUtil.tryTrim(alias);
}
public QueryTable getTable() {
return table;
}

View File

@ -18,29 +18,23 @@ package com.mybatisflex.core.query;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.StringUtil;
import java.util.Objects;
/**
* 查询列描述的是一张表的字段
* 查询表
*
* @author michael
* @author 王帅
*/
public class QueryTable implements CloneSupport<QueryTable> {
protected int tableDefHashCode = 0;
protected String schema;
protected String name;
protected String alias;
public QueryTable() {
}
public QueryTable(TableDef tableDef) {
// TableDef的标识符号,0:不确定标识
this.tableDefHashCode = tableDef.hashCode();
this.schema = tableDef.getSchema();
this.name = tableDef.getTableName();
protected QueryTable() {
}
public QueryTable(String name) {
@ -97,12 +91,12 @@ public class QueryTable implements CloneSupport<QueryTable> {
if (table == null) {
return false;
}
if (StringUtil.isNotBlank(alias) && StringUtil.isNotBlank(table.alias) && (Objects.equals(alias, table.alias))) {
return false;
if (this == table) {
return true;
}
//比较对象都有tableDef标记,就用标记比对, 否则就用名称比对
if (tableDefHashCode != 0 && table.tableDefHashCode != 0) {
return tableDefHashCode == table.tableDefHashCode;
if (StringUtil.isNotBlank(alias)
&& StringUtil.isNotBlank(table.alias)) {
return Objects.equals(alias, table.alias);
}
return Objects.equals(name, table.name);
}

View File

@ -20,23 +20,11 @@ import com.mybatisflex.core.constant.SqlConnector;
import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.dialect.DialectFactory;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.util.ArrayUtil;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.LambdaGetter;
import com.mybatisflex.core.util.LambdaUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil;
import com.mybatisflex.core.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
@ -200,13 +188,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return this;
}
public QueryWrapper from(TableDef... tableDefs) {
for (TableDef tableDef : tableDefs) {
from(new QueryTable(tableDef));
}
return this;
}
public QueryWrapper from(Class<?>... entityClasses) {
for (Class<?> entityClass : entityClasses) {
TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass);
@ -253,7 +234,8 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
if (CollectionUtil.isEmpty(queryTables)) {
throw new IllegalArgumentException("query table must not be empty.");
}
queryTables.get(queryTables.size() - 1).alias = alias;
int index = queryTables.size() - 1;
queryTables.set(index, queryTables.get(index).as(alias));
return this;
}
@ -431,14 +413,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.LEFT_JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> leftJoin(TableDef table) {
return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), true);
}
public <Q extends QueryWrapper> Joiner<Q> leftJoin(TableDef table, boolean when) {
return joining(SqlConsts.LEFT_JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> leftJoin(QueryWrapper table) {
return joining(SqlConsts.LEFT_JOIN, table, true);
}
@ -467,14 +441,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.RIGHT_JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> rightJoin(TableDef table) {
return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), true);
}
public <Q extends QueryWrapper> Joiner<Q> rightJoin(TableDef table, boolean when) {
return joining(SqlConsts.RIGHT_JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> rightJoin(QueryWrapper table) {
return joining(SqlConsts.RIGHT_JOIN, table, true);
}
@ -503,14 +469,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.INNER_JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> innerJoin(TableDef table) {
return innerJoin(table, true);
}
public <Q extends QueryWrapper> Joiner<Q> innerJoin(TableDef table, boolean when) {
return joining(SqlConsts.INNER_JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> innerJoin(QueryWrapper table) {
return joining(SqlConsts.INNER_JOIN, table, true);
}
@ -539,14 +497,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.FULL_JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> fullJoin(TableDef table) {
return joining(SqlConsts.FULL_JOIN, new QueryTable(table), true);
}
public <Q extends QueryWrapper> Joiner<Q> fullJoin(TableDef table, boolean when) {
return joining(SqlConsts.FULL_JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> fullJoin(QueryWrapper table) {
return joining(SqlConsts.FULL_JOIN, table, true);
}
@ -575,14 +525,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.CROSS_JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> crossJoin(TableDef table) {
return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), true);
}
public <Q extends QueryWrapper> Joiner<Q> crossJoin(TableDef table, boolean when) {
return joining(SqlConsts.CROSS_JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> crossJoin(QueryWrapper table) {
return joining(SqlConsts.CROSS_JOIN, table, true);
}
@ -611,14 +553,6 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return joining(SqlConsts.JOIN, entityClass, when);
}
public <Q extends QueryWrapper> Joiner<Q> join(TableDef table) {
return joining(SqlConsts.JOIN, new QueryTable(table), true);
}
public <Q extends QueryWrapper> Joiner<Q> join(TableDef table, boolean when) {
return joining(SqlConsts.JOIN, new QueryTable(table), when);
}
public <Q extends QueryWrapper> Joiner<Q> join(QueryWrapper table) {
return joining(SqlConsts.JOIN, table, true);
}

View File

@ -16,7 +16,6 @@
package com.mybatisflex.core.query;
import com.mybatisflex.core.constant.SqlConnector;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.util.LambdaGetter;
import com.mybatisflex.core.util.LambdaUtil;
@ -98,13 +97,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return (R) this;
}
@Override
public R from(TableDef... tableDefs) {
super.from(tableDefs);
return (R) this;
}
@Override
public R from(Class<?>... entityClasses) {
super.from(entityClasses);
return (R) this;
@ -295,16 +287,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.leftJoin(entityClass, when);
}
@Override
public Joiner<R> leftJoin(TableDef table) {
return super.leftJoin(table);
}
@Override
public Joiner<R> leftJoin(TableDef table, boolean when) {
return super.leftJoin(table, when);
}
@Override
public Joiner<R> leftJoin(QueryWrapper table) {
return super.leftJoin(table);
@ -341,16 +323,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.rightJoin(entityClass, when);
}
@Override
public Joiner<R> rightJoin(TableDef table) {
return super.rightJoin(table);
}
@Override
public Joiner<R> rightJoin(TableDef table, boolean when) {
return super.rightJoin(table, when);
}
@Override
public Joiner<R> rightJoin(QueryWrapper table) {
return super.rightJoin(table);
@ -386,16 +358,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.innerJoin(entityClass, when);
}
@Override
public Joiner<R> innerJoin(TableDef table) {
return super.innerJoin(table);
}
@Override
public Joiner<R> innerJoin(TableDef table, boolean when) {
return super.innerJoin(table, when);
}
@Override
public Joiner<R> innerJoin(QueryWrapper table) {
return super.innerJoin(table);
@ -431,16 +393,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.fullJoin(entityClass, when);
}
@Override
public Joiner<R> fullJoin(TableDef table) {
return super.fullJoin(table);
}
@Override
public Joiner<R> fullJoin(TableDef table, boolean when) {
return super.fullJoin(table, when);
}
@Override
public Joiner<R> fullJoin(QueryWrapper table) {
return super.fullJoin(table);
@ -476,16 +428,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.crossJoin(entityClass, when);
}
@Override
public Joiner<R> crossJoin(TableDef table) {
return super.crossJoin(table);
}
@Override
public Joiner<R> crossJoin(TableDef table, boolean when) {
return super.crossJoin(table, when);
}
@Override
public Joiner<R> crossJoin(QueryWrapper table) {
return super.crossJoin(table);
@ -521,16 +463,6 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
return super.join(entityClass, when);
}
@Override
public Joiner<R> join(TableDef table) {
return super.join(table);
}
@Override
public Joiner<R> join(TableDef table, boolean when) {
return super.join(table, when);
}
@Override
public Joiner<R> join(QueryWrapper table) {
return super.join(table);

View File

@ -19,9 +19,13 @@ package com.mybatisflex.core.row;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.query.QueryWrapperAdapter;
import com.mybatisflex.core.table.*;
import com.mybatisflex.core.table.ColumnInfo;
import com.mybatisflex.core.table.IdInfo;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.update.PropertySetter;
import com.mybatisflex.core.util.FieldWrapper;
import com.mybatisflex.core.util.LambdaGetter;
@ -75,8 +79,8 @@ public class DbChain extends QueryWrapperAdapter<DbChain> implements PropertySet
return table(tableInfo.getSchema(), tableInfo.getTableName());
}
public static DbChain table(TableDef tableDef) {
return table(tableDef.getSchema(), tableDef.getTableName());
public static DbChain table(QueryTable queryTable) {
return table(queryTable.getSchema(), queryTable.getName());
}
private Row getRow() {

View File

@ -13,40 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.table;
import com.mybatisflex.core.query.QueryTable;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* @author michael
* 表定义内包含字段
*
* @author 王帅
* @since 2024-03-11
*/
public class TableDef implements Serializable {
public abstract class TableDef extends QueryTable {
private String schema;
private final String tableName;
public TableDef(String schema, String tableName) {
this.schema = schema;
this.tableName = tableName;
protected TableDef(String schema, String tableName) {
super(schema, tableName);
}
public TableDef(String tableName) {
this.tableName = tableName;
protected TableDef(String schema, String tableName, String alias) {
super(schema, tableName, alias);
}
/**
* 兼容方法 {@link #getName()} 相同
*
* @return 表名
*/
public String getTableName() {
return tableName;
return name;
}
public String getSchema() {
return schema;
}
private static final Map<String, TableDef> CACHE = new ConcurrentHashMap<>();
public QueryTable as(String alias) {
return new QueryTable(schema, tableName, alias);
@SuppressWarnings("unchecked")
protected static <V extends TableDef> V getCache(String key, Function<String, V> mappingFunction) {
return (V) CACHE.computeIfAbsent(key, mappingFunction);
}
}

View File

@ -1,97 +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.table;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.StringUtil;
import org.apache.ibatis.io.ResolverUtil;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author michael
*/
public class TableDefs implements Serializable {
private static final Map<String, TableDef> TABLE_DEF_MAP = new HashMap<>();
private static final Map<String, Map<String, QueryColumn>> QUERY_COLUMN_MAP = new HashMap<>();
public static void init(String packageName) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(TableDef.class), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
for (Class<?> type : typeSet) {
if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
try {
registerTableDef(type);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static TableDef getTableDef(Class<?> entityClass, String tableNameWithSchema) {
TableDef tableDef = TABLE_DEF_MAP.get(tableNameWithSchema);
if (tableDef == null) {
init(entityClass.getPackage().getName());
tableDef = TABLE_DEF_MAP.get(tableNameWithSchema);
}
return tableDef;
}
public static QueryColumn getQueryColumn(Class<?> entityClass, String tableNameWithSchema, String column) {
Map<String, QueryColumn> queryColumnMap = QUERY_COLUMN_MAP.get(tableNameWithSchema);
if (queryColumnMap == null) {
init(entityClass.getPackage().getName());
queryColumnMap = QUERY_COLUMN_MAP.get(tableNameWithSchema);
}
return queryColumnMap != null ? queryColumnMap.get(column) : null;
}
public static void registerTableDef(Class<?> tableDefClass) throws IllegalAccessException {
TableDef tableDef = (TableDef) ClassUtil.getFirstField(tableDefClass, field -> {
int mod = Modifier.fieldModifiers();
return Modifier.isPublic(mod) && Modifier.isStatic(mod);
}).get(null);
String key = StringUtil.buildSchemaWithTable(tableDef.getSchema(), tableDef.getTableName());
TABLE_DEF_MAP.put(key, tableDef);
List<Field> allFields = ClassUtil.getAllFields(tableDef.getClass(), field -> field.getType() == QueryColumn.class);
Map<String, QueryColumn> columnMap = new HashMap<>(allFields.size());
for (Field field : allFields) {
QueryColumn queryColumn = (QueryColumn) field.get(tableDef);
columnMap.put(queryColumn.getName(), queryColumn);
}
QUERY_COLUMN_MAP.put(key, columnMap);
}
}

View File

@ -15,11 +15,7 @@
*/
package com.mybatisflex.core.table;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.InsertListener;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.SetListener;
import com.mybatisflex.annotation.UpdateListener;
import com.mybatisflex.annotation.*;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.constant.SqlConsts;
@ -29,31 +25,12 @@ import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.mybatis.TypeHandlerObject;
import com.mybatisflex.core.query.Brackets;
import com.mybatisflex.core.query.CPI;
import com.mybatisflex.core.query.Join;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.query.SelectQueryColumn;
import com.mybatisflex.core.query.SelectQueryTable;
import com.mybatisflex.core.query.SqlOperators;
import com.mybatisflex.core.query.UnionWrapper;
import com.mybatisflex.core.query.*;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.tenant.TenantManager;
import com.mybatisflex.core.update.RawValue;
import com.mybatisflex.core.update.UpdateWrapper;
import com.mybatisflex.core.util.ArrayUtil;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.ConvertUtil;
import com.mybatisflex.core.util.EnumWrapper;
import com.mybatisflex.core.util.FieldWrapper;
import com.mybatisflex.core.util.ObjectUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil;
import com.mybatisflex.core.util.*;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
@ -68,26 +45,13 @@ import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.mybatisflex.core.constant.SqlConsts.AND;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS_PLACEHOLDER;
import static com.mybatisflex.core.constant.SqlConsts.IN;
import static com.mybatisflex.core.constant.SqlConsts.*;
public class TableInfo {
@ -984,7 +948,10 @@ public class TableInfo {
}
Object value = metaObject.getValue(property);
if (value != null && !"".equals(value)) {
QueryColumn queryColumn = buildQueryColumn(column);
QueryColumn queryColumn = Arrays.stream(queryColumns)
.filter(e -> e.getName().equals(column))
.findFirst()
.orElse(QueryMethods.column(getTableNameWithSchema(), column));
if (operators != null && operators.containsKey(property)) {
SqlOperator operator = operators.get(property);
if (operator == SqlOperator.IGNORE) {
@ -1006,17 +973,6 @@ public class TableInfo {
return queryWrapper;
}
public QueryColumn buildQueryColumn(String column) {
String tableNameWithSchema = getTableNameWithSchema();
QueryColumn queryColumn = TableDefs.getQueryColumn(entityClass, tableNameWithSchema, column);
if (queryColumn == null) {
queryColumn = QueryMethods.column(tableNameWithSchema, column);
}
return queryColumn;
}
public String getKeyProperties() {
StringJoiner joiner = new StringJoiner(",");
for (IdInfo value : primaryKeyList) {

View File

@ -30,33 +30,45 @@ import com.mybatisflex.core.query.SqlOperators;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.table.TableManager;
import com.mybatisflex.coretest.table.AccountTableDef;
import com.mybatisflex.coretest.table.ArticleTableDef;
import org.junit.Assert;
import org.junit.Test;
import java.util.Date;
import static com.mybatisflex.core.query.QueryMethods.avg;
import static com.mybatisflex.core.query.QueryMethods.case_;
import static com.mybatisflex.core.query.QueryMethods.column;
import static com.mybatisflex.core.query.QueryMethods.convert;
import static com.mybatisflex.core.query.QueryMethods.count;
import static com.mybatisflex.core.query.QueryMethods.distinct;
import static com.mybatisflex.core.query.QueryMethods.exists;
import static com.mybatisflex.core.query.QueryMethods.left;
import static com.mybatisflex.core.query.QueryMethods.max;
import static com.mybatisflex.core.query.QueryMethods.noCondition;
import static com.mybatisflex.core.query.QueryMethods.notExists;
import static com.mybatisflex.core.query.QueryMethods.raw;
import static com.mybatisflex.core.query.QueryMethods.select;
import static com.mybatisflex.core.query.QueryMethods.selectCountOne;
import static com.mybatisflex.core.query.QueryMethods.selectOne;
import static com.mybatisflex.core.query.QueryMethods.year;
import static com.mybatisflex.core.query.QueryMethods.*;
import static com.mybatisflex.coretest.table.Account01TableDef.ACCOUNT01;
import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT;
import static com.mybatisflex.coretest.table.ArticleTableDef.ARTICLE;
public class AccountSqlTester {
@Test
public void testAlisa() {
AccountTableDef a1 = ACCOUNT.as("a1");
AccountTableDef a2 = ACCOUNT.as("a2");
ArticleTableDef ar = ARTICLE.as("ar");
QueryWrapper queryWrapper = new QueryWrapper()
.select(ar.CONTENT, a1.ID, a2.AGE)
.from(ar)
.leftJoin(a1).on(a1.ID.eq(ar.ACCOUNT_ID))
.leftJoin(a2).on(a2.ID.eq(ar.ACCOUNT_ID));
String sql = SqlFormatter.format(queryWrapper.toSQL());
Assert.assertEquals("SELECT\n" +
" ` ar `.` content `,\n" +
" ` a1 `.` id `,\n" +
" ` a2 `.` age `\n" +
"FROM\n" +
" ` tb_article ` AS ` ar `\n" +
" LEFT JOIN ` tb_account ` AS ` a1 ` ON ` a1 `.` id ` = ` ar `.` account_id `\n" +
" LEFT JOIN ` tb_account ` AS ` a2 ` ON ` a2 `.` id ` = ` ar `.` account_id `", sql);
System.out.println(sql);
Assert.assertSame(a1, a1.as("a1"));
Assert.assertNotSame(a1, a1.as("a2"));
Assert.assertNotSame(a1, a2);
}
@Test
public void testOracleFrom() {
OracleDialect oracleDialect = new OracleDialect();
@ -852,11 +864,12 @@ public class AccountSqlTester {
QueryWrapper qw = QueryWrapper.create(account, operators);
Assert.assertEquals("SELECT `id`, `user_name`, `birthday`, `sex`, `age`, `is_normal`, `is_delete` FROM `tb_account` " +
"WHERE `user_name` LIKE 'michael%' A" +
"ND `sex` = 0 " +
"WHERE `user_name` LIKE 'michael%' " +
"AND `sex` = 0 " +
"AND `age` >= 18 " +
"AND `is_normal` = false"
, qw.toSQL());
System.out.println(SqlFormatter.format(qw.toSQL()));
}
}

View File

@ -1,3 +1,19 @@
/*
* 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.coretest;
import com.mybatisflex.core.dialect.DbType;
@ -9,7 +25,6 @@ import com.mybatisflex.core.row.RowKey;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.coretest.auth.AuthDialectImpl;
import com.mybatisflex.coretest.auth.Project;
import com.mybatisflex.coretest.auth.table.ProjectTableDef;
import org.junit.Before;
import org.junit.Test;
@ -35,10 +50,10 @@ public class AuthTest {
public void test() {
// 1.单个删除
assert "DELETE FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forDeleteById(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}));
.equals(dialect.forDeleteById(PROJECT.getSchema(), PROJECT.getName(), new String[]{PROJECT.ID.getName()}));
// 2.批量删除
assert "DELETE FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forDeleteBatchByIds(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
.equals(dialect.forDeleteBatchByIds(PROJECT.getSchema(), PROJECT.getName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
// 3.查询
QueryWrapper deleteWrapper =
QueryWrapper.create(new Project()).where(PROJECT.ID.eq(1));
@ -46,7 +61,7 @@ public class AuthTest {
.equals(dialect.forDeleteByQuery(deleteWrapper));
// 4.更新
assert "UPDATE `tb_project` SET `name` = ? WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forUpdateById(PROJECT.getSchema(), PROJECT.getTableName(),
.equals(dialect.forUpdateById(PROJECT.getSchema(), PROJECT.getName(),
Row.ofKey(RowKey.AUTO).set(PROJECT.NAME, "项目")));
// 5.更新
Row row = new Row();
@ -57,7 +72,7 @@ public class AuthTest {
.equals(dialect.forUpdateByQuery(updateWrapper, row));
// 6.ID查询
assert "SELECT * FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = 1"
.equals(dialect.forSelectOneById(PROJECT.getSchema(), PROJECT.getTableName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
.equals(dialect.forSelectOneById(PROJECT.getSchema(), PROJECT.getName(), new String[]{PROJECT.ID.getName()}, new Object[]{1L}));
QueryWrapper queryWrapper = QueryWrapper.create(new Project()).where(PROJECT.ID.eq(1));
// 7.query查询
assert "SELECT `id`, `name`, `insert_user_id`, `is_delete` FROM `tb_project` WHERE `id` = ? AND `insert_user_id` = ?"

View File

@ -18,13 +18,7 @@ package com.mybatisflex.coretest;
import com.mybatisflex.core.constant.SqlConnector;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.query.CPI;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryColumnBehavior;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.query.*;
import com.mybatisflex.core.util.StringUtil;
import org.junit.Assert;
import org.junit.Test;
@ -39,9 +33,7 @@ import static com.mybatisflex.core.query.QueryColumnBehavior.getConditionCaster;
import static com.mybatisflex.core.query.QueryMethods.bracket;
import static com.mybatisflex.core.query.QueryMethods.raw;
import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* 动态条件测试
@ -109,7 +101,7 @@ public class DynamicConditionTest {
boolean anyMatch = CPI.getQueryTables(queryWrapper)
.stream()
.map(QueryTable::getName)
.anyMatch(tableName -> tableName.equals(ACCOUNT.getTableName()));
.anyMatch(tableName -> tableName.equals(ACCOUNT.getName()));
if (anyMatch) {
CPI.addWhereQueryCondition(queryWrapper, ACCOUNT.AGE.ge(18), SqlConnector.AND);

View File

@ -1,6 +1,23 @@
package com.mybatisflex.core;
/*
* 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.coretest;
import com.mybatisflex.annotation.UpdateListener;
import com.mybatisflex.core.FlexGlobalConfig;
import org.junit.Assert;
import org.junit.Test;

View File

@ -1,3 +1,19 @@
/*
* 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.coretest.auth;
import com.mybatisflex.core.dialect.OperateType;
@ -25,7 +41,7 @@ public class AuthDialectImpl extends CommonsDialectImpl {
return;
}
for (QueryTable queryTable : queryTables) {
if (PROJECT.getTableName().equals(queryTable.getName())) {
if (PROJECT.getName().equals(queryTable.getName())) {
queryWrapper.and(PROJECT.INSERT_USER_ID.eq(1));
}
}
@ -34,7 +50,7 @@ public class AuthDialectImpl extends CommonsDialectImpl {
@Override
public void prepareAuth(String schema, String tableName, StringBuilder sql, OperateType operateType) {
if (PROJECT.getTableName().equals(tableName)) {
if (PROJECT.getName().equals(tableName)) {
sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1);
}
super.prepareAuth(schema, tableName, sql, operateType);
@ -42,7 +58,7 @@ public class AuthDialectImpl extends CommonsDialectImpl {
@Override
public void prepareAuth(TableInfo tableInfo, StringBuilder sql, OperateType operateType) {
if (PROJECT.getTableName().equals(tableInfo.getTableName())) {
if (PROJECT.getName().equals(tableInfo.getTableName())) {
sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1);
}
super.prepareAuth(tableInfo, sql, operateType);

View File

@ -136,6 +136,15 @@ public class ContentBuilder {
: StrUtil.firstCharToLowerCase(tableInfo.getEntitySimpleName());
content.append(" public ").append(tableDefClassName).append("() {\n")
.append(" super").append("(\"").append(schema).append("\", \"").append(tableName).append("\");\n")
.append(" }\n\n");
content.append(" private ").append(tableDefClassName).append("(String schema, String name, String alisa) {\n")
.append(" super(schema, name, alisa);\n")
.append(" }\n\n");
content.append(" public ").append(tableDefClassName).append(" as(String alias) {\n")
.append(" String key = getNameWithSchema() + \".\" + alias;\n")
.append(" return getCache(key, k -> new ").append(tableDefClassName).append("(\"").append(schema).append("\", \"").append(tableName).append("\", alias));\n")
.append(" }\n\n}\n");
return content.toString();
}

View File

@ -1,9 +1,25 @@
/*
* 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.issue113.def;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.query.QueryTable;
public class TClassTableDef extends TableDef {
public class TClassTableDef extends QueryTable {
public static final TClassTableDef TB_CLASS = new TClassTableDef();
public final QueryColumn ID = new QueryColumn(this, "id");

View File

@ -1,9 +1,25 @@
/*
* 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.issue113.def;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.table.TableDef;
import com.mybatisflex.core.query.QueryTable;
public class TUserTableDef extends TableDef {
public class TUserTableDef extends QueryTable {
public static final TUserTableDef TB_USER = new TUserTableDef();
public final QueryColumn ID = new QueryColumn(this, "id");