mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
优化wrapper
This commit is contained in:
parent
90941058ce
commit
ed3c33db42
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 条件,查询总记录数
|
||||
*
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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}";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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> {
|
||||
|
||||
}
|
@ -89,3 +89,14 @@ INSERT INTO user_dto (id, user_id, create_by, update_by, del) VALUES
|
||||
(6,1, 2, 3, false),
|
||||
(7,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');
|
@ -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
|
||||
);
|
||||
|
@ -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不支持连表删除
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user