diff --git a/docs/zh/base/query.md b/docs/zh/base/query.md index 00da7963..57aa3468 100644 --- a/docs/zh/base/query.md +++ b/docs/zh/base/query.md @@ -80,6 +80,38 @@ List results = mapper.selectListByQueryAs(query, ArticleDTO.class); System.out.println(results); ``` +假设 `ArticleDTO` 定义的属性和 SQL 查询的字段不一致时,例如: + +```java +public class ArticleDTO { + + private Long id; + private Long accountId; + private String title; + private String content; + + //以下用户字段 和 用户表定义的列不一致,表定义的列为 user_name + private String authorName; + private int authorAge; + private Date birthday; +} +``` + +那么, `QueryWrapper` 需要添加 as,修改如下: + +```java 3,4 +QueryWrapper asWrapper = QueryWrapper.create() + .select(ARTICLE.ALL_COLUMNS) + .select(ACCOUNT.USER_NAME.as(ArticleDTO::getAuthorName) + ,ACCOUNT.AGE.as(ArticleDTO::getAuthorAge) + ,ACCOUNT.BIRTHDAY + ) + .from(ARTICLE) + .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID)) + .where(ACCOUNT.ID.ge(0)); +``` + + **注意事项:** 关联查询(`selectOneByQueryAs`、`selectListByQueryAs` 、`paginateAs` 等方法)中的 `asType` 参数类型(比如:`ArticleDTO`), diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryColumn.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryColumn.java index 5efa80ac..2d5f10b3 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryColumn.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryColumn.java @@ -18,6 +18,8 @@ package com.mybatisflex.core.query; import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.table.TableDef; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.LambdaUtil; import com.mybatisflex.core.util.SqlUtil; import com.mybatisflex.core.util.StringUtil; @@ -80,6 +82,10 @@ public class QueryColumn implements Serializable { this.alias = alias; } + public QueryColumn as(LambdaGetter fn) { + return as(LambdaUtil.getFieldName(fn)); + } + public QueryColumn as(String alias) { SqlUtil.keepColumnSafely(alias); QueryColumn newColumn = new QueryColumn(); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java index b4d2953e..65506cbb 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java @@ -640,6 +640,16 @@ public class TableInfo { .typeHandler(columnInfo.buildTypeHandler()) .build(); resultMappings.add(mapping); + + //add property mapper for sql as ... + if (!Objects.equals(columnInfo.getColumn(), columnInfo.getProperty())) { + ResultMapping propertyMapping = new ResultMapping.Builder(configuration, columnInfo.getProperty(), + columnInfo.getProperty(), columnInfo.getPropertyType()) + .jdbcType(columnInfo.getJdbcType()) + .typeHandler(columnInfo.buildTypeHandler()) + .build(); + resultMappings.add(propertyMapping); + } } for (IdInfo idInfo : primaryKeyList) { diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaGetter.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaGetter.java new file mode 100644 index 00000000..ede3a678 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaGetter.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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 + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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.util; + +import java.io.Serializable; + +@FunctionalInterface +public interface LambdaGetter extends Serializable { + Object get(T source); +} + diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java new file mode 100644 index 00000000..b27bf4c7 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/LambdaUtil.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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 + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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.util; + +import org.apache.ibatis.reflection.property.PropertyNamer; +import org.apache.ibatis.util.MapUtil; + +import java.io.Serializable; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class LambdaUtil { + + private static final Map, SerializedLambda> lambdaMap = new ConcurrentHashMap<>(); + + public static String getFieldName(LambdaGetter getter) { + SerializedLambda lambda = getSerializedLambda(getter); + String methodName = lambda.getImplMethodName(); + return PropertyNamer.methodToProperty(methodName); + } + + + private static SerializedLambda getSerializedLambda(Serializable getter) { + return MapUtil.computeIfAbsent(lambdaMap, getter.getClass(), aClass -> { + try { + Method method = getter.getClass().getDeclaredMethod("writeReplace"); + method.setAccessible(Boolean.TRUE); + return (SerializedLambda) method.invoke(getter); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java index e55d9a9a..b6edca9b 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java @@ -12,9 +12,9 @@ public class ArticleDTO { private String content; - private String userName; + private String authorName; - private int age; + private int authorAge; private Date birthday; @@ -50,20 +50,21 @@ public class ArticleDTO { this.content = content; } - public String getUserName() { - return userName; + + public String getAuthorName() { + return authorName; } - public void setUserName(String userName) { - this.userName = userName; + public void setAuthorName(String authorName) { + this.authorName = authorName; } - public int getAge() { - return age; + public int getAuthorAge() { + return authorAge; } - public void setAge(int age) { - this.age = age; + public void setAuthorAge(int authorAge) { + this.authorAge = authorAge; } public Date getBirthday() { @@ -81,8 +82,8 @@ public class ArticleDTO { ", accountId=" + accountId + ", title='" + title + '\'' + ", content='" + content + '\'' + - ", userName='" + userName + '\'' + - ", age=" + age + + ", authorName='" + authorName + '\'' + + ", authorAge=" + authorAge + ", birthday=" + birthday + '}'; } diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java index 0540a481..3592a9ec 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java @@ -85,7 +85,10 @@ public class EntityTestStarter { // QueryWrapper asWrapper = QueryWrapper.create() .select(ARTICLE.ALL_COLUMNS) - .select(ACCOUNT.USER_NAME,ACCOUNT.AGE,ACCOUNT.BIRTHDAY) + .select(ACCOUNT.USER_NAME.as(ArticleDTO::getAuthorName) + ,ACCOUNT.AGE.as(ArticleDTO::getAuthorAge) + ,ACCOUNT.BIRTHDAY + ) .from(ARTICLE) .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID)) .where(ACCOUNT.ID.ge(0));