All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.github.dengchen2020.core.utils.SqlMetaUtils Maven / Gradle / Ivy
package io.github.dengchen2020.core.utils;
import jakarta.persistence.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
/**
* sql元数据解析工具类
* @author dengchen
* @since 2024/6/22
*/
public abstract class SqlMetaUtils {
private static final Logger log = LoggerFactory.getLogger(SqlMetaUtils.class);
private static final ConcurrentMap tableInfoCache = new ConcurrentReferenceHashMap<>();
public static class TableInfo {
private String tableName;
private String schema = "";
private List columns = new ArrayList<>();
private String idColumn;
private Method getIdMethod;
private Method getVersionMethod;
private Method prePersisit;
private Method postPersisit;
private Method preUpdate;
private Method postUpdate;
private Method preRemove;
private Method postRemove;
private Method postLoad;
private String selectAllSql;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public List getColumns() {
return columns;
}
public void setColumns(List column) {
this.columns = column;
}
public String getIdColumn() {
return idColumn;
}
public void setIdColumn(String idColumn) {
this.idColumn = idColumn;
}
public Method getGetIdMethod() {
return getIdMethod;
}
public void setGetIdMethod(Method getIdMethod) {
this.getIdMethod = getIdMethod;
}
public Method getGetVersionMethod() {
return getVersionMethod;
}
public void setGetVersionMethod(Method getVersionMethod) {
this.getVersionMethod = getVersionMethod;
}
public Method getPrePersisit() {
return prePersisit;
}
public void setPrePersisit(Method prePersisit) {
this.prePersisit = prePersisit;
}
public Method getPostPersisit() {
return postPersisit;
}
public void setPostPersisit(Method postPersisit) {
this.postPersisit = postPersisit;
}
public Method getPreUpdate() {
return preUpdate;
}
public void setPreUpdate(Method preUpdate) {
this.preUpdate = preUpdate;
}
public Method getPostUpdate() {
return postUpdate;
}
public void setPostUpdate(Method postUpdate) {
this.postUpdate = postUpdate;
}
public Method getPreRemove() {
return preRemove;
}
public void setPreRemove(Method preRemove) {
this.preRemove = preRemove;
}
public Method getPostRemove() {
return postRemove;
}
public void setPostRemove(Method postRemove) {
this.postRemove = postRemove;
}
public Method getPostLoad() {
return postLoad;
}
public void setPostLoad(Method postLoad) {
this.postLoad = postLoad;
}
public String getSelectAllSql() {
return selectAllSql;
}
public void setSelectAllSql(String selectAllSql) {
this.selectAllSql = selectAllSql;
}
}
/**
* 添加父类方法
*/
public static void addSuperMethods(Class entityClass, List methods) {
if (entityClass.getSuperclass() != null) {
addSuperMethods(entityClass.getSuperclass(), methods);
}
if (entityClass.getAnnotation(MappedSuperclass.class) != null) {
methods.addAll(new ArrayList<>(Arrays.asList(ReflectionUtils.getDeclaredMethods(entityClass))));
}
}
/**
* 添加父类字段
*/
public static void addSuperFields(Class entityClass, List fields) {
if (entityClass.getSuperclass() != null) {
addSuperFields(entityClass.getSuperclass(), fields);
}
if (entityClass.getAnnotation(MappedSuperclass.class) != null) {
fields.addAll(new ArrayList<>(Arrays.asList(entityClass.getDeclaredFields())));
}
}
/**
* 保存回调函数
*/
private static void saveCallbackMethod(Method method, TableInfo tableInfo) {
if (tableInfo.getPrePersisit() == null && method.getAnnotation(PrePersist.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPrePersisit(method);
}
if (tableInfo.getPostPersisit() == null && method.getAnnotation(PostPersist.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPostPersisit(method);
}
if (tableInfo.getPreUpdate() == null && method.getAnnotation(PreUpdate.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPreUpdate(method);
}
if (tableInfo.getPostUpdate() == null && method.getAnnotation(PostUpdate.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPostUpdate(method);
}
if (tableInfo.getPreRemove() == null && method.getAnnotation(PreRemove.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPreRemove(method);
}
if (tableInfo.getPostRemove() == null && method.getAnnotation(PostRemove.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPostRemove(method);
}
if (tableInfo.getPostLoad() == null && method.getAnnotation(PostLoad.class) != null) {
ReflectionUtils.makeAccessible(method);
tableInfo.setPostLoad(method);
}
}
/**
* 解析@Column指定的字段名
*
* @return 字段名
*/
private static String getColumnName(Field field) {
Column column = field.getAnnotation(Column.class);
if (column == null || !StringUtils.hasText(column.name())) {
return convertToSnakeCase(field.getName());
}
return column.name();
}
/**
* 转化成蛇形下划线命名格式
*
* @param name 原字段名
* @return 新字段名
*/
public static String convertToSnakeCase(String name) {
StringBuilder result = new StringBuilder();
for (int i = 0,len = name.length(); i < len; i++) {
char c = name.charAt(i);
if (Character.isUpperCase(c) && i > 0) {
result.append("_");
}
result.append(Character.toLowerCase(c));
}
return result.toString();
}
public static TableInfo init(Class entityClass) {
String entityName = entityClass.getName();
return tableInfoCache.computeIfAbsent(entityName, key -> {
TableInfo tableInfo = new TableInfo();
Table table = entityClass.getAnnotation(Table.class);
if (table == null) {
tableInfo.setTableName(convertToSnakeCase(key));
} else {
tableInfo.setTableName(table.name());
tableInfo.setSchema(table.schema());
}
List methods = new ArrayList<>();
addSuperMethods(entityClass, methods);
methods.addAll(new ArrayList<>(Arrays.asList(ReflectionUtils.getDeclaredMethods(entityClass))));
List fields = new ArrayList<>();
addSuperFields(entityClass, fields);
fields.addAll(new ArrayList<>(Arrays.asList(entityClass.getDeclaredFields())));
String idFieldName = null;
String versionFieldName = null;
for (Field field : fields) {
if(!Modifier.isStatic(field.getModifiers()) && field.getAnnotation(Transient.class) == null){
tableInfo.getColumns().add(getColumnName(field));
}
if (idFieldName == null && field.getAnnotation(Id.class) != null) {
idFieldName = field.getName();
Column column = field.getAnnotation(Column.class);
if(column != null && StringUtils.hasText(column.name())){
tableInfo.setIdColumn(column.name());
}else {
tableInfo.setIdColumn(convertToSnakeCase(idFieldName));
}
}
if (versionFieldName == null && field.getAnnotation(Version.class) != null) {
versionFieldName = field.getName();
}
}
tableInfo.setSelectAllSql(String.join(",",tableInfo.getColumns()));
String getIdMethodName = getMethodName(idFieldName);
String getVersionMethodName = getMethodName(versionFieldName);
boolean getId = true;
boolean getVersion = true;
for (Method method : methods) {
saveCallbackMethod(method, tableInfo);
if (getId && getIdMethodName != null) {
if (method.getName().equals(getIdMethodName) && method.getParameterCount() == 0 && method.getReturnType() != Void.class) {
ReflectionUtils.makeAccessible(method);
getId = false;
tableInfo.setGetIdMethod(method);
}
if (getId) {
if (method.getName().equals(idFieldName) && method.getParameterCount() == 0 && method.getReturnType() != Void.class) {
ReflectionUtils.makeAccessible(method);
getId = false;
tableInfo.setGetIdMethod(method);
}
}
}
if (getVersion && getVersionMethodName != null) {
if (method.getName().equals(getVersionMethodName) && method.getParameterCount() == 0 && method.getReturnType() != Void.class) {
ReflectionUtils.makeAccessible(method);
getVersion = false;
tableInfo.setGetVersionMethod(method);
}
if (getVersion) {
if (method.getName().equals(versionFieldName) && method.getParameterCount() == 0 && method.getReturnType() != Void.class) {
ReflectionUtils.makeAccessible(method);
getVersion = false;
tableInfo.setGetVersionMethod(method);
}
}
}
}
return tableInfo;
});
}
private static String getMethodName(String fieldName) {
if (fieldName != null) {
if (fieldName.length() > 1) {
return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
} else {
return "get" + fieldName.toUpperCase();
}
}
return null;
}
public static boolean isNew(T entity) {
String entityClassName = entity.getClass().getName();
TableInfo tableInfo = tableInfoCache.get(entityClassName);
Method getIdMethod = tableInfo.getGetIdMethod();
Method getVersionMethod = tableInfo.getGetVersionMethod();
if (getIdMethod != null) {
return ReflectionUtils.invokeMethod(getIdMethod, entity) == null || (getVersionMethod != null && ReflectionUtils.invokeMethod(getVersionMethod, entity) == null);
}
return false;
}
public static void onBeforeConvert(T entity) {
String entityClassName = entity.getClass().getName();
TableInfo tableInfo = tableInfoCache.get(entityClassName);
if(tableInfo.getPrePersisit() == null && tableInfo.getPreUpdate() == null){
return;
}
Method getIdMethod = tableInfo.getGetIdMethod();
Method getVersionMethod = tableInfo.getGetVersionMethod();
if (getIdMethod != null) {
Object id = ReflectionUtils.invokeMethod(getIdMethod, entity);
if (id != null && (getVersionMethod == null || ReflectionUtils.invokeMethod(getVersionMethod, entity) != null)) {
Method preUpdate = tableInfo.getPreUpdate();
if (preUpdate != null) {
if (log.isDebugEnabled())
log.debug("onBeforeConvert forward to {} @preUpdate method", entity.getClass().getName());
ReflectionUtils.invokeMethod(preUpdate, entity);
}
} else {
Method prePersist = tableInfo.getPrePersisit();
if (prePersist != null) {
if (log.isDebugEnabled())
log.debug("onBeforeConvert forward to {} @prePersist method", entity.getClass().getName());
ReflectionUtils.invokeMethod(prePersist, entity);
}
}
}
}
public static void onAfterConvert(T entity) {
String entityClassName = entity.getClass().getName();
TableInfo tableInfo = tableInfoCache.get(entityClassName);
if(tableInfo.getPostPersisit() == null && tableInfo.getPostUpdate() == null){
return;
}
Method getIdMethod = tableInfo.getGetIdMethod();
Method getVersionMethod = tableInfo.getGetVersionMethod();
if (getIdMethod != null) {
Object id = ReflectionUtils.invokeMethod(getIdMethod, entity);
if (id != null && (getVersionMethod == null || ReflectionUtils.invokeMethod(getVersionMethod, entity) != null)) {
Method postUpdate = tableInfo.getPostUpdate();
if (postUpdate != null) {
if (log.isDebugEnabled())
log.debug("onAfterConvert forward to {} @postUpdate method", entity.getClass().getName());
ReflectionUtils.invokeMethod(postUpdate, entity);
}
} else {
Method postPersist = tableInfo.getPostPersisit();
if (postPersist != null) {
if (log.isDebugEnabled())
log.debug("onAfterConvert forward to {} @postPersist method", entity.getClass().getName());
ReflectionUtils.invokeMethod(postPersist, entity);
}
}
}
}
public static void onBeforeDelete(T entity) {
String entityClassName = entity.getClass().getName();
TableInfo tableInfo = tableInfoCache.get(entityClassName);
Method preRemove = tableInfo.getPreRemove();
if (preRemove != null) {
if (log.isDebugEnabled())
log.debug("onBeforeDelete forward to {} @preRemove method", entity.getClass().getName());
ReflectionUtils.invokeMethod(preRemove, entity);
}
}
public static void onAfterDelete(T entity) {
String entityClassName = entity.getClass().getName();
TableInfo tableInfo = tableInfoCache.get(entityClassName);
Method postRemove = tableInfo.getPostRemove();
if (postRemove != null) {
if (log.isDebugEnabled())
log.debug("onAfterDelete forward to {} @postRemove method", entity.getClass().getName());
ReflectionUtils.invokeMethod(postRemove, entity);
}
}
}