From 1fe9433332a9ed00429c54cef2dbbd0a78f72ec1 Mon Sep 17 00:00:00 2001
From: lanyuanxiaoyao
Date: Thu, 11 Sep 2025 10:21:21 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0DDL=E8=AF=AD=E5=8F=A5?=
=?UTF-8?q?=E7=94=9F=E6=88=90=E7=9A=84=E5=B0=8F=E5=B7=A5=E5=85=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 7 ++
.../service/template/util/DDLGenerator.java | 116 ++++++++++++++++++
2 files changed, 123 insertions(+)
create mode 100644 src/main/java/com/lanyuanxiaoyao/service/template/util/DDLGenerator.java
diff --git a/pom.xml b/pom.xml
index 690b6a5..dc4cd5d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,6 +43,13 @@
${querydsl.version}
+
+ org.hibernate.orm
+ hibernate-ant
+ 6.6.15.Final
+ provided
+
+
org.mapstruct
mapstruct
diff --git a/src/main/java/com/lanyuanxiaoyao/service/template/util/DDLGenerator.java b/src/main/java/com/lanyuanxiaoyao/service/template/util/DDLGenerator.java
new file mode 100644
index 0000000..a430142
--- /dev/null
+++ b/src/main/java/com/lanyuanxiaoyao/service/template/util/DDLGenerator.java
@@ -0,0 +1,116 @@
+package com.lanyuanxiaoyao.service.template.util;
+
+import jakarta.persistence.Entity;
+import java.util.EnumSet;
+import java.util.List;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.hibernate.tool.schema.TargetType;
+import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.util.ClassUtils;
+
+/**
+ * 构造DDL建表语句
+ *
+ * 该工具类用于生成数据库表结构的DDL语句,通过扫描指定包下的实体类,
+ * 利用Hibernate的SchemaExport工具生成建表SQL脚本。
+ *
+ *
+ *
+ * 使用示例:
+ *
+ * DDLGenerator.generateDDL(
+ * List.of("com.example.entity", "com.another.package"),
+ * "./sql",
+ * MySQL8Dialect.class,
+ * "jdbc:mysql://localhost:3306/test",
+ * "username",
+ * "password",
+ * com.mysql.cj.jdbc.Driver.class
+ * );
+ *
+ *
+ *
+ * @author lanyuanxiaoyao
+ */
+public class DDLGenerator {
+ public static void generateDDL(
+ List entityPackages,
+ String ddlFilePath,
+ Class> dialect,
+ String jdbc,
+ String username,
+ String password,
+ Class> driver
+ ) {
+ var metadataSources = new MetadataSources(
+ new StandardServiceRegistryBuilder()
+ .applySetting("hibernate.dialect", dialect.getName())
+ .applySetting("hibernate.physical_naming_strategy", CamelCaseToUnderscoresNamingStrategy.class.getName())
+ .applySetting("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName())
+ .applySetting("hibernate.connection.url", jdbc)
+ .applySetting("hibernate.connection.username", username)
+ .applySetting("hibernate.connection.password", password)
+ .applySetting("hibernate.connection.driver_class", driver.getName())
+ .build()
+ );
+
+ // 使用Spring类路径扫描方式查找所有@Entity注解的类
+ var scanner = new ClassPathScanningCandidateComponentProvider(false);
+ scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
+
+ // 遍历所有包路径,扫描@Entity注解的类
+ for (String entityPackage : entityPackages) {
+ var candidates = scanner.findCandidateComponents(entityPackage);
+
+ // 将找到的实体类添加到metadataSources中
+ for (var candidate : candidates) {
+ // 处理candidate或getBeanClassName可能为null的情况
+ if (candidate == null || candidate.getBeanClassName() == null) {
+ continue;
+ }
+
+ try {
+ var entityClass = ClassUtils.forName(candidate.getBeanClassName(), DDLGenerator.class.getClassLoader());
+ metadataSources.addAnnotatedClass(entityClass);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Failed to load entity class: " + candidate.getBeanClassName(), e);
+ }
+ }
+ }
+
+ var export = new SchemaExport();
+ export.setFormat(true);
+ export.setDelimiter(";");
+ export.setOutputFile(ddlFilePath + "/" + dialect.getSimpleName() + ".sql");
+ export.setOverrideOutputFileContent();
+ export.execute(EnumSet.of(TargetType.SCRIPT), SchemaExport.Action.CREATE, metadataSources.buildMetadata());
+ }
+
+ /**
+ * 兼容旧版本的方法签名
+ *
+ * @param entityPackage 实体类包路径
+ * @param ddlFilePath DDL文件输出路径
+ * @param dialect 方言类
+ * @param jdbc JDBC连接URL
+ * @param username 数据库用户名
+ * @param password 数据库密码
+ * @param driver JDBC驱动类
+ */
+ public static void generateDDL(
+ String entityPackage,
+ String ddlFilePath,
+ Class> dialect,
+ String jdbc,
+ String username,
+ String password,
+ Class> driver
+ ) {
+ generateDDL(List.of(entityPackage), ddlFilePath, dialect, jdbc, username, password, driver);
+ }
+}
\ No newline at end of file