优化wrapper

This commit is contained in:
yulichang 2023-05-05 18:04:05 +08:00
parent 90941058ce
commit ed3c33db42
28 changed files with 1464 additions and 299 deletions

View File

@ -62,7 +62,6 @@ public class UserDO {
```java
/**
* 一对一,一对多关系映射查询
* 映射只对以Deep结尾有效比如 getByIdDeep listByIdsDeep 等
* 如果不需要关系映射就使用mybatis plus原生方法即可比如 getById listByIds 等
*
* 注意关系映射不会去关联查询而是执行多次单表查询对结果汇总后使用in语句查询,再对结果进行匹配)
@ -80,14 +79,15 @@ class MappingTest {
@Test
void test2() {
List<UserDO> list = userMapper.selectListDeep(Wrappers.emptyWrapper());
List<UserDO> list = userMapper.selectRelation(mapper -> mapper.selectList(Wrappers.emptyWrapper()));
list.forEach(System.out::println);
}
@Test
void test3() {
Page<UserDO> page = userMapper.selectPageDeep(new Page<>(2, 2), Wrappers.emptyWrapper());
page.getRecords().forEach(System.out::println);
Page<UserDO> page = new Page<>(2, 2);
Page<UserDO> result = userMapper.selectRelation(mapper -> mapper.selectPage(page, Wrappers.emptyWrapper()));
result.getRecords().forEach(System.out::println);
}
/**

View File

@ -2,9 +2,12 @@ package com.github.yulichang.base.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.github.yulichang.interfaces.MPJBaseJoin;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.UpdateJoinWrapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -16,6 +19,29 @@ import java.util.Map;
*/
public interface MPJJoinMapper<T> extends BaseMapper<T> {
/**
* 根据 Wrapper 条件连表删除
*
* @param wrapper joinWrapper
*/
int deleteJoin(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
/**
* 根据 whereEntity 条件更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param wrapper 实体对象封装操作类可以为 null,里面的 entity 用于生成 where 语句
*/
int updateJoin(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
/**
* 根据 whereEntity 条件更新记录 (null字段也会更新 !!!)
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param wrapper 实体对象封装操作类可以为 null,里面的 entity 用于生成 where 语句
*/
int updateJoinAndNull(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
/**
* 根据 Wrapper 条件查询总记录数
*

View File

@ -9,7 +9,9 @@ import com.baomidou.mybatisplus.core.injector.methods.*;
import com.baomidou.mybatisplus.core.mapper.Mapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.github.yulichang.adapter.v3431.AbstractMethodV3431;
import com.github.yulichang.mapper.MPJTableMapperHelper;
import com.github.yulichang.method.*;
@ -59,10 +61,10 @@ public class MPJSqlInjector extends DefaultSqlInjector {
* 升级到 mybatis plus 3.4.3.2 后对之前的版本兼容
*/
@Deprecated
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "DeprecatedIsStillUsed"})
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
if (VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.4.3.2") >= 0) {
logger.error(() -> "DefaultSqlInjector 的 getMethodList(Class<?> mapperClass) 方法已在 3.4.3.2+ 改为" +
throw ExceptionUtils.mpe("DefaultSqlInjector 的 getMethodList(Class<?> mapperClass) 方法已在 3.4.3.2+ 改为" +
"getMethodList(Class<?> mapperClass, TableInfo tableInfo)\n");
}
if (Objects.nonNull(sqlInjector)) {
@ -119,6 +121,8 @@ public class MPJSqlInjector extends DefaultSqlInjector {
List<AbstractMethod> list = new ArrayList<>();
if (VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.5.0") >= 0) {
list.add(new DeleteJoin(SqlMethod.DELETE_JOIN.getMethod()));
list.add(new UpdateJoin(SqlMethod.UPDATE_JOIN.getMethod()));
list.add(new UpdateJoinAndNull(SqlMethod.UPDATE_JOIN_AND_NULL.getMethod()));
list.add(new SelectJoinCount(SqlMethod.SELECT_JOIN_COUNT.getMethod()));
list.add(new SelectJoinOne(SqlMethod.SELECT_JOIN_ONE.getMethod()));
list.add(new SelectJoinList(SqlMethod.SELECT_JOIN_LIST.getMethod()));
@ -128,6 +132,8 @@ public class MPJSqlInjector extends DefaultSqlInjector {
list.add(new SelectJoinMapsPage(SqlMethod.SELECT_JOIN_MAPS_PAGE.getMethod()));
} else {
list.add(new DeleteJoin());
list.add(new UpdateJoin());
list.add(new UpdateJoinAndNull());
list.add(new SelectJoinCount());
list.add(new SelectJoinOne());
list.add(new SelectJoinList());

View File

@ -1,8 +1,18 @@
package com.github.yulichang.interfaces;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
/**
* @author yulichang
*/
@SuppressWarnings("unused")
public interface MPJBaseJoin<T> {
default String getDeleteSql() {
return StringPool.EMPTY;
}
default String getDeleteLogicSql() {
return StringPool.EMPTY;
}
}

View File

@ -0,0 +1,53 @@
package com.github.yulichang.method;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.github.yulichang.adapter.AdapterHelper;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* copy {@link com.baomidou.mybatisplus.core.injector.methods.Delete}
*
* @author yulichang
*/
public class DeleteJoin extends MPJAbstractMethod {
@SuppressWarnings("deprecation")
public DeleteJoin() {
super();
}
@SuppressWarnings("unused")
public DeleteJoin(String name) {
super(name);
}
@Override
@SuppressWarnings("DuplicatedCode")
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_JOIN;
if (AdapterHelper.getTableInfoAdapter().mpjHasLogic(tableInfo)) {
String sql = String.format(sqlMethod.getSql(), sqlFirst(), mpjTableName(tableInfo), sqlAlias(), sqlFrom(),
mpjDeleteLogic(tableInfo), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
} else {
sqlMethod = SqlMethod.DELETE_JOIN;
String sql = String.format(sqlMethod.getSql(), sqlFirst(), mpjDelete(), mpjTableName(tableInfo),
sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
}
}
private String mpjDelete() {
return SqlScriptUtils.convertChoose(String.format("%s == null or %s.deleteSql == ''", Constants.WRAPPER, Constants.WRAPPER),
"${ew.alias}", "${ew.deleteSql}");
}
private String mpjDeleteLogic(TableInfo tableInfo) {
return "SET ${ew.alias}." + tableInfo.getLogicDeleteSql(false, false) + " ${ew.deleteLogicSql}";
}
}

View File

@ -9,6 +9,7 @@ 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.sql.SqlScriptUtils;
import com.github.yulichang.adapter.AdapterHelper;
import com.github.yulichang.annotation.DynamicTableName;
import com.github.yulichang.config.ConfigProperties;
import com.github.yulichang.toolkit.VersionUtils;
@ -200,4 +201,84 @@ public interface MPJBaseMethod extends Constants {
boolean en = tableName.equals(encode);
return String.format("${ew.getTableName%s(\"%s\")}", en ? "" : "Enc", en ? tableName : encode);
}
default String mpjSqlSet(boolean logic, boolean ew, TableInfo table, boolean judgeAliasNull, String alias, String prefix) {
String sqlScript = mpjGetAllSqlSet(table, logic, prefix);
if (judgeAliasNull) {
sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", alias), true);
}
if (ew) {
sqlScript += NEWLINE;
sqlScript += mpjConvertIfEwParam(U_WRAPPER_SQL_SET, false);
}
sqlScript = SqlScriptUtils.convertSet(sqlScript);
return sqlScript;
}
default String mpjConvertIfEwParam(final String param, final boolean newLine) {
return StringPool.EMPTY;
}
/**
* 获取所有的 sql set 片段
*
* @param ignoreLogicDelFiled 是否过滤掉逻辑删除字段
* @param prefix 前缀
* @return sql 脚本片段
*/
default String mpjGetAllSqlSet(TableInfo tableInfo, boolean ignoreLogicDelFiled, final String prefix) {
final String newPrefix = prefix == null ? EMPTY : prefix;
return tableInfo.getFieldList().stream()
.filter(i -> {
if (ignoreLogicDelFiled) {
return !(AdapterHelper.getTableInfoAdapter().mpjHasLogic(tableInfo) && i.isLogicDelete());
}
return true;
}).map(i -> mpjGetSqlSet(i, newPrefix)).filter(Objects::nonNull).collect(joining(NEWLINE));
}
/**
* 获取 set sql 片段
*
* @param prefix 前缀
* @return sql 脚本片段
*/
default String mpjGetSqlSet(TableFieldInfo tableFieldInfo, final String prefix) {
return mpjGetSqlSet(tableFieldInfo, false, prefix);
}
/**
* 获取 set sql 片段
*
* @param ignoreIf 忽略 IF 包裹
* @param prefix 前缀
* @return sql 脚本片段
*/
default String mpjGetSqlSet(TableFieldInfo tableFieldInfo, final boolean ignoreIf, final String prefix) {
final String newPrefix = prefix == null ? EMPTY : prefix;
// 默认: column=
String sqlSet = "${ew.alias}." + tableFieldInfo.getColumn() + EQUALS;
if (StringUtils.isNotBlank(tableFieldInfo.getUpdate())) {
sqlSet += String.format(tableFieldInfo.getUpdate(), tableFieldInfo.getColumn());
} else {
sqlSet += SqlScriptUtils.safeParam(newPrefix + tableFieldInfo.getEl());
}
sqlSet += COMMA;
if (ignoreIf) {
return sqlSet;
}
if (tableFieldInfo.isWithUpdateFill()) {
// 不进行 if 包裹
return sqlSet;
}
return mpjConvertIf(tableFieldInfo, sqlSet, mpjConvertIfProperty(newPrefix, tableFieldInfo.getProperty()), tableFieldInfo.getUpdateStrategy());
}
default String mpjConvertIfProperty(String prefix, String property) {
return StringUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
}
default String mpjConvertIf(TableFieldInfo tableFieldInfo, final String sqlScript, final String property, final FieldStrategy fieldStrategy) {
return StringPool.EMPTY;
}
}

View File

@ -32,8 +32,29 @@ public enum SqlMethod {
"<script>\n%s SELECT %s %s FROM %s %s %s %s %s %s\n</script>"),
SELECT_JOIN_MAPS_PAGE("selectJoinMapsPage", "返回Map集合并分页",
"<script>\n%s SELECT %s %s FROM %s %s %s %s %s %s\n</script>");
"<script>\n%s SELECT %s %s FROM %s %s %s %s %s %s\n</script>"),
/**
* 连表删除
*/
DELETE_JOIN("deleteJoin", "连表删除",
"<script>\n%s DELETE %s FROM %s %s %s %s %s\n</script>"),
/**
* 连表逻辑删除
*/
LOGIC_DELETE_JOIN("deleteJoin", "连表逻辑删除", "<script>\n%s UPDATE %s %s %s %s %s %s\n</script>"),
/**
* 连表更新
*/
UPDATE_JOIN("updateJoin", "连表更新", "<script>\n%s UPDATE %s %s %s %s %s %s\n</script>"),
/**
* 连表逻辑更新 (会更新null字段)
*/
UPDATE_JOIN_AND_NULL("updateJoinAndNull", "连表更新", "<script>\n%s UPDATE %s %s %s %s %s %s\n</script>"),
;
private final String method;
private final String sql;

View File

@ -0,0 +1,66 @@
package com.github.yulichang.method;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.github.yulichang.adapter.AdapterHelper;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* copy {@link com.baomidou.mybatisplus.core.injector.methods.Update}
*
* @author yulichang
*/
public class UpdateJoin extends MPJAbstractMethod {
@SuppressWarnings("deprecation")
public UpdateJoin() {
super();
}
@SuppressWarnings("unused")
public UpdateJoin(String name) {
super(name);
}
@Override
@SuppressWarnings("DuplicatedCode")
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.UPDATE_JOIN;
String sql = String.format(sqlMethod.getSql(), sqlFirst(), mpjTableName(tableInfo), sqlAlias(), sqlFrom(),
mpjSqlSet(true, true, tableInfo, true, ENTITY, ENTITY_DOT), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}
@Override
public String mpjConvertIfEwParam(String param, boolean newLine) {
return super.convertIfEwParam(param, newLine);
}
/**
* 转换成 if 标签的脚本片段
*
* @param sqlScript sql 脚本片段
* @param property 字段名
* @param fieldStrategy 验证策略
* @return if 脚本片段
*/
@Override
public String mpjConvertIf(TableFieldInfo tableFieldInfo, final String sqlScript, final String property, final FieldStrategy fieldStrategy) {
if (fieldStrategy == FieldStrategy.NEVER) {
return null;
}
if (AdapterHelper.getTableInfoAdapter().mpjIsPrimitive(tableFieldInfo) || fieldStrategy == FieldStrategy.IGNORED) {
return sqlScript;
}
if (fieldStrategy == FieldStrategy.NOT_EMPTY && tableFieldInfo.isCharSequence()) {
return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null and %s != ''", property, property),
false);
}
return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", property), false);
}
}

View File

@ -0,0 +1,56 @@
package com.github.yulichang.method;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
/**
* copy {@link com.baomidou.mybatisplus.core.injector.methods.Update}
*
* @author yulichang
*/
public class UpdateJoinAndNull extends MPJAbstractMethod {
@SuppressWarnings("deprecation")
public UpdateJoinAndNull() {
super();
}
@SuppressWarnings("unused")
public UpdateJoinAndNull(String name) {
super(name);
}
@Override
@SuppressWarnings("DuplicatedCode")
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.UPDATE_JOIN_AND_NULL;
String sql = String.format(sqlMethod.getSql(), sqlFirst(), mpjTableName(tableInfo), sqlAlias(), sqlFrom(),
mpjSqlSet(true, true, tableInfo, true, ENTITY, ENTITY_DOT), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}
@Override
public String mpjConvertIfEwParam(String param, boolean newLine) {
return super.convertIfEwParam(param, newLine);
}
/**
* 转换成 if 标签的脚本片段
*
* @param sqlScript sql 脚本片段
* @param property 字段名
* @param fieldStrategy 验证策略
* @return if 脚本片段
*/
@Override
public String mpjConvertIf(TableFieldInfo tableFieldInfo, final String sqlScript, final String property, final FieldStrategy fieldStrategy) {
if (fieldStrategy == FieldStrategy.NEVER) {
return null;
}
return sqlScript;
}
}

View File

@ -1,7 +1,9 @@
package com.github.yulichang.toolkit;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.UpdateJoinWrapper;
/**
* @author yulichang
@ -56,7 +58,7 @@ public class JoinWrappers {
* JoinWrappers.lambda("t", User.class)
*/
public static <T> MPJLambdaWrapper<T> lambda(String alias, Class<T> clazz) {
return new MPJLambdaWrapper<T>(alias).setEntityClass(clazz);
return new MPJLambdaWrapper<T>(clazz, alias);
}
/**
@ -70,6 +72,27 @@ public class JoinWrappers {
* JoinWrappers.lambda("t", user)
*/
public static <T> MPJLambdaWrapper<T> lambda(String alias, T entity) {
return new MPJLambdaWrapper<T>(alias).setEntity(entity);
return new MPJLambdaWrapper<T>(entity, alias);
}
/**
* JoinWrappers.delete(User.class)
*/
public static <T> DeleteJoinWrapper<T> delete(Class<T> clazz) {
return new DeleteJoinWrapper<>(clazz);
}
/**
* JoinWrappers.update(User.class)
*/
public static <T> UpdateJoinWrapper<T> update(Class<T> clazz) {
return new UpdateJoinWrapper<>(clazz);
}
/**
* JoinWrappers.update("t", User.class)
*/
public static <T> UpdateJoinWrapper<T> update(String alias, Class<T> clazz) {
return new UpdateJoinWrapper<>(clazz, alias);
}
}

View File

@ -22,13 +22,15 @@ public class LogicInfoUtils implements Constants {
private static final Map<Class<?>, Map<String, String>> LOGIC_CACHE_NO_AND = new ConcurrentHashMap<>();
private static final Map<Class<?>, Map<String, String>> LOGIC_CACHE_INVERT = new ConcurrentHashMap<>();
public static String getLogicInfo(Integer tableIndex, Class<?> clazz, boolean hasAlias, String alias) {
Map<String, String> absent = LOGIC_CACHE.get(clazz);
if (absent == null) {
absent = new ConcurrentHashMap<>();
LOGIC_CACHE.put(clazz, absent);
}
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, true));
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, true, false));
}
public static String getLogicInfoNoAnd(Integer tableIndex, Class<?> clazz, boolean hasAlias, String alias) {
@ -37,21 +39,31 @@ public class LogicInfoUtils implements Constants {
absent = new ConcurrentHashMap<>();
LOGIC_CACHE_NO_AND.put(clazz, absent);
}
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, false));
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, false, false));
}
private static String getLogicStr(String prefix, Class<?> clazz, boolean and) {
public static String getLogicInfoInvert(Integer tableIndex, Class<?> clazz, boolean hasAlias, String alias) {
Map<String, String> absent = LOGIC_CACHE_INVERT.get(clazz);
if (absent == null) {
absent = new ConcurrentHashMap<>();
LOGIC_CACHE_INVERT.put(clazz, absent);
}
return absent.computeIfAbsent(hasAlias ? alias : (alias + tableIndex), key -> getLogicStr(key, clazz, false, true));
}
private static String getLogicStr(String prefix, Class<?> clazz, boolean and, boolean invert) {
String logicStr;
TableInfo tableInfo = TableHelper.get(clazz);
Asserts.hasTable(tableInfo, clazz);
TableFieldInfo logicField = ConfigProperties.tableInfoAdapter.mpjGetLogicField(tableInfo);
if (ConfigProperties.tableInfoAdapter.mpjHasLogic(tableInfo) && Objects.nonNull(logicField)) {
final String value = logicField.getLogicNotDeleteValue();
if (NULL.equalsIgnoreCase(value)) {
logicStr = (and ? " AND " : EMPTY) + prefix + DOT + logicField.getColumn() + " IS NULL";
final String notDeleteValue = logicField.getLogicNotDeleteValue();
final String deleteValue = logicField.getLogicDeleteValue();
if (NULL.equalsIgnoreCase(notDeleteValue)) {
logicStr = (and ? " AND " : EMPTY) + prefix + DOT + logicField.getColumn() + (invert ? " IS NOT NULL" : " IS NULL");
} else {
logicStr = (and ? " AND " : EMPTY) + prefix + DOT + logicField.getColumn() + EQUALS + String.format(logicField.isCharSequence() ? "'%s'" : "%s", value);
logicStr = (and ? " AND " : EMPTY) + prefix + DOT + logicField.getColumn() + EQUALS +
String.format(logicField.isCharSequence() ? "'%s'" : "%s", invert ? deleteValue : notDeleteValue);
}
} else {
logicStr = StringPool.EMPTY;

View File

@ -1,5 +1,6 @@
package com.github.yulichang.toolkit;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.Data;
@ -155,11 +156,20 @@ public class TableList {
}
}
public String getPrefixByClassAssert(Class<?> clazz) {
if (Objects.equals(clazz, rootClass)) {
return alias;
}
Node node = getByClassFirst(clazz);
Assert.notNull(node, "sql 中无法找到 <%s> 类对应的表", clazz.getSimpleName());
return node.hasAlias ? node.getAlias() : (node.getAlias() + node.getIndex());
}
private Node getByIndex(int index) {
return all.stream().filter(i -> i.getIndex() == index).findFirst().orElse(null);
}
private Node getByClassFirst(Class<?> clazz) {
public Node getByClassFirst(Class<?> clazz) {
return all.stream().filter(i -> i.getClazz() == clazz).findFirst().orElse(null);
}
@ -167,6 +177,17 @@ public class TableList {
return all.stream().filter(i -> i.getClazz() == clazz).collect(Collectors.toList());
}
public boolean contain(Class<?> clazz) {
if (Objects.isNull(clazz)) {
return false;
}
if (rootClass != null && rootClass == clazz) {
return true;
}
return all.stream().anyMatch(i -> i.getClazz() == clazz);
}
public void clear() {
this.all.clear();
this.child.clear();

View File

@ -0,0 +1,234 @@
package com.github.yulichang.wrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.github.yulichang.adapter.AdapterHelper;
import com.github.yulichang.toolkit.Asserts;
import com.github.yulichang.toolkit.LogicInfoUtils;
import com.github.yulichang.toolkit.TableHelper;
import com.github.yulichang.toolkit.TableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author yulichang
* @since 1.4.5
*/
public class DeleteJoinWrapper<T> extends MPJAbstractLambdaWrapper<T, DeleteJoinWrapper<T>> {
/**
* 删除表
*/
private final SharedString deleteSql = new SharedString();
/**
* 删除的表
*/
private List<Class<?>> deleteTableList;
/**
* 删除的表
*/
private List<String> deleteTableName;
/**
* 是否删除主表以及所有副表
*/
private boolean deleteAll = false;
private DeleteJoinWrapper() {
super();
}
/**
* 推荐使用此构造方法
*/
public DeleteJoinWrapper(Class<T> clazz) {
super(clazz);
}
/**
* 构造方法
*
* @param clazz 主表class类
* @param alias 主表别名
*/
public DeleteJoinWrapper(Class<T> clazz, String alias) {
super(clazz, alias);
}
/**
* 获取删除的表
*/
@Override
@SuppressWarnings("UnusedReturnValue")
public String getDeleteSql() {
if (StringUtils.isNotBlank(this.deleteSql.getStringValue())) {
return this.deleteSql.getStringValue();
}
String delete = null;
if (deleteAll) {
List<String> tables = tableList.getAll().stream().map(i -> i.isHasAlias() ? i.getAlias() :
(i.getAlias() + i.getIndex())).collect(Collectors.toList());
tables.add(0, this.alias);
delete = String.join(StringPool.COMMA, tables);
} else {
if (CollectionUtils.isNotEmpty(deleteTableList)) {
delete = deleteTableList.stream().map(c -> tableList.getPrefixByClassAssert(c)).collect(Collectors.joining(StringPool.COMMA));
}
}
if (CollectionUtils.isNotEmpty(deleteTableName)) {
delete = delete + StringPool.COMMA + String.join(StringPool.COMMA, deleteTableName);
}
if (StringUtils.isBlank(delete)) {
delete = this.alias;
}
deleteSql.setStringValue(delete);
return delete;
}
/**
* 获取删除的表
*/
@Override
public String getDeleteLogicSql() {
if (StringUtils.isNotBlank(this.deleteSql.getStringValue())) {
return this.deleteSql.getStringValue();
}
String delete = null;
if (deleteAll) {
delete = tableList.getAll().stream().map(i -> LogicInfoUtils.getLogicInfoInvert(i.getIndex(), i.getClazz(),
i.isHasAlias(), i.getAlias())).collect(Collectors.joining(StringPool.COMMA));
} else {
if (CollectionUtils.isNotEmpty(deleteTableList)) {
delete = deleteTableList.stream().map(c -> tableList.getByClassFirst(c)).map(i ->
LogicInfoUtils.getLogicInfoInvert(i.getIndex(), i.getClazz(), i.isHasAlias(), i.getAlias()))
.collect(Collectors.joining(StringPool.COMMA));
}
}
if (CollectionUtils.isNotEmpty(deleteTableName)) {
delete = delete + StringPool.COMMA + String.join(StringPool.COMMA, deleteTableName);
}
if (StringUtils.isNotBlank(delete)) {
delete = StringPool.COMMA + delete;
}else {
delete = StringPool.EMPTY;
}
deleteSql.setStringValue(delete);
return delete;
}
/**
* 删除表
*/
public DeleteJoinWrapper<T> deleteAll() {
this.deleteAll = true;
return typedThis;
}
/**
* 删除表
*/
public DeleteJoinWrapper<T> delete(String... tables) {
if (CollectionUtils.isEmpty(deleteTableName)) {
deleteTableName = new ArrayList<>();
deleteTableName.addAll(Arrays.asList(tables));
}
return typedThis;
}
/**
* 删除表
*/
public DeleteJoinWrapper<T> delete(Class<?>... deleteClass) {
Class<T> entityClass = getEntityClass();
Assert.notNull(entityClass, "缺少主表类型, 请使用 new MPJLambdaWrapper<>(主表.class) 或 JoinWrappers.lambda(主表.class) 构造方法");
if (CollectionUtils.isEmpty(deleteTableList)) {
deleteTableList = new ArrayList<>();
}
TableInfo tableInfo = TableHelper.get(entityClass);
Asserts.hasTable(tableInfo, entityClass);
//检查
boolean mainLogic = AdapterHelper.getTableInfoAdapter().mpjHasLogic(tableInfo);
boolean check = Arrays.stream(deleteClass).allMatch(t -> {
TableInfo ti = TableHelper.get(t);
Asserts.hasTable(ti, t);
return mainLogic == AdapterHelper.getTableInfoAdapter().mpjHasLogic(ti);
});
if (!check) {
List<Class<?>> list = Arrays.stream(deleteClass).collect(Collectors.toList());
throw ExceptionUtils.mpe("连表删除只适用于全部表(主表和副表)都是物理删除或全部都是逻辑删除, " +
"不支持同时存在物理删除和逻辑删除 [物理删除->(%s)] [逻辑删除->(%s)]",
list.stream().filter(t -> !AdapterHelper.getTableInfoAdapter().mpjHasLogic(TableHelper.get(t)))
.map(Class::getSimpleName).collect(Collectors.joining(StringPool.COMMA)),
list.stream().filter(t -> AdapterHelper.getTableInfoAdapter().mpjHasLogic(TableHelper.get(t)))
.map(Class::getSimpleName).collect(Collectors.joining(StringPool.COMMA)));
}
deleteTableList.addAll(Arrays.asList(deleteClass));
return typedThis;
}
/**
* 用于生成嵌套 sql
* <p> sqlSelect 不向下传递</p>
*/
@Override
protected DeleteJoinWrapper<T> instance() {
return instance(index, null, null, null);
}
@Override
protected DeleteJoinWrapper<T> instanceEmpty() {
return new DeleteJoinWrapper<>();
}
@Override
protected DeleteJoinWrapper<T> instance(Integer index, String keyWord, Class<?> joinClass, String tableName) {
return new DeleteJoinWrapper<>(getEntity(), getEntityClass(), paramNameSeq, paramNameValuePairs,
new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
this.tableList, index, keyWord, joinClass, tableName);
}
/**
* 不建议直接 new 该实例使用 JoinWrappers.delete(User.class)
*/
public DeleteJoinWrapper(T entity, Class<T> entityClass, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
TableList tableList, Integer index, String keyWord, Class<?> joinClass, String tableName) {
super.setEntity(entity);
super.setEntityClass(entityClass);
this.paramNameSeq = paramNameSeq;
this.paramNameValuePairs = paramNameValuePairs;
this.expression = mergeSegments;
this.lastSql = lastSql;
this.sqlComment = sqlComment;
this.sqlFirst = sqlFirst;
this.tableList = tableList;
this.index = index;
this.keyWord = keyWord;
this.joinClass = joinClass;
this.tableName = tableName;
}
@Override
public void clear() {
super.clear();
if (CollectionUtils.isNotEmpty(deleteTableList)) {
deleteTableList.clear();
}
if (CollectionUtils.isNotEmpty(deleteTableName)) {
deleteTableName.clear();
}
this.deleteSql.toNull();
this.deleteAll = false;
}
}

View File

@ -10,11 +10,10 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.config.ConfigProperties;
import com.github.yulichang.config.enums.LogicDelTypeEnum;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.toolkit.TableHelper;
import com.github.yulichang.toolkit.TableList;
import com.github.yulichang.toolkit.*;
import com.github.yulichang.toolkit.support.ColumnCache;
import com.github.yulichang.wrapper.enums.PrefixEnum;
import com.github.yulichang.wrapper.interfaces.QueryJoin;
import com.github.yulichang.wrapper.segments.SelectCache;
import lombok.Getter;
@ -24,8 +23,11 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
import static java.util.stream.Collectors.joining;
/**
@ -35,7 +37,7 @@ import static java.util.stream.Collectors.joining;
*/
@SuppressWarnings({"DuplicatedCode", "unused"})
public abstract class MPJAbstractLambdaWrapper<T, Children extends MPJAbstractLambdaWrapper<T, Children>>
extends MPJAbstractWrapper<T, Children> {
extends MPJAbstractWrapper<T, Children> implements QueryJoin<Children, T> {
/**
* 主表别名
@ -66,6 +68,97 @@ public abstract class MPJAbstractLambdaWrapper<T, Children extends MPJAbstractLa
*/
protected LogicDelTypeEnum logicDelType = ConfigProperties.logicDelType;
/**
* 查询表
*/
protected final SharedString from = new SharedString();
/**
* 是否有表别名
*/
@Getter
protected boolean hasAlias;
/**
* 连表关键字 on 条件 func 使用
*/
@Getter
protected String keyWord;
/**
* 副表逻辑删除开关
*/
protected boolean subLogicSql = ConfigProperties.subTableLogic;
/**
* 主表逻辑删除开关
*/
protected boolean logicSql = true;
/**
* 推荐使用 class 的构造方法
*/
public MPJAbstractLambdaWrapper() {
initNeed();
}
/**
* 推荐使用此构造方法
*/
public MPJAbstractLambdaWrapper(Class<T> clazz) {
initNeed();
setEntityClass(clazz);
tableList.setRootClass(clazz);
}
/**
* 构造方法
*
* @param entity 主表实体
*/
public MPJAbstractLambdaWrapper(T entity) {
initNeed();
setEntity(entity);
if (entity != null) {
tableList.setRootClass(entity.getClass());
}
}
/**
* 自定义主表别名
*/
public MPJAbstractLambdaWrapper(String alias) {
this.alias = alias;
initNeed();
tableList.setAlias(alias);
}
/**
* 构造方法
*
* @param clazz 主表class类
* @param alias 主表别名
*/
public MPJAbstractLambdaWrapper(Class<T> clazz, String alias) {
this.alias = alias;
setEntityClass(clazz);
initNeed();
tableList.setAlias(alias);
tableList.setRootClass(clazz);
}
/**
* 构造方法
*
* @param entity 主表实体类
* @param alias 主表别名
*/
public MPJAbstractLambdaWrapper(T entity, String alias) {
this.alias = alias;
setEntity(entity);
initNeed();
tableList.setAlias(alias);
if (entity != null) {
tableList.setRootClass(entity.getClass());
}
}
/**
* 设置表别名
* 设置表别名注意sql注入问题
@ -163,6 +256,165 @@ public abstract class MPJAbstractLambdaWrapper<T, Children extends MPJAbstractLa
}
}
/**
* 关闭副表逻辑删除
* <p>
* 副表逻辑删除默认在where语句中
* 但有时候需要让它出现在on语句中, 这两种写法区别还是很大的
* 所以可以关闭副表逻辑删除, 通过on语句多条件, 自己实现on语句的逻辑删除
*/
public Children disableSubLogicDel() {
this.subLogicSql = false;
return typedThis;
}
public Children enableSubLogicDel() {
this.subLogicSql = true;
return typedThis;
}
/**
* 关闭主表逻辑删除
*/
public Children disableLogicDel() {
this.logicSql = false;
return typedThis;
}
public Children enableLogicDel() {
this.logicSql = true;
return typedThis;
}
/**
* 副表部分逻辑删除支持
*/
public String getSubLogicSql() {
if (subLogicSql && logicDelType == LogicDelTypeEnum.WHERE) {
if (tableList.getAll().isEmpty()) {
return StringPool.EMPTY;
}
return tableList.getAll().stream().map(t -> LogicInfoUtils.getLogicInfo(t.getIndex(),
t.getClazz(), t.isHasAlias(), t.getAlias())).collect(Collectors.joining(StringPool.SPACE));
}
return StringPool.EMPTY;
}
/**
* 主表部分逻辑删除支持
*/
public boolean getLogicSql() {
return this.logicSql;
}
/**
* 调整逻辑删除位置为ON语句
*/
public Children logicDelToOn() {
this.logicDelType = LogicDelTypeEnum.ON;
return typedThis;
}
/**
* 调整逻辑删除位置为WHERE语句
*/
public Children logicDelToWhere() {
this.logicDelType = LogicDelTypeEnum.WHERE;
return typedThis;
}
/**
* 获取连表部分语句
*/
public String getFrom() {
if (StringUtils.isBlank(from.getStringValue())) {
StringBuilder value = new StringBuilder();
for (Children wrapper : onWrappers) {
if (StringUtils.isBlank(wrapper.from.getStringValue())) {
if (wrapper.subLogicSql && this.logicDelType == LogicDelTypeEnum.ON) {
TableInfo tableInfo = TableHelper.get(wrapper.getJoinClass());
if (ConfigProperties.tableInfoAdapter.mpjHasLogic(tableInfo)) {
wrapper.appendSqlSegments(APPLY, () -> LogicInfoUtils.getLogicInfoNoAnd(
wrapper.getIndex(), wrapper.getJoinClass(), wrapper.isHasAlias(), wrapper.getAlias()
));
}
}
value.append(StringPool.SPACE)
.append(wrapper.getKeyWord())
.append(StringPool.SPACE)
.append(wrapper.getTableName())
.append(StringPool.SPACE)
.append(wrapper.hasAlias ? wrapper.alias : (wrapper.alias + wrapper.getIndex()))
.append(Constant.ON)
.append(wrapper.getExpression().getNormal().getSqlSegment());
} else {
value.append(StringPool.SPACE)
.append(wrapper.getKeyWord())
.append(StringPool.SPACE)
.append(wrapper.from.getStringValue())
.append(StringPool.SPACE);
}
}
from.setStringValue(value.toString());
}
return from.getStringValue();
}
public String getAlias() {
return alias;
}
/**
* 内部调用, 不建议使用
*/
@Override
public <R> Children join(String keyWord, Class<R> clazz, String tableAlias, BiConsumer<MPJAbstractLambdaWrapper<T, ?>, Children> consumer) {
Integer oldIndex = this.getIndex();
int newIndex = tableIndex;
TableInfo info = TableHelper.get(clazz);
Asserts.hasTable(info, clazz);
Children instance = instance(newIndex, keyWord, clazz, info.getTableName());
instance.isNo = true;
instance.isMain = false;
onWrappers.add(instance);
if (StringUtils.isBlank(tableAlias)) {
tableList.put(oldIndex, clazz, false, ConfigProperties.tableAlias, newIndex);
instance.alias = ConfigProperties.tableAlias;
instance.hasAlias = false;
} else {
tableList.put(oldIndex, clazz, true, tableAlias, newIndex);
instance.alias = tableAlias;
instance.hasAlias = true;
}
tableIndex++;
this.index = newIndex;
boolean isM = this.isMain;
this.isMain = false;
consumer.accept(instance, typedThis);
this.isMain = isM;
this.index = oldIndex;
return typedThis;
}
/**
* 自定义关键词连接
*
* @param keyWord 连表关键词
* @param condition 条件
* @param joinSql sql
*/
@Override
public Children join(String keyWord, boolean condition, String joinSql) {
if (condition) {
Children wrapper = instanceEmpty();
wrapper.from.setStringValue(joinSql);
wrapper.keyWord = keyWord;
onWrappers.add(wrapper);
}
return typedThis;
}
/**
* 是否使用默认注解 {@link OrderBy} 排序
*
@ -191,4 +443,20 @@ public abstract class MPJAbstractLambdaWrapper<T, Children extends MPJAbstractLa
tableList = new TableList();
tableList.setAlias(alias);
}
@Override
public void clear() {
super.clear();
this.alias = ConfigProperties.tableAlias;
this.resultMap = false;
this.tableIndex = 1;
this.dynamicTableName = false;
this.tableFunc = null;
this.logicDelType = ConfigProperties.logicDelType;
this.from.toNull();
this.hasAlias = false;
this.keyWord = null;
this.logicSql = true;
this.onWrappers.clear();
}
}

View File

@ -70,9 +70,8 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
/**
* ON sql wrapper集合
*/
protected final List<MPJLambdaWrapper<T>> onWrappers = new ArrayList<>();
protected final List<Children> onWrappers = new ArrayList<>();
/**
* ß
* 数据库表映射实体类
*/
private T entity;
@ -517,6 +516,10 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
*/
protected abstract Children instance();
protected abstract Children instanceEmpty();
protected abstract Children instance(Integer index, String keyWord, Class<?> joinClass, String tableName);
/**
* 格式化 sql
* <p>
@ -604,6 +607,12 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
lastSql.toEmpty();
sqlComment.toEmpty();
sqlFirst.toEmpty();
tableList.clear();
entityClass = null;
onWrappers.clear();
index = null;
isMain = true;
isNo = false;
}
/**
@ -978,6 +987,4 @@ public abstract class MPJAbstractWrapper<T, Children extends MPJAbstractWrapper<
return maybeDo(condition, () -> columns.forEach(c -> appendSqlSegments(ORDER_BY,
columnToSqlSegment(columnSqlInjectFilter(c)), isAsc ? ASC : DESC)));
}
}

View File

@ -14,7 +14,6 @@ import com.github.yulichang.toolkit.*;
import com.github.yulichang.toolkit.support.ColumnCache;
import com.github.yulichang.wrapper.interfaces.Chain;
import com.github.yulichang.wrapper.interfaces.Query;
import com.github.yulichang.wrapper.interfaces.QueryJoin;
import com.github.yulichang.wrapper.interfaces.QueryLabel;
import com.github.yulichang.wrapper.resultmap.Label;
import com.github.yulichang.wrapper.segments.Select;
@ -24,7 +23,6 @@ import lombok.Getter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
@ -37,12 +35,16 @@ import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
*/
@SuppressWarnings({"unused"})
public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWrapper<T>> implements
Query<MPJLambdaWrapper<T>>, QueryJoin<MPJLambdaWrapper<T>, T>, QueryLabel<MPJLambdaWrapper<T>>, Chain<T> {
Query<MPJLambdaWrapper<T>>, QueryLabel<MPJLambdaWrapper<T>>, Chain<T> {
/**
* 查询
* 查询字段 sql
*/
private final SharedString from = new SharedString();
private SharedString sqlSelect = new SharedString();
/**
* 是否 select distinct
*/
private boolean selectDistinct = false;
/**
* 查询的字段
*/
@ -53,47 +55,20 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
*/
@Getter
private final List<Label<?>> resultMapMybatisLabel = new ArrayList<>();
/**
* 是否有表别名
*/
@Getter
private boolean hasAlias;
/**
* 查询字段 sql
*/
private SharedString sqlSelect = new SharedString();
/**
* 是否 select distinct
*/
private boolean selectDistinct = false;
/**
* 连表关键字 on 条件 func 使用
*/
@Getter
private String keyWord;
/**
* 副表逻辑删除开关
*/
private boolean subLogicSql = ConfigProperties.subTableLogic;
/**
* 主表逻辑删除开关
*/
private boolean logicSql = true;
/**
* 推荐使用 class 的构造方法
*/
public MPJLambdaWrapper() {
super.initNeed();
super();
}
/**
* 推荐使用此构造方法
*/
public MPJLambdaWrapper(Class<T> clazz) {
super.initNeed();
setEntityClass(clazz);
tableList.setRootClass(clazz);
super(clazz);
}
/**
@ -102,20 +77,14 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
* @param entity 主表实体
*/
public MPJLambdaWrapper(T entity) {
super.initNeed();
setEntity(entity);
if (entity != null) {
tableList.setRootClass(entity.getClass());
}
super(entity);
}
/**
* 自定义主表别名
*/
public MPJLambdaWrapper(String alias) {
this.alias = alias;
super.initNeed();
tableList.setAlias(alias);
super(alias);
}
/**
@ -125,11 +94,7 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
* @param alias 主表别名
*/
public MPJLambdaWrapper(Class<T> clazz, String alias) {
this.alias = alias;
setEntityClass(clazz);
super.initNeed();
tableList.setAlias(alias);
tableList.setRootClass(clazz);
super(clazz, alias);
}
/**
@ -139,18 +104,11 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
* @param alias 主表别名
*/
public MPJLambdaWrapper(T entity, String alias) {
this.alias = alias;
setEntity(entity);
super.initNeed();
tableList.setAlias(alias);
if (entity != null) {
tableList.setRootClass(entity.getClass());
}
super(entity, alias);
}
/**
* 不建议直接 new 该实例使用 MPJWrappers.<UserDO>lambdaQuery()
* 不建议直接 new 该实例使用 JoinWrappers.lambda(UserDO.class)
*/
MPJLambdaWrapper(T entity, Class<T> entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,
@ -266,47 +224,6 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
return sqlSelect.getStringValue();
}
/**
* 获取连表部分语句
*/
public String getFrom() {
if (StringUtils.isBlank(from.getStringValue())) {
StringBuilder value = new StringBuilder();
for (MPJLambdaWrapper<?> wrapper : onWrappers) {
if (StringUtils.isBlank(wrapper.from.getStringValue())) {
if (wrapper.subLogicSql && this.logicDelType == LogicDelTypeEnum.ON) {
TableInfo tableInfo = TableHelper.get(wrapper.getJoinClass());
if (ConfigProperties.tableInfoAdapter.mpjHasLogic(tableInfo)) {
wrapper.appendSqlSegments(APPLY, () -> LogicInfoUtils.getLogicInfoNoAnd(
wrapper.getIndex(), wrapper.getJoinClass(), wrapper.isHasAlias(), wrapper.getAlias()
));
}
}
value.append(StringPool.SPACE)
.append(wrapper.getKeyWord())
.append(StringPool.SPACE)
.append(wrapper.getTableName())
.append(StringPool.SPACE)
.append(wrapper.hasAlias ? wrapper.alias : (wrapper.alias + wrapper.getIndex()))
.append(Constant.ON)
.append(wrapper.getExpression().getNormal().getSqlSegment());
} else {
value.append(StringPool.SPACE)
.append(wrapper.getKeyWord())
.append(StringPool.SPACE)
.append(wrapper.from.getStringValue())
.append(StringPool.SPACE);
}
}
from.setStringValue(value.toString());
}
return from.getStringValue();
}
public String getAlias() {
return alias;
}
public boolean getSelectDistinct() {
return selectDistinct;
@ -321,6 +238,12 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
return instance(index, null, null, null);
}
@Override
protected MPJLambdaWrapper<T> instanceEmpty() {
return new MPJLambdaWrapper<>();
}
@Override
protected MPJLambdaWrapper<T> instance(Integer index, String keyWord, Class<?> joinClass, String tableName) {
return new MPJLambdaWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs,
new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
@ -330,127 +253,9 @@ public class MPJLambdaWrapper<T> extends MPJAbstractLambdaWrapper<T, MPJLambdaWr
@Override
public void clear() {
super.clear();
selectDistinct = false;
sqlSelect.toNull();
from.toNull();
selectColumns.clear();
tableList.clear();
}
/**
* 关闭副表逻辑删除
* <p>
* 副表逻辑删除默认在where语句中
* 但有时候需要让它出现在on语句中, 这两种写法区别还是很大的
* 所以可以关闭副表逻辑删除, 通过on语句多条件, 自己实现on语句的逻辑删除
*/
public MPJLambdaWrapper<T> disableSubLogicDel() {
this.subLogicSql = false;
return typedThis;
}
public MPJLambdaWrapper<T> enableSubLogicDel() {
this.subLogicSql = true;
return typedThis;
}
/**
* 关闭主表逻辑删除
*/
public MPJLambdaWrapper<T> disableLogicDel() {
this.logicSql = false;
return typedThis;
}
public MPJLambdaWrapper<T> enableLogicDel() {
this.logicSql = true;
return typedThis;
}
/**
* 副表部分逻辑删除支持
*/
public String getSubLogicSql() {
if (subLogicSql && logicDelType == LogicDelTypeEnum.WHERE) {
if (tableList.getAll().isEmpty()) {
return StringPool.EMPTY;
}
return tableList.getAll().stream().map(t -> LogicInfoUtils.getLogicInfo(t.getIndex(),
t.getClazz(), t.isHasAlias(), t.getAlias())).collect(Collectors.joining(StringPool.SPACE));
}
return StringPool.EMPTY;
}
/**
* 主表部分逻辑删除支持
*/
public boolean getLogicSql() {
return this.logicSql;
}
/**
* 调整逻辑删除位置为ON语句
*/
public MPJLambdaWrapper<T> logicDelToOn() {
this.logicDelType = LogicDelTypeEnum.ON;
return typedThis;
}
/**
* 调整逻辑删除位置为WHERE语句
*/
public MPJLambdaWrapper<T> logicDelToWhere() {
this.logicDelType = LogicDelTypeEnum.WHERE;
return typedThis;
}
/**
* 内部调用, 不建议使用
*/
@Override
public <R> MPJLambdaWrapper<T> join(String keyWord, Class<R> clazz, String tableAlias, BiConsumer<MPJAbstractLambdaWrapper<T, ?>, MPJLambdaWrapper<T>> consumer) {
Integer oldIndex = this.getIndex();
int newIndex = tableIndex;
TableInfo info = TableHelper.get(clazz);
Asserts.hasTable(info, clazz);
MPJLambdaWrapper<T> instance = instance(newIndex, keyWord, clazz, info.getTableName());
instance.isNo = true;
instance.isMain = false;
onWrappers.add(instance);
if (StringUtils.isBlank(tableAlias)) {
tableList.put(oldIndex, clazz, false, ConfigProperties.tableAlias, newIndex);
instance.alias = ConfigProperties.tableAlias;
instance.hasAlias = false;
} else {
tableList.put(oldIndex, clazz, true, tableAlias, newIndex);
instance.alias = tableAlias;
instance.hasAlias = true;
}
tableIndex++;
this.index = newIndex;
boolean isM = this.isMain;
this.isMain = false;
consumer.accept(instance, typedThis);
this.isMain = isM;
this.index = oldIndex;
return typedThis;
}
/**
* 自定义关键词连接
*
* @param keyWord 连表关键词
* @param condition 条件
* @param joinSql sql
*/
@Override
public MPJLambdaWrapper<T> join(String keyWord, boolean condition, String joinSql) {
if (condition) {
MPJLambdaWrapper<T> wrapper = new MPJLambdaWrapper<>();
wrapper.from.setStringValue(joinSql);
wrapper.keyWord = keyWord;
onWrappers.add(wrapper);
}
return typedThis;
resultMapMybatisLabel.clear();
}
}

View File

@ -0,0 +1,252 @@
package com.github.yulichang.wrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.adapter.AdapterHelper;
import com.github.yulichang.toolkit.Asserts;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.toolkit.TableHelper;
import com.github.yulichang.toolkit.TableList;
import com.github.yulichang.wrapper.interfaces.Update;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author yulichang
* @since 1.4.5
*/
@SuppressWarnings("unused")
public class UpdateJoinWrapper<T> extends MPJAbstractLambdaWrapper<T, UpdateJoinWrapper<T>>
implements Update<UpdateJoinWrapper<T>> {
/**
* SQL 更新字段内容例如name='1', age=2
*/
private final SharedString sqlSetStr = new SharedString();
/**
* SQL 更新字段内容例如name='1', age=2
*/
private List<String> sqlSet;
/**
* SQL 更新字段内容例如name='1', age=2
*/
private List<UpdateSet> updateSet;
/**
* SQL 更新实体(更新非空字段)
*/
private List<Object> updateEntity;
/**
* SQL 更新实体(空字段也会更新)
*/
private List<Object> updateEntityNull;
private UpdateJoinWrapper() {
super();
}
/**
* 推荐使用此构造方法
*/
public UpdateJoinWrapper(Class<T> clazz) {
super(clazz);
}
public UpdateJoinWrapper(T entity) {
super(entity);
}
public UpdateJoinWrapper(Class<T> clazz, String alias) {
super(clazz, alias);
}
public UpdateJoinWrapper(T entity, String alias) {
super(entity, alias);
}
/**
* 设置更新的实体set语句部分, 更新非空字段
* <p>
* 注意!!!
* 这里这是的实体类是set部分, 不作为条件, where条件是wrapper.setEntity()
*/
public UpdateJoinWrapper<T> setUpdateEntity(Object... entity) {
if (Objects.isNull(updateEntity)) {
updateEntity = new ArrayList<>();
}
for (Object obj : entity) {
Assert.notNull(obj, "更新实体不能为空");
updateEntity.add(obj);
}
return typedThis;
}
/**
* 设置更新的实体set语句部分, 更新非空字段
* <p>
* 注意!!!
* 这里这是的实体类是set部分, 不作为条件, where条件是wrapper.setEntity()
*/
public UpdateJoinWrapper<T> setUpdateEntityAndNull(Object... entity) {
if (Objects.isNull(updateEntityNull)) {
updateEntityNull = new ArrayList<>();
}
for (Object obj : entity) {
Assert.notNull(obj, "更新实体不能为空");
updateEntityNull.add(obj);
}
return typedThis;
}
@Override
public <R> UpdateJoinWrapper<T> set(boolean condition, SFunction<R, ?> column, Object val, String mapping) {
return maybeDo(condition, () -> {
if (Objects.isNull(updateSet)) {
updateSet = new ArrayList<>();
}
updateSet.add(new UpdateSet(column, val, mapping));
});
}
@Override
public UpdateJoinWrapper<T> setSql(boolean condition, String sql) {
if (condition && StringUtils.isNotBlank(sql)) {
if (Objects.isNull(sqlSet)) {
sqlSet = new ArrayList<>();
}
sqlSet.add(sql);
}
return typedThis;
}
@Override
public String getSqlSet() {
if (StringUtils.isNotBlank(sqlSetStr.getStringValue())) {
return sqlSetStr.getStringValue();
}
StringBuilder set = new StringBuilder(StringPool.EMPTY);
if (CollectionUtils.isNotEmpty(updateSet)) {
set = new StringBuilder(updateSet.stream().map(i -> tableList.getPrefixByClass(LambdaUtils.getEntityClass(i.getColumn())) +
Constants.DOT + getCache(i.getColumn()).getColumn() + Constants.EQUALS + formatParam(i.mapping, i.value))
.collect(Collectors.joining(StringPool.COMMA)) + StringPool.COMMA);
}
if (CollectionUtils.isNotEmpty(sqlSet)) {
set.append(String.join(StringPool.COMMA, sqlSet)).append(StringPool.COMMA);
}
if (CollectionUtils.isNotEmpty(updateEntity)) {
getSqlByEntity(set, true, updateEntity);
}
if (CollectionUtils.isNotEmpty(updateEntityNull)) {
getSqlByEntity(set, false, updateEntityNull);
}
sqlSetStr.setStringValue(set.toString());
return set.toString();
}
/**
* 用于生成嵌套 sql
* <p> sqlSelect 不向下传递</p>
*/
@Override
protected UpdateJoinWrapper<T> instance() {
return instance(index, null, null, null);
}
@Override
protected UpdateJoinWrapper<T> instanceEmpty() {
return new UpdateJoinWrapper<>();
}
@Override
protected UpdateJoinWrapper<T> instance(Integer index, String keyWord, Class<?> joinClass, String tableName) {
return new UpdateJoinWrapper<>(getEntity(), getEntityClass(), paramNameSeq, paramNameValuePairs,
new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
this.tableList, index, keyWord, joinClass, tableName);
}
/**
* 不建议直接 new 该实例使用 JoinWrappers.update(User.class)
*/
public UpdateJoinWrapper(T entity, Class<T> entityClass, AtomicInteger paramNameSeq,
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
TableList tableList, Integer index, String keyWord, Class<?> joinClass, String tableName) {
super.setEntity(entity);
super.setEntityClass(entityClass);
this.paramNameSeq = paramNameSeq;
this.paramNameValuePairs = paramNameValuePairs;
this.expression = mergeSegments;
this.lastSql = lastSql;
this.sqlComment = sqlComment;
this.sqlFirst = sqlFirst;
this.tableList = tableList;
this.index = index;
this.keyWord = keyWord;
this.joinClass = joinClass;
this.tableName = tableName;
}
private void getSqlByEntity(StringBuilder sb, boolean filterNull, List<Object> entityList) {
for (Object obj : entityList) {
Assert.isTrue(tableList.contain(obj.getClass()), "更新的实体不是主表或关联表 <%>", obj.getClass().getSimpleName());
TableInfo tableInfo = TableHelper.get(obj.getClass());
Asserts.hasTable(tableInfo, obj.getClass());
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 (filterNull && Objects.isNull(val)) {
continue;
}
sb.append(tableList.getPrefixByClass(obj.getClass())).append(Constants.DOT)
.append(fieldInfo.getColumn()).append(Constants.EQUALS).append(formatParam(null, val))
.append(StringPool.COMMA);
}
}
}
@Override
public void clear() {
super.clear();
sqlSetStr.toNull();
if (CollectionUtils.isNotEmpty(sqlSet)) {
sqlSet.clear();
}
if (CollectionUtils.isNotEmpty(updateSet)) {
updateSet.clear();
}
if (CollectionUtils.isNotEmpty(updateEntity)) {
updateEntity.clear();
}
if (CollectionUtils.isNotEmpty(updateEntityNull)) {
updateEntityNull.clear();
}
}
@Data
@AllArgsConstructor
public static class UpdateSet {
private SFunction<?, ?> column;
private Object value;
private String mapping;
}
}

View File

@ -5,7 +5,6 @@ import com.github.yulichang.interfaces.MPJBaseJoin;
import com.github.yulichang.query.interfaces.StringJoin;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.wrapper.MPJAbstractLambdaWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import java.util.function.BiConsumer;
@ -45,7 +44,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param left 条件
* @param right 条件
*/
default <T, X> Children leftJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children leftJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.LEFT_JOIN, clazz, left, right, ext);
}
@ -57,7 +56,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param clazz 关联实体类
* @param consumer 条件
*/
default <T> Children leftJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children leftJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.LEFT_JOIN, clazz, consumer);
}
@ -91,7 +90,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param left 条件
* @param right 条件
*/
default <T, X> Children leftJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children leftJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.LEFT_JOIN, clazz, alias, left, right, ext);
}
@ -103,7 +102,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param clazz 关联实体类
* @param consumer 条件
*/
default <T> Children leftJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children leftJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.LEFT_JOIN, clazz, alias, consumer);
}
@ -124,14 +123,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children rightJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.RIGHT_JOIN, clazz, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T, X> Children rightJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.RIGHT_JOIN, clazz, consumer);
}
@ -152,14 +151,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children rightJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.RIGHT_JOIN, clazz, alias, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T, X> Children rightJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T, X> Children rightJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.RIGHT_JOIN, clazz, alias, consumer);
}
@ -181,14 +180,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children innerJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children innerJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.INNER_JOIN, clazz, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T> Children innerJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children innerJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.INNER_JOIN, clazz, consumer);
}
@ -210,14 +209,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children innerJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children innerJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.INNER_JOIN, clazz, alias, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T> Children innerJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children innerJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.INNER_JOIN, clazz, alias, consumer);
}
@ -238,14 +237,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children fullJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children fullJoin(Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.FULL_JOIN, clazz, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T> Children fullJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children fullJoin(Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.FULL_JOIN, clazz, consumer);
}
@ -266,14 +265,14 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* ignore 参考 left join
*/
default <T, X> Children fullJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children fullJoin(Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(Constant.FULL_JOIN, clazz, alias, left, right, ext);
}
/**
* ignore 参考 left join
*/
default <T> Children fullJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children fullJoin(Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(Constant.FULL_JOIN, clazz, alias, consumer);
}
@ -311,7 +310,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param left 条件
* @param right 条件
*/
default <T, X> Children join(String keyWord, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children join(String keyWord, Class<T> clazz, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(keyWord, clazz, (on, e) -> {
on.eq(left, right);
ext.apply(e);
@ -352,7 +351,7 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
* @param left 条件
* @param right 条件
*/
default <T, X> Children join(String keyWord, Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<MPJLambdaWrapper<Entity>> ext) {
default <T, X> Children join(String keyWord, Class<T> clazz, String alias, SFunction<T, ?> left, SFunction<X, ?> right, WrapperFunction<Children> ext) {
return join(keyWord, clazz, alias, (on, e) -> {
on.eq(left, right);
ext.apply(e);
@ -362,12 +361,12 @@ public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, String
/**
* 内部使用, 不建议直接调用
*/
default <T> Children join(String keyWord, Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer) {
default <T> Children join(String keyWord, Class<T> clazz, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer) {
return join(keyWord, clazz, null, consumer);
}
/**
* 内部使用, 不建议直接调用
*/
<T> Children join(String keyWord, Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, MPJLambdaWrapper<Entity>> consumer);
<T> Children join(String keyWord, Class<T> clazz, String alias, BiConsumer<MPJAbstractLambdaWrapper<Entity, ?>, Children> consumer);
}

View File

@ -0,0 +1,72 @@
package com.github.yulichang.wrapper.interfaces;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import java.io.Serializable;
/**
* copy {@link com.baomidou.mybatisplus.core.conditions.update.Update}
*
* @author yulichang
* @since 1.4.5
*/
@SuppressWarnings("unused")
public interface Update<Children> extends Serializable {
/**
* ignore
*/
default <R> Children set(SFunction<R, ?> column, Object val) {
return set(true, column, val);
}
/**
* 设置 更新 SQL SET 片段
*
* @param condition 是否加入 set
* @param column 字段
* @param val
* @return children
*/
default <R> Children set(boolean condition, SFunction<R, ?> column, Object val) {
return set(condition, column, val, null);
}
/**
* ignore
*/
default <R> Children set(SFunction<R, ?> column, Object val, String mapping) {
return set(true, column, val, mapping);
}
/**
* 设置 更新 SQL SET 片段
*
* @param condition 是否加入 set
* @param column 字段
* @param val
* @param mapping : javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler
* @return children
*/
<R> Children set(boolean condition, SFunction<R, ?> column, Object val, String mapping);
/**
* ignore
*/
default Children setSql(String sql) {
return setSql(true, sql);
}
/**
* 设置 更新 SQL SET 片段
*
* @param sql set sql
* @return children
*/
Children setSql(boolean condition, String sql);
/**
* 获取 更新 SQL SET 片段
*/
String getSqlSet();
}

View File

@ -72,22 +72,6 @@ public class MybatisPlusConfig {
};
}
// @Bean
// @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
// public SqlSessionFactory sqlSessionFactory(DataSource dataSource,
// MybatisPlusInterceptor interceptor) throws Exception {
// MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
// factory.setDataSource(dataSource);
// GlobalConfig.DbConfig config = new GlobalConfig.DbConfig();
// config.setLogicDeleteField("del");
// config.setLogicDeleteValue("true");
// config.setLogicNotDeleteValue("false");
// factory.setGlobalConfig(new GlobalConfig().setSqlInjector(new MPJSqlInjector())
// .setDbConfig(config));
// factory.setPlugins(interceptor);
// return factory.getObject();
// }
/**
* 校验sql
*/

View File

@ -1,14 +1,20 @@
package com.github.yulichang.test.join.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.ToString;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@Accessors(chain = true)
@TableName("address")
public class AddressDO extends AddressGeneric<Integer, Integer, Integer, String, String, Boolean> implements Serializable {
@TableField(exist = false)
private boolean aaa;
}

View File

@ -4,8 +4,10 @@ package com.github.yulichang.test.join.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AddressGeneric<ID, USER_ID, AREA_ID, TEL, ADDRESS, DEL> {
@TableId

View File

@ -0,0 +1,30 @@
package com.github.yulichang.test.join.entity;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.core.annotation.Order;
import java.io.Serializable;
@Data
@ToString
@Accessors(chain = true)
@TableName("order_t")
public class OrderDO implements Serializable {
@TableId
private Integer id;
private Integer userId;
@OrderBy
private String name;
@TableField(exist = false)
private String userName;
}

View File

@ -0,0 +1,10 @@
package com.github.yulichang.test.join.mapper;
import com.github.yulichang.test.join.entity.OrderDO;
import com.github.yulichang.test.join.entity.UserDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderMapper extends MyBaseMapper<OrderDO> {
}

View File

@ -88,4 +88,15 @@ INSERT INTO user_dto (id, user_id, create_by, update_by, del) VALUES
(5,1, 2, 3, false),
(6,1, 2, 3, false),
(7,1, 2, 3, false),
(8,1, 2, 3, false);
(8,1, 2, 3, false);
DELETE FROM order_t;
INSERT INTO order_t (id, user_id, age, name) VALUES
(1, 1, 8, '1,8'),
(2, 2, 7, '2,7'),
(3, 3, 6, '3,6'),
(4, 4, 5, '4,5'),
(5, 5, 4, '5,4'),
(6, 6, 3, '6,3'),
(7, 7, 2, '7,2'),
(8, 8, 1, '8,1');

View File

@ -56,3 +56,12 @@ create table user_dto
update_by int not null,
del bit null
);
create table order_t
(
id int auto_increment
primary key,
user_id int not null,
age int not null,
name varchar(255) not null
);

View File

@ -6,17 +6,16 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.test.join.dto.AddressDTO;
import com.github.yulichang.test.join.dto.UserDTO;
import com.github.yulichang.test.join.entity.AddressDO;
import com.github.yulichang.test.join.entity.AreaDO;
import com.github.yulichang.test.join.entity.UserDO;
import com.github.yulichang.test.join.entity.UserDto;
import com.github.yulichang.test.join.entity.*;
import com.github.yulichang.test.join.mapper.AddressMapper;
import com.github.yulichang.test.join.mapper.OrderMapper;
import com.github.yulichang.test.join.mapper.UserDTOMapper;
import com.github.yulichang.test.join.mapper.UserMapper;
import com.github.yulichang.test.util.ThreadLocalUtils;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.UpdateJoinWrapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@ -48,6 +47,9 @@ class LambdaWrapperTest {
@Autowired
private AddressMapper addressMapper;
@Autowired
private OrderMapper orderMapper;
@Test
void testJoin() {
@ -853,7 +855,7 @@ class LambdaWrapperTest {
"WHERE t.del = false\n" +
" AND (t.id <= ?)\n" +
"ORDER BY t.id DESC\n");
MPJLambdaWrapper<UserDO> wrapper = MPJWrappers.lambdaJoin(UserDO.class)
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.logicDelToOn()
.selectAll(UserDO.class)
.selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
@ -875,8 +877,6 @@ class LambdaWrapperTest {
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.logicDelToOn()
.selectAll(UserDO.class)
// .selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
// .id(AddressDO::getId))
.selectCollection(UserDTO::getAddressList, addr -> addr
.id(AddressDO::getId, AddressDTO::getId)
.result(UserDO::getName, AddressDTO::getAddress)
@ -900,13 +900,114 @@ class LambdaWrapperTest {
ThreadLocalUtils.set("SELECT t.id,t.user_id,t.area_id,t.tel,t.address,t.del FROM address t LEFT JOIN `user` t1 ON (t1.address_id = t.id) LEFT JOIN `user` t2 ON (t2.pid = t1.id) WHERE t.del=false AND t1.del=false AND t2.del=false");
MPJLambdaWrapper<AddressDO> wrapper = JoinWrappers.lambda(AddressDO.class)
.selectAll(AddressDO.class)
// .selectAssociation(AddressDO::getUsera, map -> map
// .all("t1", UserDO.class)
// .result("t2", UserDO::getName, UserDO::getPname))
.leftJoin(UserDO.class, UserDO::getAddressId, AddressDO::getId)
.leftJoin(UserDO.class, UserDO::getPid, UserDO::getId);
List<AddressDO> addressDOS = wrapper.list();
System.out.println(1);
}
/**
* 同一个类字段比较
*/
@Test
void joinOwn() {
ThreadLocalUtils.set("SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) WHERE t.del=false AND t1.del=false AND (t1.id = t1.id)");
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.selectAll(UserDO.class)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.eq(AddressDO::getId, AddressDO::getId);
List<UserDO> addressDOS = wrapper.list();
}
/**
* 同一个类字段比较
*/
@Test
void joinOwn1() {
ThreadLocalUtils.set("SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by FROM `user` t LEFT JOIN address aaa ON (aaa.user_id = t.id) WHERE t.del=false AND aaa.del=false AND (aaa.id = t.id AND aaa.id = aaa.id)");
MPJLambdaWrapper<UserDO> wrapper = JoinWrappers.lambda(UserDO.class)
.selectAll(UserDO.class)
.leftJoin(AddressDO.class, "aaa", AddressDO::getUserId, UserDO::getId, ext -> ext
.eq(AddressDO::getId, AddressDO::getId))
.eq(AddressDO::getId, AddressDO::getId);
List<UserDO> addressDOS = wrapper.list();
}
/**
* 同一个类字段比较
*/
@Test
void joinOrder() {
ThreadLocalUtils.set("SELECT id,user_id,name FROM order_t t ORDER BY t.name DESC");
MPJLambdaWrapper<OrderDO> wrapper = JoinWrappers.lambda(OrderDO.class);
List<OrderDO> list = wrapper.list();
ThreadLocalUtils.set("SELECT t.id,t.user_id,t.name,t1.`name` AS userName FROM order_t t LEFT JOIN `user` t1 ON (t1.id = t.user_id) WHERE t1.del=false ORDER BY t.name DESC");
MPJLambdaWrapper<OrderDO> w = JoinWrappers.lambda(OrderDO.class)
.selectAll(OrderDO.class)
.selectAs(UserDO::getName, OrderDO::getUserName)
.leftJoin(UserDO.class, UserDO::getId, OrderDO::getUserId);
System.out.println(wrapper.getFrom());
List<OrderDO> l = w.list();
}
/**
* 同一个类字段比较
*/
@Test
void delete() {
//物理删除
ThreadLocalUtils.set("DELETE t FROM order_t t LEFT JOIN user_dto t1 ON (t1.id = t.user_id) WHERE (t.id = ?)");
DeleteJoinWrapper<OrderDO> w = JoinWrappers.delete(OrderDO.class)
.leftJoin(UserDto.class, UserDto::getId, OrderDO::getUserId)
.eq(OrderDO::getId, 1);
try {
int i = orderMapper.deleteJoin(w);
} catch (BadSqlGrammarException ignored) {
//忽略异常 h2不支持连表删除
}
//逻辑删除
ThreadLocalUtils.set("UPDATE `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) LEFT JOIN area t2 ON (t2.id = t1.area_id) SET t.del=true ,t1.del=true,t2.del=true WHERE t.del=false AND t1.del=false AND t2.del=false AND (t.id = ?)");
DeleteJoinWrapper<UserDO> wrapper = JoinWrappers.delete(UserDO.class)
.deleteAll()
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.leftJoin(AreaDO.class, AreaDO::getId, AddressDO::getAreaId)
.eq(OrderDO::getId, 1);
try {
DeleteJoinWrapper<UserDO> wrapper1 = new DeleteJoinWrapper<>(UserDO.class);
int i = userMapper.deleteJoin(wrapper);
} catch (BadSqlGrammarException ignored) {
//忽略异常 h2不支持连表删除
}
}
@Test
void update() {
ThreadLocalUtils.set("UPDATE `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) SET t.update_by=?, t.`name`=?,t1.address=?,t1.tel=?,t1.address=?,t.`name`=?,t.update_by=?,t1.user_id=?,t1.area_id=?,t1.tel=?,t1.address=? WHERE t.del=false AND t1.del=false AND (t.id = ?)");
UpdateJoinWrapper<UserDO> update = JoinWrappers.update(UserDO.class)
.set(UserDO::getName, "aaaaaa")
.set(AddressDO::getAddress, "bbbbb")
.setUpdateEntity(new AddressDO().setAddress("sadf").setTel("qqqqqqqq"),
new UserDO().setName("nnnnnnnnnnnn").setUpdateBy(1))
.setUpdateEntityAndNull(new AddressDO())
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.eq(OrderDO::getId, 1);
try {
int i = userMapper.updateJoin(new UserDO().setUpdateBy(123123), update);
} catch (BadSqlGrammarException ignored) {
//忽略异常 h2不支持连表删除
}
ThreadLocalUtils.set("UPDATE `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) SET t.pid=?, t.`name`=?, t.`json`=?, t.sex=?, t.head_img=?, t.create_time=?, t.address_id=?, t.address_id2=?, t.create_by=?, t.update_by=? WHERE t.del=false AND t1.del=false AND (t.id = ?)");
UpdateJoinWrapper<UserDO> up = JoinWrappers.update(UserDO.class)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.eq(OrderDO::getId, 1);
try {
int i = userMapper.updateJoinAndNull(new UserDO(), up);
} catch (BadSqlGrammarException ignored) {
//忽略异常 h2不支持连表删除
}
}
}

