From c1c93487d48dd1da3322c65776c8e6eac35c0735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=B5=B7=E5=93=A5?= Date: Mon, 15 May 2023 12:54:44 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0=20selectOneByQu?= =?UTF-8?q?eryAs=20=E7=AD=89=E6=96=B9=E6=B3=95=EF=BC=8C=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E5=9C=A8=20left=20join=20=E7=AD=89=E5=9C=BA=E6=99=AF=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E8=BD=AC=E6=8D=A2=E4=B8=BA=20dto=20vo=20=E7=AD=89;=20?= =?UTF-8?q?close=20#I72XOK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mybatisflex/core/BaseMapper.java | 64 ++++++++++++- .../java/com/mybatisflex/core/FlexConsts.java | 1 + .../core/mybatis/FlexConfiguration.java | 19 +++- .../core/mybatis/MappedStatementTypes.java | 34 +++++++ .../core/mybatis/MapperInvocationHandler.java | 8 ++ .../core/table/TableInfoFactory.java | 1 - .../java/com/mybatisflex/test/ArticleDTO.java | 90 +++++++++++++++++++ .../mybatisflex/test/EntityTestStarter.java | 11 +++ 8 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MappedStatementTypes.java create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java index d86cd846..bc6b3480 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java @@ -323,6 +323,19 @@ public interface BaseMapper { return (entities == null || entities.isEmpty()) ? null : entities.get(0); } + + /** + * 根据 queryWrapper 构建的条件来查询 1 条数据 + * + * @param queryWrapper query 条件 + * @param asType 接收类型 + * @return 数据内容 + */ + default R selectOneByQueryAs(QueryWrapper queryWrapper, Class asType) { + List entities = selectListByQueryAs(queryWrapper.limit(1), asType); + return (entities == null || entities.isEmpty()) ? null : entities.get(0); + } + /** * 根据多个主键来查询多条数据 * @@ -390,6 +403,17 @@ public interface BaseMapper { List selectListByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper); + /** + * 根据 query 来构建条件查询数据列表,要求返回的数据为 asType + * 这种场景一般用在 left join 时,有多出了 entity 本身的字段内容,可以转换为 dto、vo 等场景时 + * + * @param queryWrapper 查询条件 + * @param asType 接收数据类型 + * @return 数据列表 + */ + @SelectProvider(type = EntitySqlProvider.class, method = "selectListByQuery") + List selectListByQueryAs(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper, Class asType); + /** * 查询全部数据 * @@ -545,10 +569,44 @@ public interface BaseMapper { * @return page 数据 */ default Page paginate(Page page, QueryWrapper queryWrapper) { - List groupByColumns = CPI.getGroupByColumns(queryWrapper); List selectColumns = CPI.getSelectColumns(queryWrapper); + // 只有 totalRow 小于 0 的时候才会去查询总量 + // 这样方便用户做总数缓存,而非每次都要去查询总量 + // 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的 + if (page.getTotalRow() < 0) { + + //清除group by 去查询数据 + CPI.setGroupByColumns(queryWrapper, null); + CPI.setSelectColumns(queryWrapper, Arrays.asList(count())); + + long count = selectCountByQuery(queryWrapper); + page.setTotalRow(count); + } + + if (page.getTotalRow() == 0 || page.getPageNumber() > page.getTotalPage()) { + return page; + } + + + //恢复数量查询清除的 groupBy + CPI.setGroupByColumns(queryWrapper, groupByColumns); + + //重置 selectColumns + CPI.setSelectColumns(queryWrapper, selectColumns); + + int offset = page.getPageSize() * (page.getPageNumber() - 1); + queryWrapper.limit(offset, page.getPageSize()); + List rows = selectListByQuery(queryWrapper); + page.setRecords(rows); + return page; + } + + + default Page paginateAs(Page page, QueryWrapper queryWrapper, Class asType) { + List groupByColumns = CPI.getGroupByColumns(queryWrapper); + List selectColumns = CPI.getSelectColumns(queryWrapper); // 只有 totalRow 小于 0 的时候才会去查询总量 // 这样方便用户做总数缓存,而非每次都要去查询总量 @@ -575,8 +633,8 @@ public interface BaseMapper { int offset = page.getPageSize() * (page.getPageNumber() - 1); queryWrapper.limit(offset, page.getPageSize()); - List rows = selectListByQuery(queryWrapper); - page.setRecords(rows); + List records = selectListByQueryAs(queryWrapper, asType); + page.setRecords(records); return page; } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java index 364235d8..25b65c45 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java @@ -39,6 +39,7 @@ public class FlexConsts { public static final String IGNORE_NULLS = "$$ignoreNulls"; public static final String METHOD_INSERT_BATCH = "insertBatch"; + public static final String METHOD_SELECT_LIST_BY_QUERY_AS = "selectListByQueryAs"; /** * 当 entity 使用逻辑删除时,0 为 entity 的正常状态 diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java index 822b1e3d..659eec6b 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java @@ -126,6 +126,20 @@ public class FlexConfiguration extends Configuration { } + @Override + public MappedStatement getMappedStatement(String id) { + MappedStatement ms = super.getMappedStatement(id); + + //动态 resultsMap + if (id.endsWith(FlexConsts.METHOD_SELECT_LIST_BY_QUERY_AS)) { + Class asType = MappedStatementTypes.getCurrentType(); + ms = replaceResultMap(ms, TableInfoFactory.ofEntityClass(asType)); + } + + return ms; + } + + @Override public void addMappedStatement(MappedStatement ms) { //替换 RowMapper.insert 的主键生成器 @@ -141,7 +155,7 @@ public class FlexConfiguration extends Configuration { //entity select else if (StringUtil.endsWithAny(ms.getId(), "selectOneById", "selectListByIds" , "selectListByQuery")) { - ms = replaceResultMap(ms); + ms = replaceResultMap(ms, getTableInfo(ms)); } super.addMappedStatement(ms); @@ -151,9 +165,8 @@ public class FlexConfiguration extends Configuration { /** * 替换 entity 查询的 ResultMap */ - private MappedStatement replaceResultMap(MappedStatement ms) { + private MappedStatement replaceResultMap(MappedStatement ms, TableInfo tableInfo) { - TableInfo tableInfo = getTableInfo(ms); if (tableInfo == null) { return ms; } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MappedStatementTypes.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MappedStatementTypes.java new file mode 100644 index 00000000..f3383262 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MappedStatementTypes.java @@ -0,0 +1,34 @@ +/** + * 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.mybatis; + +public class MappedStatementTypes { + + private static ThreadLocal> currentTypeTL = new ThreadLocal<>(); + + static void setCurrentType(Class type){ + currentTypeTL.set(type); + } + + static Class getCurrentType(){ + return currentTypeTL.get(); + } + + static void clear(){ + currentTypeTL.remove(); + } + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java index cc9028cf..5a3d2e77 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java @@ -16,6 +16,7 @@ package com.mybatisflex.core.mybatis; import com.mybatisflex.annotation.UseDataSource; +import com.mybatisflex.core.FlexConsts; import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.datasource.FlexDataSource; @@ -45,7 +46,11 @@ public class MapperInvocationHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { boolean clearDsKey = false; boolean clearDbType = false; + boolean isSelectListByQueryAsMethod = FlexConsts.METHOD_SELECT_LIST_BY_QUERY_AS.equals(method.getName()); try { + if (isSelectListByQueryAsMethod){ + MappedStatementTypes.setCurrentType((Class) args[1]); + } //获取用户动态指定,由用户指定数据源,则应该有用户清除 String dataSourceKey = DataSourceKey.get(); @@ -73,6 +78,9 @@ public class MapperInvocationHandler implements InvocationHandler { } return method.invoke(mapper, args); } finally { + if (isSelectListByQueryAsMethod){ + MappedStatementTypes.clear(); + } if (clearDbType) { DialectFactory.clearHintDbType(); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java index 8b25820e..b71a55b3 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java @@ -117,7 +117,6 @@ public class TableInfoFactory { tableInfo.setEntityClass(entityClass); tableInfo.setReflector(new Reflector(entityClass)); - //初始化表名 Table table = entityClass.getAnnotation(Table.class); if (table != null) { 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 new file mode 100644 index 00000000..8e9f93db --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleDTO.java @@ -0,0 +1,90 @@ +package com.mybatisflex.test; + +import java.util.Date; + +public class ArticleDTO { + + private Long id; + + private Long accountId; + + private String title; + + private String content; + + + private String userName; + + private int age; + + private Date birthday; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + @Override + public String toString() { + return "ArticleDTO{" + + "id=" + id + + ", accountId=" + accountId + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", userName='" + userName + '\'' + + ", age=" + age + + ", 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 d75b0729..8b1dfa7c 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 @@ -28,6 +28,7 @@ import javax.sql.DataSource; import java.util.List; import static com.mybatisflex.test.table.Tables.ACCOUNT; +import static com.mybatisflex.test.table.Tables.ARTICLE; public class EntityTestStarter { @@ -81,6 +82,16 @@ public class EntityTestStarter { Object object = accountMapper.selectObjectByQuery(wrapper2); System.out.println(object); + QueryWrapper asWrapper = QueryWrapper.create() + .select(ARTICLE.ALL_COLUMNS) + .select(ACCOUNT.USER_NAME,ACCOUNT.AGE,ACCOUNT.BIRTHDAY) + .from(ARTICLE) + .leftJoin(ACCOUNT).on(ARTICLE.ACCOUNT_ID.eq(ACCOUNT.ID)) + .where(ACCOUNT.ID.ge(0)); + + List articleDTOS = accountMapper.selectListByQueryAs(asWrapper, ArticleDTO.class); + System.out.println(articleDTOS); + // QueryWrapper queryWrapper = new QueryWrapper(); // queryWrapper.where(ACCOUNT.ID.in(