package com.xxx.xxxx.utils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cqcloud.platform.entity.SysPaymentInfo;
import cn.hutool.core.lang.Console;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 根据实体创建表sql语句
* @author weimeilayer@gmail.com ✨
* @date 💓💕 2024年8月6日 🐬🐇 💓💕
*/
public class SqlGenerator {
public static String createTableSql(Class<?> clazz) {
// 检查类是否包含 @TableName 注解
if (!clazz.isAnnotationPresent(TableName.class)) {
throw new IllegalArgumentException("The class must be annotated with @TableName");
}
// 初始化 StringBuilder 来构建 SQL 语句
StringBuilder sql = new StringBuilder();
TableName tableNameAnnotation = clazz.getAnnotation(TableName.class);
String tableName = tableNameAnnotation.value();
// 获取类级别的 @Schema 注解
Schema classSchema = clazz.getAnnotation(Schema.class);
String tableComment = (classSchema != null) ? classSchema.description() : clazz.getSimpleName();
// 构建 SQL 语句的初始部分
sql.append("drop table if exists ").append(tableName).append(" cascade;\n");
sql.append("create table ").append(tableName).append(" (\n");
// 获取类的所有字段
Field[] fields = clazz.getDeclaredFields();
String primaryKey = null;
Map<String, String> columnComments = new HashMap<>();
// 遍历每个字段
for (Field field : fields) {
// 跳过 serialVersionUID 字段
if (field.getName().equals("serialVersionUID")) {
continue;
}
// 跳过被 @TableField 注解并且 exist 属性为 false 的字段
if (field.isAnnotationPresent(TableField.class) && field.getAnnotation(TableField.class).exist() == false) {
continue;
}
// 初始化列名和列类型
String columnName;
String columnType = null;
// 检查字段是否被 @TableId 注解
if (field.isAnnotationPresent(TableId.class)) {
TableId tableId = field.getAnnotation(TableId.class);
columnName = tableId.value();
if (tableId.type() == IdType.ASSIGN_ID) {
primaryKey = columnName;
}
} else {
TableField tableField = field.getAnnotation(TableField.class);
columnName = (tableField != null && !tableField.value().isEmpty()) ? tableField.value() : field.getName();
}
// 将列名从驼峰命名转换为下划线命名
columnName = convertToUnderscore(columnName);
// 根据字段类型设置列类型
Class<?> fieldType = field.getType();
if (fieldType == String.class) {
columnType = "varchar(255)";
} else if (fieldType == int.class || fieldType == Integer.class) {
columnType = "integer";
} else if (fieldType == long.class || fieldType == Long.class) {
columnType = "bigint";
} else if (fieldType == double.class || fieldType == Double.class) {
columnType = "double precision";
} else if (fieldType == BigDecimal.class) {
columnType = "numeric(19, 2)";
} else if (fieldType == boolean.class || fieldType == Boolean.class) {
columnType = "boolean";
} else if (fieldType == LocalDateTime.class) {
columnType = "timestamp";
}
// 处理 @Schema 注解以获取列注释
if (field.isAnnotationPresent(Schema.class)) {
Schema schema = field.getAnnotation(Schema.class);
columnComments.put(columnName, schema.description());
}
// 构建列定义部分的 SQL 语句
sql.append(" ").append(columnName).append(" ").append(columnType);
// 如果字段被 @TableId 注解,设置为主键
if (field.isAnnotationPresent(TableId.class)) {
sql.append(" primary key");
}
// 处理 @TableField 注解以设置默认值
if (field.isAnnotationPresent(TableField.class)) {
TableField tableField = field.getAnnotation(TableField.class);
if (tableField.fill() == FieldFill.INSERT || tableField.fill() == FieldFill.UPDATE) {
sql.append(" default current_timestamp");
}
}
// 添加列定义的结尾部分
sql.append(",\n");
}
// 删除最后一个逗号并完成 SQL 语句
sql.setLength(sql.length() - 2); // Remove the last comma
sql.append("\n);\n");
// 添加表和列的注释
sql.append("comment on table \"public\".\"").append(tableName).append("\" IS '").append(tableComment).append("';\n");
if (!columnComments.isEmpty()) {
columnComments.forEach((columnName, comment) -> {
sql.append("comment on column ").append(tableName).append(".").append(columnName)
.append(" IS '").append(comment).append("';\n");
});
}
// 打印 SQL 语句
Console.log(sql);
return sql.toString();
}
// 辅助方法:将驼峰命名转换为下划线命名
private static String convertToUnderscore(String camelCase) {
StringBuilder result = new StringBuilder();
for (char c : camelCase.toCharArray()) {
if (Character.isUpperCase(c)) {
result.append('_').append(Character.toLowerCase(c));
} else {
result.append(c);
}
}
return result.toString();
}
// 执行调用方法
public static void main(String[] args) {
createTableSql(SysPaymentInfo.class);
}
}
运行结果
实体案例