diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/WrapperUtils.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/WrapperUtils.java new file mode 100644 index 0000000..3416ab5 --- /dev/null +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/toolkit/WrapperUtils.java @@ -0,0 +1,114 @@ +package com.github.yulichang.toolkit; + +import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.adapter.AdapterHelper; +import com.github.yulichang.toolkit.sql.SqlScriptUtils; +import com.github.yulichang.wrapper.MPJLambdaWrapper; + +import java.util.Objects; +import java.util.Optional; + +/** + * @author yulichang + * @since 1.4.5 + */ +public class WrapperUtils { + + public static String buildSqlByWrapper(Class clazz, MPJLambdaWrapper wrapper, SFunction alias) { + TableInfo tableInfo = TableHelper.get(clazz); + Asserts.hasTable(tableInfo, clazz); + String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY); + boolean hasWhere = false; + String entityWhere = getEntitySql(tableInfo, wrapper); + if (StringUtils.isNotBlank(entityWhere)) { + hasWhere = true; + } + String mainLogic = mainLogic(hasWhere, clazz, wrapper); + if (StringUtils.isNotBlank(mainLogic)) { + hasWhere = true; + } + String subLogic = subLogic(hasWhere, wrapper); + if (StringUtils.isNotBlank(subLogic)) { + hasWhere = true; + } + String sqlSegment = (wrapper.getSqlSegment() != null && StringUtils.isNotBlank(wrapper.getSqlSegment())) ? + ((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY; + + String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY); + return String.format("(%s SELECT %s FROM %s %s %s %s %s %s %s) AS %s", + first, + wrapper.getSqlSelect(), + tableInfo.getTableName(), + wrapper.getAlias(), + wrapper.getFrom(), + mainLogic, + subLogic, + sqlSegment, + sqlComment, + LambdaUtils.getName(alias)); + } + + private static String formatParam(MPJLambdaWrapper wrapper, Object param) { + final String genParamName = Constants.WRAPPER_PARAM + wrapper.getParamNameSeq().incrementAndGet(); + final String paramStr = wrapper.getParamAlias() + ".paramNameValuePairs." + genParamName; + wrapper.getParamNameValuePairs().put(genParamName, param); + return SqlScriptUtils.safeParam(paramStr, null); + } + + private static String getEntitySql(TableInfo tableInfo, MPJLambdaWrapper wrapper) { + T obj = wrapper.getEntity(); + if (Objects.isNull(obj)) { + return StringPool.EMPTY; + } + StringBuilder sb = new StringBuilder(StringPool.EMPTY); + for (TableFieldInfo fieldInfo : tableInfo.getFieldList()) { + if (AdapterHelper.getTableInfoAdapter().mpjHasLogic(tableInfo) && fieldInfo.isLogicDelete()) { + continue; + } + Object val; + try { + val = fieldInfo.getField().get(obj); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + if (Objects.isNull(val)) { + continue; + } + sb.append(" AND ").append(wrapper.getTableList().getPrefixByClass(obj.getClass())).append(Constants.DOT) + .append(fieldInfo.getColumn()).append(Constants.EQUALS).append(formatParam(wrapper, val)); + } + //条件不为空 加上 where + if (sb.length() > 0) { + sb.delete(0, 4); + sb.insert(0, " WHERE "); + } + return sb.toString(); + } + + private static String mainLogic(boolean hasWhere, Class clazz, MPJLambdaWrapper wrapper) { + String info = LogicInfoUtils.getLogicInfo(null, clazz, true, wrapper.getAlias()); + if (StringUtils.isNotBlank(info)) { + if (hasWhere) { + return " AND " + info; + } + return " WHERE " + info.substring(4); + } + return StringPool.EMPTY; + } + + private static String subLogic(boolean hasWhere, MPJLambdaWrapper wrapper) { + String sql = wrapper.getSubLogicSql(); + if (StringUtils.isNotBlank(sql)) { + if (hasWhere) { + return sql; + } + return " WHERE " + sql.substring(4); + } + return StringPool.EMPTY; + } +} diff --git a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java index 83338e6..1645e9c 100644 --- a/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java +++ b/mybatis-plus-join-core/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java @@ -43,6 +43,10 @@ public abstract class MPJAbstractLambdaWrapper paramNameValuePairs; /** @@ -103,6 +104,7 @@ public abstract class MPJAbstractWrapper extends MPJAbstractLambdaWrapper MPJLambdaWrapper selectSub(Class clazz, Consumer> consumer, SFunction alias) { + MPJLambdaWrapper wrapper = new MPJLambdaWrapper(null, clazz, SharedString.emptyString(), paramNameSeq, paramNameValuePairs, + new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), + new TableList(), null, null, null, null) { + }; + String st = "st"; + wrapper.tableList.setAlias(st); + wrapper.alias = st; + wrapper.subTableAlias = st; + consumer.accept(wrapper); + String sql = WrapperUtils.buildSqlByWrapper(clazz, wrapper, alias); + this.selectColumns.add(new SelectString(sql, hasAlias, this.alias)); + return typedThis; + } + /** * 查询条件 SQL 片段 */ diff --git a/mybatis-plus-join-test/test-join/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java b/mybatis-plus-join-test/test-join/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java index 4bee13e..1d24c78 100644 --- a/mybatis-plus-join-test/test-join/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java +++ b/mybatis-plus-join-test/test-join/src/test/java/com/github/yulichang/test/join/LambdaWrapperTest.java @@ -1011,4 +1011,20 @@ class LambdaWrapperTest { //忽略异常 h2不支持连表删除 } } + + /** + * select 子查询 + */ + @Test + void sub() { + ThreadLocalUtils.set("SELECT ( SELECT st.id FROM `user` st WHERE st.del=false AND (st.id <= ?) limit 1 ) AS pid FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del=false AND t1.del=false AND (t.id <= ?)"); + MPJLambdaWrapper wrapper = JoinWrappers.lambda(UserDO.class) + .selectSub(UserDO.class, w -> w.select(UserDO::getId) + .le(UserDO::getId,1000) + .last("limit 1"), UserDO::getPid) + .leftJoin(AddressDO.class,AddressDO::getUserId,UserDO::getId) + .le(UserDO::getId,100); + wrapper.list(); + System.out.println(1); + } }