package com.tianqi.log;
import java.lang.reflect.Field;
import java.util.*;
public class EntityChangeLogger {
// 新增方法,获取字段的别名和字段名
private static String getFieldAliasWithFieldName(Field field) {
String alias = getFieldAlias(field);
String fieldName = field.getName();
return alias + "(" + fieldName + ")";
}
// 新增方法,获取实体的别名和类名
private static String getEntityAliasWithClassName(Class<?> clazz) {
String alias = getEntityAlias(clazz);
String className = clazz.getSimpleName();
if (!alias.equals(className)) {
return alias + "(" + className + ")";
} else {
return alias;
}
}
/**
* 记录实体变化前后的差异,支持唯一键判断和别名注解
*
* @param before 变化前的实体列表
* @param after 变化后的实体列表
* @param <T> 实体类型
* @return 变化前后的差异日志(中文描述)
*/
public static <T> String logChanges(List<T> before, List<T> after) {
StringBuilder log = new StringBuilder();
log.append("检测到以下变化:\n");
try {
// 获取唯一键字段
Class<?> clazz = before.isEmpty() ? after.get(0).getClass() : before.get(0).getClass();
List<String> uniqueKeys = getUniqueKeys(clazz);
if (uniqueKeys.isEmpty()) {
throw new IllegalArgumentException("实体类中未找到唯一键字段。");
}
// 构建唯一键到实体的映射
Map<String, T> beforeMap = buildUniqueKeyMap(before, uniqueKeys);
Map<String, T> afterMap = buildUniqueKeyMap(after, uniqueKeys);
// 比较变化
log.append(compareChanges(beforeMap, afterMap, uniqueKeys));
} catch (IllegalAccessException e) {
log.append("错误:访问字段失败:").append(e.getMessage()).append("\n");
} catch (IllegalArgumentException e) {
log.append("错误:").append(e.getMessage()).append("\n");
}
return log.toString();
}
/**
* 获取实体类的唯一键字段
*
* @param clazz 实体类
* @return 唯一键字段列表
*/
private static List<String> getUniqueKeys(Class<?> clazz) {
List<String> uniqueKeys = new ArrayList<>();
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(UniqueKey.class)) {
uniqueKeys.add(field.getName());
}
}
clazz = clazz.getSuperclass(); // 移动到父类
}
return uniqueKeys;
}
/**
* 构建唯一键到实体的映射
*
* @param entities 实体列表
* @param uniqueKeys 唯一键字段列表
* @param <T> 实体类型
* @return 唯一键到实体的映射
* @throws IllegalAccessException 如果字段不可访问
*/
private static <T> Map<String, T> buildUniqueKeyMap(List<T> entities, List<String> uniqueKeys) throws IllegalAccessException {
Map<String, T> map = new HashMap<>();
for (T entity : entities) {
String uniqueKeyValue = getUniqueKeyValue(entity, uniqueKeys);
map.put(uniqueKeyValue, entity);
}
return map;
}
/**
* 获取实体的唯一键值
*
* @param entity 实体对象
* @param uniqueKeys 唯一键字段列表
* @param <T> 实体类型
* @return 唯一键值
* @throws IllegalAccessException 如果字段不可访问
*/
private static <T> String getUniqueKeyValue(T entity, List<String> uniqueKeys) throws IllegalAccessException {
StringBuilder keyBuilder = new StringBuilder();
for (String uniqueKey : uniqueKeys) {
Field field = getField(entity.getClass(), uniqueKey); // 确保这里传入的是正确的字段名
field.setAccessible(true);
Object value = field.get(entity);
keyBuilder.append(value != null ? value.toString() : "null").append("|");
}
return keyBuilder.toString();
}
/**
* 获取字段别名
*
* @param field 字段对象
* @return 字段别名(如果存在),否则返回字段名
*/
private static String getFieldAlias(Field field) {
if (field.isAnnotationPresent(Alias.class)) {
return field.getAnnotation(Alias.class).value();
}
return field.getName();
}
/**
* 获取实体的描述(包含别名和嵌套关系)
*
* @param entity 实体对象
* @param <T> 实体类型
* @return 实体的描述
* @throws IllegalAccessException 如果字段不可访问
*/
private static <T> String getEntityDescription(T entity) throws IllegalAccessException {
StringBuilder description = new StringBuilder();
description.append(entity.getClass().getSimpleName()).append("(").append(getEntityAlias(entity.getClass())).append("){");
Field[] fields = entity.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Object value = field.get(entity);
String fieldAlias = getFieldAlias(field);
String fieldTypeAlias = getEntityAlias(field.getType());
description.append(fieldAlias).append("(").append(field.getName()).append(")=");
if (value != null && !isPrimitiveOrWrapper(value.getClass()) && !value.getClass().equals(String.class)) {
description.append(getEntityDescription(value)); // 递归描述嵌套对象
} else {
description.append(value);
}
description.append(", ");
}
// 移除最后一个逗号和空格
if (description.toString().endsWith(", ")) {
description.setLength(description.length() - 2);
}
description.append("}");
return description.toString();
}
/**
* 获取类的别名
*
* @param clazz 类
* @return 类的别名(如果存在),否则返回类名
*/
private static String getEntityAlias(Class<?> clazz) {
if (clazz.isAnnotationPresent(Alias.class)) {
return clazz.getAnnotation(Alias.class).value();
}
return clazz.getSimpleName();
}
/**
* 判断类是否是基本类型或其包装类
*
* @param clazz 类
* @return 是否是基本类型或其包装类
*/
private static boolean isPrimitiveOrWrapper(Class<?> clazz) {
return clazz.isPrimitive() ||
clazz.equals(Boolean.class) ||
clazz.equals(Character.class) ||
clazz.equals(Byte.class) ||
clazz.equals(Short.class) ||
clazz.equals(Integer.class) ||
clazz.equals(Long.class) ||
clazz.equals(Float.class) ||
clazz.equals(Double.class);
}
/**
* 获取字段对象(支持递归获取嵌套字段)
*
* @param clazz 类
* @param fieldName 字段名
* @return 字段对象
*/
private static Field getField(Class<?> clazz, String fieldName) {
try {
// 尝试从当前类获取字段
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true); // 确保字段可访问
return field;
} catch (NoSuchFieldException e) {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
return getField(superClass, fieldName); // 在父类中查找字段
}
throw new RuntimeException("未找到字段:" + fieldName, e);
}
}
深海鱼流浪去了北冰洋
- 粉丝: 94
- 资源: 9
最新资源
- 【创新无忧】基于白鲸优化算法BWO优化广义神经网络GRNN实现数据回归预测附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化广义神经网络GRNN实现电机故障诊断附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化广义神经网络GRNN实现光伏预测附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化相关向量机RVM实现北半球光伏数据预测附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化极限学习机ELM实现乳腺肿瘤诊断附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化极限学习机KELM实现故障诊断附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化广义神经网络GRNN实现光伏预测附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化广义神经网络GRNN实现电机故障诊断附matlab代码.rar
- 【创新无忧】基于白鲸优化算法BWO优化相关向量机RVM实现数据多输入单输出回归预测附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化广义神经网络GRNN实现数据回归预测附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化极限学习机KELM实现故障诊断附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化极限学习机ELM实现乳腺肿瘤诊断附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化相关向量机RVM实现数据多输入单输出回归预测附matlab代码.rar
- 【创新无忧】基于白鲨优化算法WSO优化广义神经网络GRNN实现电机故障诊断附matlab代码.rar
- 【创新无忧】基于白鹭群优化算法ESOA优化相关向量机RVM实现北半球光伏数据预测附matlab代码.rar
- 【创新无忧】基于白鲨优化算法WSO优化广义神经网络GRNN实现数据回归预测附matlab代码.rar
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