View File

@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.test.util.ThreadLocalUtils;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.yulichang.test.springboot3jdk17.dto.AddressDTO;
import com.yulichang.test.springboot3jdk17.dto.UserDTO;
@ -571,7 +571,7 @@ class LambdaWrapperTest {
Page<UserDTO> page = new Page<>(1, 10);
page.setSearchCount(false);
IPage<UserDTO> iPage = userMapper.selectJoinPage(page, UserDTO.class,
MPJWrappers.<UserDO>lambdaJoin()
JoinWrappers.lambda(UserDO.class)
.selectAll(UserDO.class)
.select(AddressDO::getAddress)
.select(AreaDO::getProvince)
@ -607,7 +607,7 @@ class LambdaWrapperTest {
AND (t.id = ? AND (t.head_img = ? OR t1.user_id = ?) AND t.id = ?)
LIMIT ?""");
IPage<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
MPJWrappers.<UserDO>lambdaJoin()
JoinWrappers.lambda(UserDO.class)
.selectAll(UserDO.class)
.select(AddressDO::getAddress)
.leftJoin(AddressDO.class, on -> on
@ -626,7 +626,7 @@ class LambdaWrapperTest {
*/
@Test
void test4() {
UserDTO one = userMapper.selectJoinOne(UserDTO.class, MPJWrappers.<UserDO>lambdaJoin()
UserDTO one = userMapper.selectJoinOne(UserDTO.class, JoinWrappers.lambda(UserDO.class)
.selectSum(UserDO::getId)
.selectMax(UserDO::getId, UserDTO::getHeadImg)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId));
@ -667,7 +667,7 @@ class LambdaWrapperTest {
*/
@Test
void test7() {
List<Map<String, Object>> list = userMapper.selectJoinMaps(MPJWrappers.<UserDO>lambdaJoin()
List<Map<String, Object>> list = userMapper.selectJoinMaps(JoinWrappers.lambda(UserDO.class)
.selectAll(UserDO.class)
.select(AddressDO::getAddress)
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId));