!105 optimize mybatis-flex-processor

Merge pull request !105 from 王帅/main
This commit is contained in:
Michael Yang 2023-07-04 03:15:08 +00:00 committed by Gitee
commit b58585c18c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
15 changed files with 2538 additions and 171 deletions

View File

@ -127,18 +127,8 @@ FROM tb_account
目前MyBatis-Flex 内置的函数支持如下:
- count
- max
- min
- avg
- sum
- year
- month
- day
- convert
- concat
目前MyBatis-Flex 基本支持所有 SQL
函数,查看已支持的 [所有函数](https://gitee.com/mybatis-flex/mybatis-flex/blob/main/mybatis-flex-core/src/main/java/com/mybatisflex/core/const/FuncName.java)。
更多的函数,用户可以参考 [QueryMethods](https://gitee.com/mybatis-flex/mybatis-flex/blob/main/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryMethods.java)
,然后再自己的项目里进行自定义扩展。

View File

@ -332,6 +332,20 @@ public interface BaseMapper<T> {
@UpdateProvider(type = EntitySqlProvider.class, method = "updateNumberAddByQuery")
int updateNumberAddByQuery(@Param(FlexConsts.FIELD_NAME) String fieldName, @Param(FlexConsts.VALUE) Number value, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
/**
* 执行类似 update table set field=field+1 where ... 的场景
*
* @param column 字段名
* @param value >=0 小于 0
* @param queryWrapper 条件
* @see EntitySqlProvider#updateNumberAddByQuery(Map, ProviderContext)
*/
default int updateNumberAddByQuery(QueryColumn column, Number value, QueryWrapper queryWrapper) {
if (value == null) {
throw FlexExceptions.wrap("value can not be null.");
}
return updateNumberAddByQuery(column.getName(), value, queryWrapper);
}
/**
* 执行类似 update table set field=field+1 where ... 的场景

View File

@ -0,0 +1,149 @@
/*
* 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.constant;
/**
* 支持的 SQL 函数名
*
* @author 王帅
* @since 2023-07-03
*/
public class FuncName {
public static final String ABS = "ABS";
public static final String ACOS = "ACOS";
public static final String ADDDATE = "ADDDATE";
public static final String ADDTIME = "ADDTIME";
public static final String ASCII = "ASCII";
public static final String ASIN = "ASIN";
public static final String ATAN = "ATAN";
public static final String AVG = "AVG";
public static final String BIN = "BIN";
public static final String CEIL = "CEIL";
public static final String CEILING = "CEILING";
public static final String CHARSET = "CHARSET";
public static final String CHAR_LENGTH = "CHAR_LENGTH";
public static final String COLLATION = "COLLATION";
public static final String CONCAT = "CONCAT";
public static final String CONCAT_WS = "CONCAT_WS";
public static final String CONNECTION_ID = "CONNECTION_ID";
public static final String CONV = "CONV";
public static final String CONVERT = "CONVERT";
public static final String COS = "COS";
public static final String COT = "COT";
public static final String COUNT = "COUNT";
public static final String CURDATE = "CURDATE";
public static final String CURRENT_DATE = "CURRENT_DATE";
public static final String CURRENT_TIME = "CURRENT_TIME";
public static final String CURRENT_TIMESTAMP = "CURRENT_TIMESTAMP";
public static final String CURTIME = "CURTIME";
public static final String DATABASE = "DATABASE";
public static final String DATEDIFF = "DATEDIFF";
public static final String DATE_FORMAT = "DATE_FORMAT";
public static final String DAY = "DAY";
public static final String DAYNAME = "DAYNAME";
public static final String DAYOFMONTH = "DAYOFMONTH";
public static final String DAYOFWEEK = "DAYOFWEEK";
public static final String DAYOFYEAR = "DAYOFYEAR";
public static final String DECODE = "DECODE";
public static final String DEGREES = "DEGREES";
public static final String ELT = "ELT";
public static final String ENCODE = "ENCODE";
public static final String EXP = "EXP";
public static final String FIELD = "FIELD";
public static final String FIND_IN_SET = "FIND_IN_SET";
public static final String FLOOR = "FLOOR";
public static final String FORMAT = "FORMAT";
public static final String FROM_DAYS = "FROM_DAYS";
public static final String FROM_UNIXTIME = "FROM_UNIXTIME";
public static final String GET_FORMAT = "GET_FORMAT";
public static final String GET_LOCT = "GET_LOCT";
public static final String HEX = "HEX";
public static final String HOUR = "HOUR";
public static final String INET_ATON = "INET_ATON";
public static final String INET_NTOA = "INET_NTOA";
public static final String INSERT = "INSERT";
public static final String INSTR = "INSTR";
public static final String IS_FREE_LOCK = "IS_FREE_LOCK";
public static final String LAST_INSERT_ID = "LAST_INSERT_ID";
public static final String LEFT = "LEFT";
public static final String LENGTH = "LENGTH";
public static final String LOCALTIME = "LOCALTIME";
public static final String LOCALTIMESTAMP = "LOCALTIMESTAMP";
public static final String LOG = "LOG";
public static final String LOG10 = "LOG10";
public static final String LOWER = "LOWER";
public static final String LPAD = "LPAD";
public static final String LTRIM = "LTRIM";
public static final String MAX = "MAX";
public static final String MD5 = "MD5";
public static final String MIN = "MIN";
public static final String MINUTE = "MINUTE";
public static final String MOD = "MOD";
public static final String MONTH = "MONTH";
public static final String MONTHNAME = "MONTHNAME";
public static final String NOW = "NOW";
public static final String OCT = "OCT";
public static final String PASSWORD = "PASSWORD";
public static final String PI = "PI";
public static final String POW = "POW";
public static final String POWER = "POWER";
public static final String QUARTER = "QUARTER";
public static final String RADIANS = "RADIANS";
public static final String RAND = "RAND";
public static final String RELEASE_LOCK = "RELEASE_LOCK";
public static final String REPEAT = "REPEAT";
public static final String REPLACE = "REPLACE";
public static final String REVERSE = "REVERSE";
public static final String RIGHT = "RIGHT";
public static final String ROUND = "ROUND";
public static final String RPAD = "RPAD";
public static final String RTRIM = "RTRIM";
public static final String SCHEMA = "SCHEMA";
public static final String SECOND = "SECOND";
public static final String SEC_TO_TIME = "SEC_TO_TIME";
public static final String SIGN = "SIGN";
public static final String SIN = "SIN";
public static final String SPACE = "SPACE";
public static final String SQRT = "SQRT";
public static final String STRCMP = "STRCMP";
public static final String SUBDATE = "SUBDATE";
public static final String SUBSTRING = "SUBSTRING";
public static final String SUBTIME = "SUBTIME";
public static final String SUM = "SUM";
public static final String SYSDATE = "SYSDATE";
public static final String TAN = "TAN";
public static final String TIME_FORMAT = "TIME_FORMAT";
public static final String TIME_TO_SEC = "TIME_TO_SEC";
public static final String TO_DAYS = "TO_DAYS";
public static final String TRIM = "TRIM";
public static final String TRUNCATE = "TRUNCATE";
public static final String UNIX_TIMESTAMP = "UNIX_TIMESTAMP";
public static final String UPPER = "UPPER";
public static final String USER = "USER";
public static final String UTC_DATE = "UTC_DATE";
public static final String UTC_TIME = "UTC_TIME";
public static final String VERSION = "VERSION";
public static final String WEEK = "WEEK";
public static final String WEEKDAY = "WEEKDAY";
public static final String WEEKOFYEAR = "WEEKOFYEAR";
public static final String YEAR = "YEAR";
private FuncName() {
}
}

View File

@ -113,7 +113,6 @@ public final class SqlConsts {
public static final String GE = " >= ";
public static final String LT = " < ";
public static final String LE = " <= ";
public static final String NOT = " NOT ";
public static final String LIKE = " LIKE ";
public static final String EQUALS = " = ";
public static final String NOT_EQUALS = " != ";
@ -123,8 +122,6 @@ public final class SqlConsts {
public static final String NOT_IN = " NOT IN ";
public static final String BETWEEN = " BETWEEN ";
public static final String NOT_BETWEEN = " NOT BETWEEN ";
public static final String EXISTS = " EXISTS ";
public static final String NOT_EXISTS = " NOT EXISTS ";
// === 排序相关关键字 ===
@ -135,19 +132,6 @@ public final class SqlConsts {
public static final String NULLS_LAST = " NULLS LAST";
// === SQL 函数名 ===
public static final String SUM = "SUM";
public static final String MAX = "MAX";
public static final String MIN = "MIN";
public static final String AVG = "AVG";
public static final String DAY = "DAY";
public static final String YEAR = "YEAR";
public static final String MONTH = "MONTH";
public static final String COUNT = "COUNT";
public static final String CONVERT = "CONVERT";
// === 数学运算符 ===
public static final String PLUS_SIGN = " + ";

View File

@ -316,6 +316,11 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String buildSelectSql(QueryWrapper queryWrapper) {
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
if (CollectionUtil.isEmpty(queryTables)) {
throw FlexExceptions.wrap("You must use the 'FROM' clause to select the table.");
}
List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper);
List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables);
@ -332,6 +337,11 @@ public class CommonsDialectImpl implements IDialect {
QueryColumn selectColumn = selectColumns.get(i);
QueryTable selectColumnTable = selectColumn.getTable();
// function 等没有对应的 selectColumnTable
if (selectColumnTable == null) {
continue;
}
//用户未配置别名的情况下自动未用户添加别名
if (StringUtil.isBlank(selectColumn.getAlias())
&& !(selectColumnTable instanceof SelectQueryTable)

View File

@ -21,6 +21,7 @@ import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.query.StringQueryColumn;
import org.junit.Test;
import static com.mybatisflex.core.query.QueryMethods.*;
import static com.mybatisflex.coretest.table.AccountTableDef.ACCOUNT;
/**
@ -40,4 +41,15 @@ public class FunctionSqlTest {
System.out.println(sql);
}
@Test
public void test02() {
String sql = QueryWrapper.create()
.select(concatWs(string("abc"), ACCOUNT.USER_NAME, ACCOUNT.BIRTHDAY))
.select(abs(number(-3)))
.from(ACCOUNT)
.where(not(ACCOUNT.ID.eq(1)))
.toSQL();
System.out.println(sql);
}
}

View File

@ -148,12 +148,8 @@ public class MybatisFlexProcessor extends AbstractProcessor {
assert table != null;
// 类属性
//修改bug https://gitee.com/mybatis-flex/mybatis-flex/issues/I7I08X
//会执行 subClass subClass
//再执行 superClass superClass
//按照顺序使用子类有的属性父类放不进去也就形成了子类覆盖父类
Collection<ColumnInfo> columnInfoList = new HashSet<>();
// 类属性 fix: https://gitee.com/mybatis-flex/mybatis-flex/issues/I7I08X
Set<ColumnInfo> columnInfos = new HashSet<>();
// 默认查询的属性 isLarge 字段
List<String> defaultColumns = new ArrayList<>();
@ -161,7 +157,7 @@ public class MybatisFlexProcessor extends AbstractProcessor {
do {
// 获取类属性和默认查询字段
fillColumnInfoList(columnInfoList, defaultColumns, (TypeElement) entityClassElement, classElement, table.camelToUnderline());
fillColumnInfoList(columnInfos, defaultColumns, (TypeElement) entityClassElement, classElement, table.camelToUnderline());
classElement = (TypeElement) typeUtils.asElement(classElement.getSuperclass());
} while (classElement != null);
@ -181,7 +177,7 @@ public class MybatisFlexProcessor extends AbstractProcessor {
String tableDefPackage = StrUtil.buildTableDefPackage(entityClass);
String tableDefClassName = entityClassName.concat(tableDefClassSuffix);
String tableDefContent = ContentBuilder.buildTableDef(table, entityClass, entityClassName, allInTablesEnable, tableDefPackage, tableDefClassName
, tableDefPropertiesNameStyle, tableDefInstanceSuffix, columnInfoList, defaultColumns);
, tableDefPropertiesNameStyle, tableDefInstanceSuffix, columnInfos, defaultColumns);
processGenClass(genPath, tableDefPackage, tableDefClassName, tableDefContent);
if (allInTablesEnable) {
@ -224,7 +220,7 @@ public class MybatisFlexProcessor extends AbstractProcessor {
return SourceVersion.latestSupported();
}
private void fillColumnInfoList(Collection<ColumnInfo> columnInfoList, List<String> defaultColumns, TypeElement baseElement, TypeElement classElement, boolean camelToUnderline) {
private void fillColumnInfoList(Set<ColumnInfo> columnInfos, List<String> defaultColumns, TypeElement baseElement, TypeElement classElement, boolean camelToUnderline) {
for (Element fieldElement : classElement.getEnclosedElements()) {
// all fields
@ -300,9 +296,8 @@ public class MybatisFlexProcessor extends AbstractProcessor {
columnInfo.setProperty(property);
columnInfo.setColumn(columnName);
columnInfo.setAlias(alias);
columnInfo.setFullClassName(baseElement.getQualifiedName().toString());
columnInfoList.add(columnInfo);
columnInfos.add(columnInfo);
if (column == null || (!column.isLarge() && !column.isLogicDelete())) {
defaultColumns.add(columnName);
@ -313,6 +308,9 @@ public class MybatisFlexProcessor extends AbstractProcessor {
private String[] getColumnAliasByGetterMethod(TypeElement baseElement, String property) {
if (baseElement == null) {
return null;
}
for (Element enclosedElement : baseElement.getEnclosedElements()) {
if (ElementKind.METHOD == enclosedElement.getKind()) {
String methodName = enclosedElement.toString();
@ -320,12 +318,14 @@ public class MybatisFlexProcessor extends AbstractProcessor {
ColumnAlias columnAlias = enclosedElement.getAnnotation(ColumnAlias.class);
if (columnAlias != null) {
return columnAlias.value();
} else {
// 重写方法忽略别名
return null;
}
break;
}
}
}
return null;
return getColumnAliasByGetterMethod((TypeElement) typeUtils.asElement(baseElement.getSuperclass()), property);
}

View File

@ -57,7 +57,7 @@ public class ContentBuilder {
public static String buildTableDef(Table table, String entityClass, String entityClassName, boolean allInTablesEnable,
String tableDefPackage, String tableDefClassName,
String tableDefPropertiesNameStyle, String tableDefInstanceSuffix,
Collection<ColumnInfo> columnInfoList, List<String> defaultColumns) {
Collection<ColumnInfo> columnInfos, List<String> defaultColumns) {
StringBuilder content = new StringBuilder("package ");
content.append(tableDefPackage).append(";\n\n");
content.append("import com.mybatisflex.core.query.QueryColumn;\n");
@ -74,7 +74,7 @@ public class ContentBuilder {
content.append(" public static final ").append(tableDefClassName).append(' ').append(StrUtil.buildFieldName(entityClassName.concat(tableDefInstanceSuffix != null ? tableDefInstanceSuffix.trim() : ""), tableDefPropertiesNameStyle))
.append(" = new ").append(tableDefClassName).append("(\"").append(schema).append("\", \"").append(tableName).append("\");\n\n");
}
columnInfoList.forEach((columnInfo) -> {
columnInfos.forEach((columnInfo) -> {
content.append(" public QueryColumn ")
.append(StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle))
.append(" = new QueryColumn(this, \"")
@ -86,7 +86,7 @@ public class ContentBuilder {
});
content.append(" public QueryColumn ").append(StrUtil.buildFieldName("allColumns", tableDefPropertiesNameStyle)).append(" = new QueryColumn(this, \"*\");\n");
StringJoiner defaultColumnJoiner = new StringJoiner(", ");
columnInfoList.forEach((columnInfo) -> {
columnInfos.forEach((columnInfo) -> {
if (defaultColumns.contains(columnInfo.getColumn())) {
defaultColumnJoiner.add(StrUtil.buildFieldName(columnInfo.getProperty(), tableDefPropertiesNameStyle));
}

View File

@ -41,8 +41,6 @@ public class ColumnInfo {
*/
private String[] alias;
private String fullClassName;
public String getProperty() {
return property;
}
@ -67,24 +65,21 @@ public class ColumnInfo {
this.alias = alias;
}
public String getFullClassName() {
return fullClassName;
}
public void setFullClassName(String fullClassName) {
this.fullClassName = fullClassName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ColumnInfo that = (ColumnInfo) o;
return Objects.equals(property, that.property) && Objects.equals(fullClassName, that.fullClassName);
return Objects.equals(property, that.property);
}
@Override
public int hashCode() {
return Objects.hash(property, fullClassName);
return property != null ? property.hashCode() : 0;
}
}

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.test;
import com.mybatisflex.annotation.*;
@ -17,6 +33,7 @@ public class Account extends BaseEntity implements Serializable, AgeAware {
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
@ColumnAlias("account_id")
private Long id;
@ColumnMask(Masks.CHINESE_NAME)

View File

@ -0,0 +1,44 @@
/*
* 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.annotation.ColumnAlias;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
@Table(value = "tb_account_1")
public class Account1 extends Account implements Serializable {
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private int age;
private int ageVV;
@Override
@ColumnAlias("account_1_id")
public Long getId() {
return id;
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.annotation.Table;
import java.io.Serializable;
@Table(value = "tb_account_2")
public class Account2 extends Account1 implements Serializable {
private static final long serialVersionUID = 1L;
private int age;
}

View File

@ -0,0 +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.test;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
@Table(value = "tb_account_3")
public class Account3 extends Account2 implements Serializable {
private static final long serialVersionUID = 1L;
private int age;
@Override
public Long getId() {
return super.getId();
}
}

View File

@ -1,19 +0,0 @@
package com.mybatisflex.test;
import com.mybatisflex.annotation.*;
import java.io.Serializable;
@Table(value = "tb_account_vv", dataSource = "ds2", onSet = AccountOnSetListener.class)
public class AccountVV extends Account implements Serializable {
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private int age;
private int ageVV;
}