此版本为粗略完成版
依赖于mybatis-plus
一共一个接口两个类。下面直接上代码,后续再作陈述
1、接口:
package com.service.biz;
import java.util.List;
/**
* 根据入参与数据库存在的数据,获取可以删除、插入、更新的数据
*
* @author sven
* @version 1.1
* @since 2022/7/21
*/
public interface ICudDataService<T> {
/**
* 找到要删除的数据
*
* @param paramData
* @param dbData
* @param clazz
* @return 主键id列表
*/
List<String> getDeleteData(List<T> paramData, List<T> dbData, Class clazz);
/**
* 找到要进行更新的数据
*
* @param paramData
* @param dbData
* @param clazz
* @return
*/
List<T> getUpdateData(List<T> paramData, List<T> dbData, Class clazz);
/**
* 找到要进行插入的数据
*
* @param paramData
* @param dbData
* @param clazz
* @return
*/
List<T> getInsertData(List<T> paramData, List<T> dbData, Class clazz);
/**
* 保存数据,处理数据的增删改
*
* @param paramData 前台的参数
* @param dbData 后台的数据
* @param clazz 前后台参数对应的class
* @param beanName spring bean服务实现类名称
* @return SUCCESS:操作成功
*/
String saveData(List<T> paramData, List<T> dbData, Class clazz,String beanName);
}
2、接口的实现类:
package com.service.biz.impl;
import com.service.SpringBeanContext;
import com.service.biz.biz.ICudDataService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 根据入参与数据库存在的数据,获取可以删除、插入、更新的数据
*
* @author sven
* @version 1.1
* @since 2022/7/21
*/
@Service
public class CudDataServiceImpl<T> implements ICudDataService<T> {
private static final String MAIN_METHOD = "getId";
private static final String DELETE_METHOD = "deleteBatchIds";
private static final String INSERT_METHOD = "insertBatch";
private static final String UPDATE_METHOD = "updateBatchById";
public List<String> getDeleteData(List<T> paramData, List<T> dbData, Class clazz) {
if (CollectionUtils.isEmpty(paramData) && CollectionUtils.isNotEmpty(dbData))
return dbData.stream().map(obj -> getId(obj, clazz)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(dbData)) return new ArrayList<>();
return dbData.stream().filter(db -> !paramData.stream().anyMatch(para -> getId(db, clazz).equals(getId(para, clazz)))).map(obj -> getId(obj, clazz)).collect(Collectors.toList());
}
public List<T> getUpdateData(List<T> paramData, List<T> dbData, Class clazz) {
if (CollectionUtils.isEmpty(paramData) || CollectionUtils.isEmpty(dbData)) return new ArrayList<>();
return paramData.stream().filter(para -> dbData.stream().anyMatch(db -> getId(db, clazz).equals(getId(para, clazz)))).collect(Collectors.toList());
}
public List<T> getInsertData(List<T> paramData, List<T> dbData, Class clazz) {
if (CollectionUtils.isEmpty(paramData)) return new ArrayList<>();
if (CollectionUtils.isEmpty(dbData)) return paramData;
return paramData.stream().filter(para -> !dbData.stream().anyMatch(db -> getId(db, clazz).equals(getId(para, clazz)))).collect(Collectors.toList());
}
@Override
public String saveData(List<T> paramData, List<T> dbData, Class clazz, String beanName) {
try {
List<String> deleteData = getDeleteData(paramData, dbData, clazz);
Object[] Paras = {deleteData};
if (CollectionUtils.isNotEmpty(deleteData)) {
SpringBeanContext.springInvokeMethod(beanName, DELETE_METHOD, Paras);
}
List<T> insertData = getInsertData(paramData, dbData, clazz);
Object[] insertDataParas = {insertData};
if (CollectionUtils.isNotEmpty(insertData)) {
SpringBeanContext.springInvokeMethod(beanName, INSERT_METHOD, insertDataParas);
}
List<T> updateData = getUpdateData(paramData, dbData, clazz);
Object[] updateDataParas = {updateData};
if (CollectionUtils.isNotEmpty(updateData)) {
SpringBeanContext.springInvokeMethod(beanName, UPDATE_METHOD, updateDataParas);
}
} catch (Exception e) {
e.printStackTrace();
return "FAIL:" + e.getMessage();
}
return "SUCCESS";
}
private String getId(T t, Class clazz) {
try {
Method getId = clazz.getMethod(MAIN_METHOD);
return (String) getId.invoke(t, null);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
3、一个动态调用bean的类
package com.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
/**
* @author sven
* @version 1.0
* @since 2022/7/26
*/
@Component
public class SpringBeanContext implements ApplicationContextAware {
private static final Logger log = LoggerFactory.getLogger(SpringBeanContext.class);
protected static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringBeanContext.applicationContext = applicationContext;
}
public static Object getBean(String beanName) {
if (applicationContext == null) {
log.error("未初始化Spring上下文");
return null;
} else if (!applicationContext.containsBean(beanName)) {
log.warn("Spring上下文中不存在要查找的对象[{}]", beanName);
return null;
} else {
return applicationContext.getBean(beanName);
}
}
public static <T> T getBean(Class<T> clazz) {
if (applicationContext == null) {
log.error("未初始化Spring上下文");
return null;
} else {
return applicationContext.getBean(clazz);
}
}
public static <T> T getBean(String name, Class<T> clazz) {
if (applicationContext == null) {
log.error("未初始化Spring上下文");
return null;
} else {
return applicationContext.getBean(name, clazz);
}
}
public static Object springInvokeMethod(String serviceName, String methodName, Object[] params) throws Exception {
Object service = getBean(serviceName);
Class<? extends Object>[] paramClass = null;
if (params != null) {
int paramsLength = params.length;
paramClass = new Class[paramsLength];
for (int i = 0; i < paramsLength; i++) {
paramClass[i] = params[i] instanceof Class ? (Class<? extends Object>) params[i] : params[i].getClass();
}
}
// 找到方法
Method method = ReflectionUtils.findMethod(service.getClass(), methodName, paramClass);
// 定制化写法 单独针对通用保存方法写死参数类型的获取
if (method == null) method = ReflectionUtils.findMethod(service.getClass(), methodName, List.class);
if (method == null) method = ReflectionUtils.findMethod(service.getClass(), methodName, Collection.class);
// 定制化写法 end
// 执行方法
return ReflectionUtils.invokeMethod(method, service, params);
}
}
大体思路是通过lambda比较入参与数据库的数据,找出需要删除、新增、修改的数据。
再反射调用bean的mybatis-plus通用方法。
诸位看官可以参考下迭代优化成一个更通用的工具。
使用体验:
7月份完成的代码,到现在也实际在项目中用了一个多月,已在生产应用中应用!只要遵循好约定的入参与数据库数据用同一实体类,效果杠杠的,一下子不用去思考是否要删除或新增或修改了。
后续看情况再作迭代优化。暂时还是处于满足要求的状况