|
|
@@ -98,25 +98,57 @@ public class OperationLogAspect implements ApplicationContextAware {
|
|
|
Object paramObj = null;
|
|
|
Object idValue = null;
|
|
|
|
|
|
- // 查找包含ID的參數對象
|
|
|
- if (args != null && parameterNames != null) {
|
|
|
+ // 優先使用注解中指定的ID參數名
|
|
|
+ if (annotation != null && StringUtils.isNotBlank(annotation.idParam()) && args != null && parameterNames != null) {
|
|
|
+ for (int i = 0; i < parameterNames.length; i++) {
|
|
|
+ if (annotation.idParam().equals(parameterNames[i]) && args[i] != null) {
|
|
|
+ idValue = args[i];
|
|
|
+ log.info("從注解指定的參數名中獲取ID: 參數名={}, ID值={}, 類型: {}",
|
|
|
+ annotation.idParam(), idValue, args[i].getClass().getSimpleName());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果沒有通過指定參數名找到ID,則使用原來的邏輯
|
|
|
+ if (idValue == null && args != null && parameterNames != null) {
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
Object arg = args[i];
|
|
|
- if (arg != null && !isPrimitiveOrWrapper(arg.getClass()) && !isString(arg.getClass())) {
|
|
|
- // 嘗試從對象中提取ID
|
|
|
- idValue = extractIdFromObject(arg, annotation.idField());
|
|
|
- if (idValue != null) {
|
|
|
- paramObj = arg;
|
|
|
- log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
|
|
|
- break;
|
|
|
+ if (arg != null) {
|
|
|
+ // 如果參數本身就是ID(Integer、Long、String等基本類型)
|
|
|
+ if (isPrimitiveOrWrapper(arg.getClass()) || isString(arg.getClass())) {
|
|
|
+ // 如果指定了mapper,可以直接使用這個參數作為ID
|
|
|
+ if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
|
|
|
+ // 如果沒有指定idParam,或者參數名是"id",則使用
|
|
|
+ if (StringUtils.isBlank(annotation.idParam()) || "id".equals(parameterNames[i])) {
|
|
|
+ idValue = arg;
|
|
|
+ log.info("參數本身就是ID: {}, 參數名: {}, 類型: {}",
|
|
|
+ idValue, parameterNames[i], arg.getClass().getSimpleName());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 嘗試從對象中提取ID
|
|
|
+ idValue = extractIdFromObject(arg, annotation.idField());
|
|
|
+ if (idValue != null) {
|
|
|
+ paramObj = arg;
|
|
|
+ log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果找到了ID,通過Mapper查詢原始數據(方法執行前)
|
|
|
- if (idValue != null && paramObj != null) {
|
|
|
- beforeDataObj = queryBeforeDataById(paramObj.getClass(), idValue);
|
|
|
+ // 如果注解中指定了mapper,可以直接使用mapper查詢,不需要paramObj
|
|
|
+ if (idValue != null) {
|
|
|
+ Class<?> entityClass = paramObj != null ? paramObj.getClass() : null;
|
|
|
+ // 如果指定了mapper,實體類會從mapper中提取,所以entityClass可以為null
|
|
|
+ if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
|
|
|
+ entityClass = null; // 實體類將從mapper中提取
|
|
|
+ }
|
|
|
+ beforeDataObj = queryBeforeDataById(entityClass, idValue, annotation);
|
|
|
if (beforeDataObj != null) {
|
|
|
log.info("✓ 成功查詢到修改前的數據,類型: {}", beforeDataObj.getClass().getSimpleName());
|
|
|
log.info("修改前的數據JSON: {}", JSON.toJSONString(beforeDataObj));
|
|
|
@@ -447,42 +479,71 @@ public class OperationLogAspect implements ApplicationContextAware {
|
|
|
Object paramObj = null;
|
|
|
Object idValue = null;
|
|
|
|
|
|
- // 查找包含ID的參數對象
|
|
|
- if (args != null && parameterNames != null) {
|
|
|
+ // 優先使用注解中指定的ID參數名
|
|
|
+ if (annotation != null && StringUtils.isNotBlank(annotation.idParam()) && args != null && parameterNames != null) {
|
|
|
+ for (int i = 0; i < parameterNames.length; i++) {
|
|
|
+ if (annotation.idParam().equals(parameterNames[i]) && args[i] != null) {
|
|
|
+ idValue = args[i];
|
|
|
+ log.info("從注解指定的參數名中獲取ID: 參數名={}, ID值={}, 類型: {}",
|
|
|
+ annotation.idParam(), idValue, args[i].getClass().getSimpleName());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果沒有通過指定參數名找到ID,則使用原來的邏輯
|
|
|
+ if (idValue == null && args != null && parameterNames != null) {
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
Object arg = args[i];
|
|
|
- if (arg != null && !isPrimitiveOrWrapper(arg.getClass()) && !isString(arg.getClass())) {
|
|
|
- // 嘗試從對象中提取ID
|
|
|
- idValue = extractIdFromObject(arg, annotation.idField());
|
|
|
- if (idValue != null) {
|
|
|
- paramObj = arg;
|
|
|
- log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if (arg != null && (arg instanceof Integer || arg instanceof Long || arg instanceof String)) {
|
|
|
- // 如果參數本身就是ID
|
|
|
- idValue = arg;
|
|
|
- log.info("參數本身就是ID: {}", idValue);
|
|
|
- // 需要找到對應的實體類,這裡先嘗試從其他參數中找
|
|
|
- for (int j = 0; j < args.length; j++) {
|
|
|
- if (j != i && args[j] != null &&
|
|
|
- !isPrimitiveOrWrapper(args[j].getClass()) &&
|
|
|
- !isString(args[j].getClass())) {
|
|
|
- paramObj = args[j];
|
|
|
+ if (arg != null) {
|
|
|
+ // 如果參數本身就是ID(Integer、Long、String等基本類型)
|
|
|
+ if (isPrimitiveOrWrapper(arg.getClass()) || isString(arg.getClass())) {
|
|
|
+ // 如果指定了mapper,可以直接使用這個參數作為ID
|
|
|
+ if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
|
|
|
+ // 如果沒有指定idParam,或者參數名是"id",則使用
|
|
|
+ if (StringUtils.isBlank(annotation.idParam()) || "id".equals(parameterNames[i])) {
|
|
|
+ idValue = arg;
|
|
|
+ log.info("參數本身就是ID: {}, 參數名: {}, 類型: {}",
|
|
|
+ idValue, parameterNames[i], arg.getClass().getSimpleName());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 沒有指定mapper,需要找到對應的實體類
|
|
|
+ idValue = arg;
|
|
|
+ log.info("參數本身就是ID: {}", idValue);
|
|
|
+ // 嘗試從其他參數中找實體對象
|
|
|
+ for (int j = 0; j < args.length; j++) {
|
|
|
+ if (j != i && args[j] != null &&
|
|
|
+ !isPrimitiveOrWrapper(args[j].getClass()) &&
|
|
|
+ !isString(args[j].getClass())) {
|
|
|
+ paramObj = args[j];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 嘗試從對象中提取ID
|
|
|
+ idValue = extractIdFromObject(arg, annotation.idField());
|
|
|
+ if (idValue != null) {
|
|
|
+ paramObj = arg;
|
|
|
+ log.info("從參數中提取到ID: {}, 對象類型: {}", idValue, arg.getClass().getSimpleName());
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果找到了ID,通過Mapper查詢原始數據
|
|
|
- if (idValue != null && paramObj != null) {
|
|
|
- beforeDataObj = queryBeforeDataById(paramObj.getClass(), idValue);
|
|
|
- } else if (idValue != null) {
|
|
|
- // 只有ID,沒有對象,嘗試通過ID類型推斷實體類
|
|
|
- log.warn("只有ID沒有對象,無法自動查詢原始數據。ID: {}", idValue);
|
|
|
+ // 如果注解中指定了mapper,可以直接使用mapper查詢,不需要paramObj
|
|
|
+ if (idValue != null) {
|
|
|
+ Class<?> entityClass = paramObj != null ? paramObj.getClass() : null;
|
|
|
+ // 如果指定了mapper,實體類會從mapper中提取,所以entityClass可以為null
|
|
|
+ if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
|
|
|
+ entityClass = null; // 實體類將從mapper中提取
|
|
|
+ }
|
|
|
+ beforeDataObj = queryBeforeDataById(entityClass, idValue, annotation);
|
|
|
} else {
|
|
|
log.warn("無法從參數中提取ID,跳過查詢修改前的數據");
|
|
|
}
|
|
|
@@ -727,78 +788,159 @@ public class OperationLogAspect implements ApplicationContextAware {
|
|
|
/**
|
|
|
* 通過ID查詢修改前的數據
|
|
|
*/
|
|
|
- private Object queryBeforeDataById(Class<?> entityClass, Object id) {
|
|
|
- if (id == null || entityClass == null) {
|
|
|
+ private Object queryBeforeDataById(Class<?> entityClass, Object id, shop.alien.store.annotation.ChangeRecordLog annotation) {
|
|
|
+ if (id == null) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- // 根據實體類名推斷Mapper名稱
|
|
|
- // 例如:EssentialHolidayComparison -> EssentialHolidayComparisonMapper
|
|
|
- String entityName = entityClass.getSimpleName();
|
|
|
- String mapperBeanName = entityName.substring(0, 1).toLowerCase() + entityName.substring(1) + "Mapper";
|
|
|
+ BaseMapper<?> mapper = null;
|
|
|
+ Class<?> actualEntityClass = entityClass;
|
|
|
|
|
|
- // 嘗試從Spring容器中獲取Mapper
|
|
|
- if (applicationContext != null) {
|
|
|
+ // 優先使用注解中指定的Mapper
|
|
|
+ if (annotation != null && annotation.mapper() != null && annotation.mapper() != BaseMapper.class) {
|
|
|
+ try {
|
|
|
+ if (applicationContext != null) {
|
|
|
+ // 從Spring容器中獲取指定類型的Mapper實例
|
|
|
+ mapper = applicationContext.getBean(annotation.mapper());
|
|
|
+ log.info("使用注解中指定的Mapper: {}", annotation.mapper().getSimpleName());
|
|
|
+
|
|
|
+ // 從Mapper的泛型參數中提取實體類
|
|
|
+ actualEntityClass = extractEntityClassFromMapper(annotation.mapper());
|
|
|
+ if (actualEntityClass != null) {
|
|
|
+ log.info("從Mapper泛型中提取到實體類: {}", actualEntityClass.getSimpleName());
|
|
|
+ } else {
|
|
|
+ log.warn("無法從Mapper泛型中提取實體類,使用參數中的實體類");
|
|
|
+ actualEntityClass = entityClass;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("無法從容器中獲取注解指定的Mapper: {}", annotation.mapper().getSimpleName(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果注解中沒有指定Mapper或獲取失敗,則從容器中查找
|
|
|
+ if (mapper == null && applicationContext != null) {
|
|
|
+ if (entityClass == null) {
|
|
|
+ log.warn("未指定Mapper且無法從參數中獲取實體類,無法查詢數據");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根據實體類名推斷Mapper名稱
|
|
|
+ // 例如:EssentialHolidayComparison -> EssentialHolidayComparisonMapper
|
|
|
+ String entityName = entityClass.getSimpleName();
|
|
|
+ String mapperBeanName = entityName.substring(0, 1).toLowerCase() + entityName.substring(1) + "Mapper";
|
|
|
+
|
|
|
try {
|
|
|
// 先嘗試標準命名
|
|
|
- BaseMapper<?> mapper = (BaseMapper<?>) applicationContext.getBean(mapperBeanName);
|
|
|
+ mapper = (BaseMapper<?>) applicationContext.getBean(mapperBeanName);
|
|
|
if (mapper != null) {
|
|
|
- // selectById 需要 Serializable 類型
|
|
|
- Serializable serializableId = convertToSerializable(id);
|
|
|
- if (serializableId != null) {
|
|
|
- Object result = mapper.selectById(serializableId);
|
|
|
- log.info("通過Mapper查詢成功,Mapper: {}, ID: {}", mapperBeanName, id);
|
|
|
- return result;
|
|
|
- }
|
|
|
+ log.info("通過標準命名找到Mapper: {}", mapperBeanName);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
log.debug("無法獲取Mapper: {}", mapperBeanName, e);
|
|
|
}
|
|
|
|
|
|
- // 嘗試查找所有BaseMapper類型的Bean
|
|
|
- try {
|
|
|
- String[] beanNames = applicationContext.getBeanNamesForType(BaseMapper.class);
|
|
|
- for (String beanName : beanNames) {
|
|
|
- try {
|
|
|
- BaseMapper<?> mapper = applicationContext.getBean(beanName, BaseMapper.class);
|
|
|
- // 檢查Mapper的泛型類型是否匹配
|
|
|
- java.lang.reflect.Type[] types = mapper.getClass().getGenericInterfaces();
|
|
|
- for (java.lang.reflect.Type type : types) {
|
|
|
- if (type instanceof java.lang.reflect.ParameterizedType) {
|
|
|
- java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
|
|
|
- if (pt.getRawType().equals(BaseMapper.class)) {
|
|
|
- java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
|
|
|
- if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
|
|
|
- Class<?> mapperEntityClass = (Class<?>) actualTypes[0];
|
|
|
- if (mapperEntityClass.equals(entityClass)) {
|
|
|
- // selectById 需要 Serializable 類型
|
|
|
- Serializable serializableId = convertToSerializable(id);
|
|
|
- if (serializableId != null) {
|
|
|
- Object result = mapper.selectById(serializableId);
|
|
|
- log.info("通過Mapper查詢成功,Mapper: {}, ID: {}", beanName, id);
|
|
|
- return result;
|
|
|
+ // 如果標準命名失敗,嘗試查找所有BaseMapper類型的Bean
|
|
|
+ if (mapper == null) {
|
|
|
+ try {
|
|
|
+ String[] beanNames = applicationContext.getBeanNamesForType(BaseMapper.class);
|
|
|
+ for (String beanName : beanNames) {
|
|
|
+ try {
|
|
|
+ BaseMapper<?> candidateMapper = applicationContext.getBean(beanName, BaseMapper.class);
|
|
|
+ // 檢查Mapper的泛型類型是否匹配
|
|
|
+ java.lang.reflect.Type[] types = candidateMapper.getClass().getGenericInterfaces();
|
|
|
+ for (java.lang.reflect.Type type : types) {
|
|
|
+ if (type instanceof java.lang.reflect.ParameterizedType) {
|
|
|
+ java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
|
|
|
+ if (pt.getRawType().equals(BaseMapper.class)) {
|
|
|
+ java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
|
|
|
+ if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
|
|
|
+ Class<?> mapperEntityClass = (Class<?>) actualTypes[0];
|
|
|
+ if (mapperEntityClass.equals(entityClass)) {
|
|
|
+ mapper = candidateMapper;
|
|
|
+ log.info("通過泛型匹配找到Mapper: {}", beanName);
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ if (mapper != null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 繼續查找下一個
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
- // 繼續查找下一個
|
|
|
}
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.debug("查找Mapper失敗", e);
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
- log.debug("查找Mapper失敗", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- log.warn("無法找到對應的Mapper,實體類: {}, ID: {}", entityClass.getSimpleName(), id);
|
|
|
+ // 使用找到的Mapper查詢數據
|
|
|
+ if (mapper != null) {
|
|
|
+ Serializable serializableId = convertToSerializable(id);
|
|
|
+ if (serializableId != null) {
|
|
|
+ Object result = mapper.selectById(serializableId);
|
|
|
+ log.info("通過Mapper查詢成功,Mapper: {}, 實體類: {}, ID: {}",
|
|
|
+ mapper.getClass().getSimpleName(),
|
|
|
+ actualEntityClass != null ? actualEntityClass.getSimpleName() : "未知",
|
|
|
+ id);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.warn("無法找到對應的Mapper,實體類: {}, ID: {}",
|
|
|
+ actualEntityClass != null ? actualEntityClass.getSimpleName() : "未知", id);
|
|
|
return null;
|
|
|
} catch (Exception e) {
|
|
|
- log.error("查詢修改前的數據失敗,實體類: {}, ID: {}", entityClass.getSimpleName(), id, e);
|
|
|
+ log.error("查詢修改前的數據失敗,實體類: {}, ID: {}",
|
|
|
+ entityClass != null ? entityClass.getSimpleName() : "未知", id, e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 從Mapper類的泛型參數中提取實體類
|
|
|
+ */
|
|
|
+ private Class<?> extractEntityClassFromMapper(Class<? extends BaseMapper> mapperClass) {
|
|
|
+ if (mapperClass == null || mapperClass == BaseMapper.class) {
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 獲取Mapper接口的泛型參數
|
|
|
+ java.lang.reflect.Type[] types = mapperClass.getGenericInterfaces();
|
|
|
+ for (java.lang.reflect.Type type : types) {
|
|
|
+ if (type instanceof java.lang.reflect.ParameterizedType) {
|
|
|
+ java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
|
|
|
+ if (pt.getRawType().equals(BaseMapper.class)) {
|
|
|
+ java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
|
|
|
+ if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
|
|
|
+ return (Class<?>) actualTypes[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果直接繼承的接口沒有泛型,嘗試從父類獲取
|
|
|
+ java.lang.reflect.Type superclass = mapperClass.getGenericSuperclass();
|
|
|
+ if (superclass instanceof java.lang.reflect.ParameterizedType) {
|
|
|
+ java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) superclass;
|
|
|
+ if (pt.getRawType().equals(BaseMapper.class)) {
|
|
|
+ java.lang.reflect.Type[] actualTypes = pt.getActualTypeArguments();
|
|
|
+ if (actualTypes.length > 0 && actualTypes[0] instanceof Class) {
|
|
|
+ return (Class<?>) actualTypes[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("從Mapper類中提取實體類失敗: {}", mapperClass.getSimpleName(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|