add join as(lambdaGetter)support

This commit is contained in:
开源海哥 2023-05-19 19:20:19 +08:00
parent 7f8fbc4ef4
commit e0e5cebebb
7 changed files with 139 additions and 13 deletions

View File

@ -80,6 +80,38 @@ List<ArticleDTO> 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`

View File

@ -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 <T> QueryColumn as(LambdaGetter<T> fn) {
return as(LambdaUtil.getFieldName(fn));
}
public QueryColumn as(String alias) {
SqlUtil.keepColumnSafely(alias);
QueryColumn newColumn = new QueryColumn();

View File

@ -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) {

View File

@ -0,0 +1,24 @@
/**
* 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.util;
import java.io.Serializable;
@FunctionalInterface
public interface LambdaGetter<T> extends Serializable {
Object get(T source);
}

View File

@ -0,0 +1,50 @@
/**
* 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.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<Class<?>, SerializedLambda> lambdaMap = new ConcurrentHashMap<>();
public static <T> String getFieldName(LambdaGetter<T> 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);
}
});
}
}

View File

@ -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 +
'}';
}

View File

@ -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));