实现上述功能需要注解进行协助
@Aspect
@Component
public class SqlLoggingAspect {
@Around("execution(* javax.sql.DataSource.getConnection(..))")
@Order
public Object aroundGetConnection(ProceedingJoinPoint joinPoint) throws Throwable {
try {
HttpServletRequest httpServletRequest = RequestUtil.GetRequest();
if (httpServletRequest != null) {//每次只会获取一次session
Callable<Connection> callable = () -> {
PreparedStatementHandler.threadLocalVariable = new ThreadLocal<>();
try {
return (Connection) joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
return createProxy(callable);
}
} catch (Exception e) {
}
return joinPoint.proceed();
}
public Object createProxy(Callable<Connection> callable) throws Exception {
Connection connection = callable.call();
return Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class[]{Connection.class},
new SqlLoggingHandler(connection)
);
}
}
public class SqlLoggingHandler implements InvocationHandler {
private final Connection realConnection;
public SqlLoggingHandler(Connection realConnection) {
this.realConnection = realConnection;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("prepareStatement".equals(method.getName())) {
PreparedStatement preparedStatement = (PreparedStatement) method.invoke(realConnection, args);
return Proxy.newProxyInstance(
preparedStatement.getClass().getClassLoader(),
preparedStatement.getClass().getInterfaces(),
new PreparedStatementHandler(preparedStatement)
);
} else {
return method.invoke(realConnection, args);
}
}
}
public class PreparedStatementHandler implements InvocationHandler {
private final PreparedStatement realPreparedStatement;
private ArrayList<Object> parameters = new ArrayList<>();
public static ThreadLocal<List<HashMap<String, Object>>> threadLocalVariable = new ThreadLocal<>();
public static ThreadLocal<String> threadLocalId = new ThreadLocal<>();
public PreparedStatementHandler(PreparedStatement realPreparedStatement) {
this.realPreparedStatement = realPreparedStatement;
}
private static Map<String, String> extractKeyValuePairs(Expression expression) {
Map<String, String> keyValuePairs = new HashMap<>();
if (expression instanceof BinaryExpression) {
BinaryExpression binaryExpression = (BinaryExpression) expression;
if (binaryExpression.getLeftExpression() instanceof Column && binaryExpression.getRightExpression() instanceof StringValue) {
Column column = (Column) binaryExpression.getLeftExpression();
StringValue stringValue = (StringValue) binaryExpression.getRightExpression();
keyValuePairs.put(column.getColumnName(), stringValue.getValue());
} else if (binaryExpression.getLeftExpression() instanceof BinaryExpression) {
keyValuePairs.putAll(extractKeyValuePairs(binaryExpression.getLeftExpression()));
} else if (binaryExpression.getRightExpression() instanceof BinaryExpression) {
keyValuePairs.putAll(extractKeyValuePairs(binaryExpression.getRightExpression()));
}
} else if (expression instanceof AndExpression) {
AndExpression andOrExpression = (AndExpression) expression;
keyValuePairs.putAll(extractKeyValuePairs(andOrExpression.getLeftExpression()));
keyValuePairs.putAll(extractKeyValuePairs(andOrExpression.getRightExpression()));
} else if (expression instanceof OrExpression) {
OrExpression andOrExpression = (OrExpression) expression;
keyValuePairs.putAll(extractKeyValuePairs(andOrExpression.getLeftExpression()));
keyValuePairs.putAll(extractKeyValuePairs(andOrExpression.getRightExpression()));
}
return keyValuePairs;
}
public static String findMainTableName(List<HashMap<String, Object>> hashMaps) {
HashMap<String, Integer> weightHashMap = new HashMap<>();
String mainTableName = "";
Integer max = 0;
for (HashMap<String, Object> hashMap : hashMaps) {
Map<String, Object> stringObjectMap = TypeConvert.FromMapJson(TypeConvert.ToString(hashMap.get("whereSets")));
if (stringObjectMap != null && stringObjectMap.containsKey(BaseModel.F_id.toUpperCase())) {//是否有id
String tableName = TypeConvert.ToString(hashMap.get("tableName"));
if (weightHashMap.containsKey(tableName)) {
Integer tableWidght = weightHashMap.get("tableName");
weightHashMap.put(tableName, tableWidght + 1);
} else {
weightHashMap.put(tableName, 1);
}
if (weightHashMap.get(tableName) > max) {
mainTableName = tableName;
max = weightHashMap.get(tableName);
}
}
}
for (HashMap<String, Object> hashMap : hashMaps) {
String tableName = TypeConvert.ToString(hashMap.get("tableName"));
Class<BaseModel> baseModelClass = SqlCache.GetClassByTableName(tableName);
if (baseModelClass != null) {
Field[] declaredFields = baseModelClass.getDeclaredFields();
Map<String, Object> whereMap = TypeConvert.FromMapJson(TypeConvert.ToString(hashMap.get("whereSets")));
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(XColumn.class)) {
XColumn annotation = declaredField.getAnnotation(XColumn.class);
if (annotation != null) {
if (StrUtil.isNotEmpty(annotation.foreignTable()) && whereMap.containsKey(declaredField.getName().toUpperCase())) {
if (weightHashMap.containsKey(annotation.foreignTable())) {
weightHashMap.compute(annotation.foreignTable(), (k, tableWidght) -> tableWidght + 1);
if (weightHashMap.get(annotation.foreignTable()) > max) {
mainTableName = annotation.foreignTable();
max = weightHashMap.get(annotation.foreignTable());
}
}
}
}
}
}
}
}
return mainTableName;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HashMap<String, Object> objMap = new HashMap<>();
boolean isSave = false;
if (threadLocalVariable.get() == null) {
threadLocalVariable.set(new ArrayList<>());
threadLocalId.set(BaseModel.GetUniqueId());
}
if (method.getName().startsWith("set")) {
parameters.add(args[1]);
} else if ("executeQuery".equals(method.getName()) || "executeUpdate".equals(method.getName()) || "executeBatch".equals(method.getName())) {
String sql = realPreparedStatement.toString(); // 默认SQL没有参数
try {
sql = realPreparedStatement.unwrap(PreparedStatement.class).toString();
} catch (SQLException e) {
// Ignore
}
objMap.put("sql", sql);
for (int i = 0; i < parameters.size(); i++) {
sql = sql.replaceFirst("\\?", parameters.get(i).toString());
}
objMap.put("param", parameters);
objMap.put("paramSql", sql);//sql param
if (!sql.toUpperCase().contains(SCLS删除历史.F_TableName)) {
if (sql.toUpperCase().split(":")[1].trim().matches("(DELETE).*")) {
Statement parse = CCJSqlParserUtil.parse(sql.toUpperCase().split(":", 2)[1].trim());
if (parse instanceof Delete) {
isSave = true;
Delete delete = (Delete) parse;
Map<String, String> retMap = extractKeyValuePairs(delete.getWhere());
objMap.put("tableName", delete.getTable().getName());
objMap.put("type", "delete");//更新内容
objMap.put("whereSets", TypeConvert.ToJson(retMap));
String selectSql = sql.toUpperCase().split(":")[1].trim().replaceFirst("DELETE", "SELECT *");
final List<Map<String, Object>> query = new ArrayList<>();
DBSession.GetSession().doWork(db -> {
List<Map<String, Object>> _query = new QueryRunner().query(db.getOrOpenConnection(), selectSql, new SqlListHandler(), db.handleSqlParams(new Object[]{}));
query.addAll(_query);
});
objMap.put("oriObjects", TypeConvert.ToJson(query));
}
} else if (sql.toUpperCase().split(":", 2)[1].trim().matches("(UPDATE).*")) {
Statement parse = CCJSqlParserUtil.parse(sql.toUpperCase().split(":", 2)[1].trim());
if (parse instanceof Update) {
isSave = true;
Update update = (Update) parse;
objMap.put("tableName", update.getTable().getName());//获取表名
if (StrUtil.isNotEqual(update.getTable().getName(), SCLS删除历史.F_TableName)) {
for (HashMap<String, Object> retMap : threadLocalVariable.get()) {
if (StrUtil.isEqual(TypeConvert.ToString(retMap.get("type")), "update")
&& StrUtil.isEqual(TypeConvert.ToString(retMap.get("tableName")), update.getTable().getName())
&& StrUtil.isEqual(TypeConvert.ToString(retMap.get("oriObjects")), TypeConvert.ToJson(update.getUpdateSets()))) {
isSave = false;
}
}
if (isSave) {
objMap.put("updateSets", TypeConvert.ToJson(update.getUpdateSets()));//更新内容
objMap.put("type", "update");//更新内容
Class<BaseModel> baseModelClass = SqlCache.GetClassByTableName(update.getTable().getName());
if (baseModelClass != null) {
Map<String, String> retMap = extractKeyValuePairs(update.getWhere());
objMap.put("whereSets", TypeConvert.ToJson(retMap));
String selectSql = "SELECT * FROM " + update.getTable().getName() + " WHERE " + update.getWhere();
final List<Map<String, Object>> query = new ArrayList<>();
DBSession.GetSession().doWork(db -> {
List<Map<String, Object>> _query = new QueryRunner().query(db.getOrOpenConnection(), selectSql, new SqlListHandler(), db.handleSqlParams(new Object[]{}));
query.addAll(_query);
});
objMap.put("oriObjects", TypeConvert.ToJson(query));
}
}
} else {
isSave = false;
}
}
}
}
if (isSave) {//
List<HashMap<String, Object>> hashMaps = threadLocalVariable.get();
hashMaps.add(objMap);
threadLocalVariable.set(hashMaps);
SCLS删除历史 scls删除历史 = new SCLS删除历史();
scls删除历史.id = threadLocalId.get();
scls删除历史.删除内容 = TypeConvert.ToJson(hashMaps);
scls删除历史.删除时间 = new Date();
scls删除历史.主表名 = findMainTableName(hashMaps);
if (GlobalValues.GetSessionUser() != null) {
scls删除历史.删除人员id = GlobalValues.GetSessionUser().id;
}
scls删除历史.Save();
}
parameters.clear();
}
return method.invoke(realPreparedStatement, args);
}
}
@RequestMapping(value = "/rollback", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
@ResponseBody
public String rollback(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception {
String id = RequestUtil.GetString(request, BaseModel.F_id);
SCLS删除历史 scls删除历史 = SCLS删除历史.GetObjectById(SCLS删除历史.class, id);
String error_msg = "";
if (scls删除历史 != null) {
List<Map<String, Object>> maps = TypeConvert.FromListMapJson(scls删除历史.删除内容);
for (Map<String, Object> map : maps) {
String tableName = TypeConvert.ToString(map.get("tableName"));
String oriObjectsJson = TypeConvert.ToString(map.get("oriObjects"));
if (StrUtil.isNotEmpty(tableName) && StrUtil.isNotEmpty(oriObjectsJson)) {
List<Map<String, Object>> objMapS = TypeConvert.FromListMapJson(oriObjectsJson);
Class<BaseModel> baseModelClass = SqlCache.GetClassByTableName(tableName);
if (baseModelClass != null) {
for (Map<String, Object> objMap : objMapS) {
BaseModel baseModel = baseModelClass.newInstance();
baseModel.SetValuesByMap(objMap);
baseModel.Save();
}
scls删除历史.Delete();
return AjaxResult.True("恢复成功").ToJson();
} else {
error_msg = tableName + "字节码文件不存在";
}
} else {
error_msg = "tableName或oriObjects为空";
}
}
}
return AjaxResult.False("恢复失败:" + error_msg).ToJson();
}