1. 通用添加、更新、删除逻辑

2. 增加全量更新、新增
This commit is contained in:
warden 2023-06-19 14:45:48 +08:00
parent b7ce933971
commit 0b293092a3
6 changed files with 528 additions and 1 deletions

View File

@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.dromara.common.core.factory.YmlPropertySourceFactory;
import org.dromara.common.mybatis.core.mapper.MySqlInjector;
import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler;
import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor;
import org.mybatis.spring.annotation.MapperScan;
@ -82,6 +83,14 @@ public class MybatisPlusConfig {
return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
}
/**
* 全量更新
* @return
*/
@Bean
public MySqlInjector sqlInjector() {
return new MySqlInjector();
}
/**
* PaginationInnerInterceptor 分页插件自动识别数据库类型
* https://baomidou.com/pages/97710a/

View File

@ -30,7 +30,7 @@ import java.util.stream.Collectors;
* @since 2021-05-13
*/
@SuppressWarnings("unchecked")
public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
public interface BaseMapperPlus<T, V> extends CommonMapper<T> {
Log log = LogFactory.getLog(BaseMapperPlus.class);

View File

@ -0,0 +1,32 @@
package org.dromara.common.mybatis.core.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Author warden
* @Date 2023/1/17 17:37
*/
public interface CommonMapper<T> extends BaseMapper<T> {
/**
* 全量插入,等价于insert
* {@link com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn}
*
* @param entityList
* @return
*/
int insertBatchSomeColumn(List<T> entityList);
/**
* 全量更新不忽略null字段等价于update
* 解决mybatis-plus会自动忽略null字段不更新
* {@link com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById}
*
* @param entity
* @return
*/
int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
}

View File

@ -0,0 +1,33 @@
package org.dromara.common.mybatis.core.mapper;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import java.util.List;
/**
* 自定义Sql注入
*
* @author nieqiurong 2018/8/11 20:23.
*/
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
/**
* 以下 3 个为内置选装件
* 2 个支持字段筛选函数
*/
// : 不要指定了 update 填充的字段
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
// 标识了INSERT的字段不更新createTime createBy)
methodList.add(new AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT));
return methodList;
}
}

View File

@ -0,0 +1,167 @@
package org.dromara.common.mybatis.core.utils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.satoken.utils.LoginHelper;
import java.lang.reflect.Field;
import java.util.*;
/**
* @Author warden
* @Date 2022/12/8 14:56
*/
@Slf4j
public class BeanUtil {
public static final String ADD = "ADD";
public static final String REMOVE = "REMOVE";
public static final String NORMAL = "NORMAL";
/**
* 比对两条记录数据库字段是否相同相同返回true不同返回false
*
* @param compare
* @param current
* @return
*/
public static boolean diffObject(Object compare, Object current) {
List<Field> fieldList = new ArrayList<>();
Field[] allFields = ReflectUtil.getFieldsDirectly(compare.getClass(), true);
String[] dontCompareFields = {"createBy", "createTime", "updateBy", "updateTime", "params", "searchValue", "serialVersionUID"};
List<String> dCList = new ArrayList<>();
dCList.addAll(Arrays.asList(dontCompareFields));
for (Field field : allFields) {
if (dCList.contains(field.getName())) {
continue;
}
TableField tableField = field.getAnnotation(TableField.class);
if (tableField == null || tableField.exist()) {
fieldList.add(field);
}
}
for (Field field : fieldList) {
try {
//抑制Java对其的检查
field.setAccessible(true);
//获取 object field 所代表的属性值
Object comp = field.get(compare);
Object curr = field.get(current);
if (comp != null && curr != null) {
if (!comp.toString().equals(curr.toString())) {
return false;
}
} else {
if ((comp == null && curr != null) || (comp != null && curr == null)) {
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
/**
* 比较原List与现List的差异返回Map
* Map的三个KEY值ADD(新增)\REMOVE删除\NORMAL相同
*
* @param compareList 需要比较的list(页面传过来的
* @param currList 当前的list当前数据库中的
* @return
*/
public static Map<String, Set<Long>> diffList(Set<Long> compareList, Set<Long> currList) {
if (CollectionUtil.isEmpty(compareList) && CollectionUtil.isEmpty(currList)) {
return null;
}
Map<String, Set<Long>> result = new HashMap();
result.put(ADD, new HashSet<Long>());
result.put(REMOVE, new HashSet<Long>());
result.put(NORMAL, new HashSet<Long>());
if (CollectionUtil.isEmpty(compareList)) {
result.put(REMOVE, currList);
} else if (CollectionUtil.isEmpty(currList)) {
result.put(ADD, compareList);
} else {
for (Long comStr : compareList) {
if (currList.contains(comStr)) {
result.get(NORMAL).add(comStr);
} else {
result.get(ADD).add(comStr);
}
}
for (Long currStr : currList) {
if (compareList.contains(currStr)) {
result.get(NORMAL).add(currStr);
} else {
result.get(REMOVE).add(currStr);
}
}
}
return result;
}
public static Map diffList(List<Long> compareList, List<Long> currList) {
Set<Long> compareSet = new HashSet<>();
Set<Long> currSet = new HashSet<>();
if (CollectionUtil.isNotEmpty(compareList)) {
for (Long val : compareList) {
compareSet.add(val);
}
}
if (CollectionUtil.isNotEmpty(currList)) {
for (Long val : currList) {
currSet.add(val);
}
}
return diffList(compareSet, currSet);
}
public static void fillValue(Object object) {
if (object instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) object;
Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime())
? baseEntity.getCreateTime() : new Date();
baseEntity.setCreateTime(current);
baseEntity.setUpdateTime(current);
Long userId = baseEntity.getCreateBy() != null
? baseEntity.getCreateBy() : getLoginUserId();
// 当前已登录 创建人为空 则填充
baseEntity.setCreateBy(userId);
// 当前已登录 更新人为空 则填充
baseEntity.setUpdateBy(userId);
}
}
/**
* 获取登录用户名
*/
private static Long getLoginUserId() {
LoginUser loginUser;
try {
loginUser = LoginHelper.getLoginUser();
} catch (Exception e) {
log.warn("自动注入警告 => 用户未登录");
return null;
}
return loginUser.getUserId();
}
}

View File

@ -0,0 +1,286 @@
package org.dromara.common.mybatis.core.utils;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.core.mapper.CommonMapper;
import java.util.*;
/**
* 比对列表数据用于判断差异并保存到数据库中
* 全量保存
*/
public class SaveDiffUtil {
// 获取mybatisplus 的ID生成器
private final static IdentifierGenerator IDENTIFIER_GENERATOR = SpringUtils.getBean("idGenerator");
public static Map<String, Set<Long>> saveFormDiff(List formList, List oriList, BaseMapper mapper) {
return saveFormDiff(formList, oriList, mapper, null, null);
}
public static Map<String, Set<Long>> saveFormDiff(List formList, List oriList, BaseMapper mapper, Boolean exeUpdate) {
return saveFormDiff(formList, oriList, mapper, exeUpdate, null);
}
/**
* 需要处理手工修改的记录
*
* @param formList 表单提交的数据
* @param oriList 数据库数据
* @param mapper 处理实体的mapper
* @param exeUpdate 是否执行更新
* @param updateAll 更新操作是否全字段更新
* @throws Exception
*/
public static Map<String, Set<Long>> saveFormDiff(List formList, List oriList, BaseMapper mapper,
Boolean exeUpdate, Boolean updateAll) {
if (exeUpdate == null) {
exeUpdate = false;
}
if (updateAll == null) {
updateAll = false;
}
if (formList == null) {
formList = new ArrayList();
}
Map<String, Set<Long>> result = getFormDiff(formList, oriList);
if (result != null) {
Set<Long> addList = result.get(BeanUtil.ADD);
Set<Long> removeList = result.get(BeanUtil.REMOVE);
Set<Long> updateList = result.get(BeanUtil.NORMAL);
// 添加的对象
if (addList != null && addList.size() > 0) {
List addObjList = new ArrayList();
for (Long id : addList) {
Iterator it = formList.iterator();
while (it.hasNext()) {
Object obj = it.next();
Long objId = (Long) ReflectUtil.getFieldValue(obj, "id");
if (id.equals(objId)) {
addObjList.add(obj);
// it.remove(); 不可删除需要返回
break;
}
}
}
if (addObjList != null && addObjList.size() > 0) {
// List list = cn.hutool.core.bean.BeanUtil.copyToList(addObjList, clz);
((BaseMapperPlus) mapper).insertBatch(addObjList);
}
}
if (removeList != null && removeList.size() > 0) {
mapper.deleteBatchIds(removeList);
}
if (exeUpdate && updateList != null && updateList.size() > 0) {
List updateObjList = new ArrayList();
for (Long id : updateList) {
Object compareObj = findObj(formList, id);
Object currObj = findObj(oriList, id);
// 比对数据库字段是否有修改
boolean diff = BeanUtil.diffObject(compareObj, currObj);
if (!diff) {
updateObjList.add(compareObj);
}
}
if (updateObjList.size() > 0) {
for (Object obj : updateObjList) {
if (updateAll) {
// 全量更新
((CommonMapper) mapper).alwaysUpdateSomeColumnById(obj);
} else {
// 更新不为空
mapper.updateById(obj);
}
}
}
}
}
return result;
}
public static Map<String, Set<Long>> getFormDiff(List formList, List oriList) {
// 需要比较的
List<Long> compareList = new ArrayList<>();
// 原始数据
List<Long> currList = new ArrayList<>();
updateObject(formList, compareList);
updateObject(oriList, currList);
Map<String, Set<Long>> result = BeanUtil.diffList(compareList, currList);
return result;
}
private static void updateObject(List objList, List targetList, String idFieldName) {
if (idFieldName == null) {
idFieldName = "id";
}
for (Object obj : objList) {
Object val = ReflectUtil.getFieldValue(obj, idFieldName);
if (val != null) {
targetList.add(val);
} else {
Long uuid = IDENTIFIER_GENERATOR.nextId(obj).longValue();
targetList.add(uuid);
ReflectUtil.setFieldValue(obj, "id", uuid);
}
}
}
private static void updateObject(List objList, List targetList) {
updateObject(objList, targetList, null);
}
/**
* 根据查询的属性找对象的key并赋值到目标列表中
*
* @param oriList
* @param targetList
* @param searchFieldName
* @param idFieldName
*/
public static void updateObject(List oriList, List targetList, String searchFieldName, String idFieldName) {
if (oriList == null) {
return;
}
for (Object oriObj : oriList) {
Object searchStr = ReflectUtil.getFieldValue(oriObj, searchFieldName);
if (searchStr != null) {
for (Object tarObj : targetList) {
Object tarStr = ReflectUtil.getFieldValue(tarObj, searchFieldName);
if (searchStr.equals(tarStr)) {
Object idStr = ReflectUtil.getFieldValue(oriObj, idFieldName);
if (idStr != null) {
ReflectUtil.setFieldValue(tarObj, idFieldName, idStr);
}
continue;
}
}
}
}
}
/**
* 根据属性及属性值从列表中查找对象
*
* @param objList
* @param idFieldName
* @param keyValue
* @return
*/
private static Object findObj(List objList, String idFieldName, Object keyValue) {
if (idFieldName == null) {
idFieldName = "id";
}
Object result = null;
for (Object obj : objList) {
Object val = ReflectUtil.getFieldValue(obj, idFieldName);
if (keyValue.equals(val)) {
result = obj;
break;
}
}
return result;
}
private static Object findObj(List objList, Object keyValue) {
return findObj(objList, null, keyValue);
}
// /**
// * 修改关系记录根据linkID+pkId添加和删除
// */
// /**
// * @param currentUser 当前用户
// * @param formList 表单提交的数据
// * @param oriList 数据库中的数据
// * @param clz 要插入表中的对象对应的类
// * @param findId 根据哪个属性查找传入的formListoriList
// * @param pkIdName 根据哪个属性删除添加关系记录
// * @param linkIdName 外键字段名称
// * @param linkId 外键字段值
// * @param mapper
// * @throws Exception
// */
// public static void saveRelaDiff(
// List formList,
// List oriList,
// Class clz,
// String findId,
// String pkIdName,
// String linkIdName,
// String linkId,
// BaseMapper mapper) throws Exception {
// // 需要比较的
// List<String> compareList = new ArrayList<>();
// // 原始数据
// List<String> currList = new ArrayList<>();
//
// updateObject(formList, compareList, findId);
// updateObject(oriList, currList, findId);
//
// Map<String, Set<String>> result = BeanUtil.diffList(compareList, currList);
//
// if (result != null) {
// Set<String> addList = result.get(BeanUtil.ADD);
// Set<String> removeList = result.get(BeanUtil.REMOVE);
//
// //删除数据
// if (removeList != null && removeList.size() > 0) {
// for (String removeId : removeList) {
// Object obj = clz.newInstance();
// ReflectUtil.setFieldValue(obj, "delFlag", DelFlag.DELETE);
//
// Example remExample = new Example(clz);
// Example.Criteria remCriteria = remExample.createCriteria();
// //获取删除标记为正常的记录
// remCriteria.andEqualTo(linkIdName, linkId);
// remCriteria.andEqualTo(pkIdName, removeId);
// remCriteria.andNotEqualTo("delFlag", DelFlag.DELETE);
// mapper.updateByExampleSelective(obj, remExample);
// }
// }
//
// //添加资源
// if (addList != null && addList.size() > 0) {
// List addObjList = new ArrayList();
// for (String addId : addList) {
// Object obj = clz.newInstance();
// ReflectUtil.setFieldValue(obj, linkIdName, linkId);
// ReflectUtil.setFieldValue(obj, pkIdName, addId);
//
// BeanUtil.setCreateUser(currentUser, obj);
// BeanUtil.setUpdateUser(currentUser, obj);
//
// addObjList.add(obj);
// }
//
// if (addObjList.size() > 0) {
// mapper.batchInsert(addObjList);
// }
// }
// }
// }
}