springboot启动初始化ddl过程
跟踪Springboot整合hibernate的启动代码:
SessionFactoryImpl 的初始化里做了非常多的事情,初始化各种资源,并调用 SchemaManagementToolCoordinator.process 先执行脚本任务再执行 Db任务:
performScriptAction( actions.getScriptAction(), metadata, tool, serviceRegistry, executionOptions, configService );
performDatabaseAction( actions.getDatabaseAction(), metadata, tool, serviceRegistry, executionOptions );
在这里就开始进行 spring.jpa.hibernate.ddl-auto 配置的项,进行处理了。
在 doMigration 时,就获取到 tables 的元数据:
public class GroupedSchemaMigratorImpl extends AbstractSchemaMigrator {
public GroupedSchemaMigratorImpl(HibernateSchemaManagementTool tool, SchemaFilter schemaFilter) {
super(tool, schemaFilter);
}
protected NameSpaceTablesInformation performTablesMigration(Metadata metadata, DatabaseInformation existingDatabase, ExecutionOptions options, Dialect dialect, Formatter formatter, Set<String> exportIdentifiers, boolean tryToCreateCatalogs, boolean tryToCreateSchemas, Set<Identifier> exportedCatalogs, Namespace namespace, GenerationTarget[] targets) {
NameSpaceTablesInformation tablesInformation = new NameSpaceTablesInformation(metadata.getDatabase().getJdbcEnvironment().getIdentifierHelper());
if (this.schemaFilter.includeNamespace(namespace)) {
this.createSchemaAndCatalog(existingDatabase, options, dialect, formatter, tryToCreateCatalogs, tryToCreateSchemas, exportedCatalogs, namespace, targets);
NameSpaceTablesInformation tables = existingDatabase.getTablesInformation(namespace);
Iterator var14 = namespace.getTables().iterator();
Table table;
TableInformation tableInformation;
while(var14.hasNext()) {
table = (Table)var14.next();
if (this.schemaFilter.includeTable(table) && table.isPhysicalTable()) {
this.checkExportIdentifier(table, exportIdentifiers);
tableInformation = tables.getTableInformation(table);
if (tableInformation == null) {
this.createTable(table, dialect, metadata, formatter, options, targets);
} else if (tableInformation != null && tableInformation.isPhysicalTable()) {
tablesInformation.addTableInformation(tableInformation);
this.migrateTable(table, tableInformation, dialect, metadata, formatter, options, targets);
}
}
}
var14 = namespace.getTables().iterator();
while(true) {
do {
do {
do {
if (!var14.hasNext()) {
return tablesInformation;
}
table = (Table)var14.next();
} while(!this.schemaFilter.includeTable(table));
} while(!table.isPhysicalTable());
tableInformation = tablesInformation.getTableInformation(table);
} while(tableInformation != null && (tableInformation == null || !tableInformation.isPhysicalTable()));
this.applyIndexes(table, tableInformation, dialect, metadata, formatter, options, targets);
this.applyUniqueKeys(table, tableInformation, dialect, metadata, formatter, options, targets);
}
} else {
return tablesInformation;
}
}
}
如何自定义修改 table
再往下的过程,到 HibernateSchemaManagementTool 这个核心类:
ddl-auto 语义的实现,就在这里。
那要自定义修改 table ,最常见的需要就是 hibernate 只能增加,对于修改字段长度这一类的涉及不到。当然这种修改只限于开发技术交流,生产环境慎用。
回归正题,要想修改字段长度有这么几个关键数据:
- table 的元数据
- Entity 的元数据
hibernate 本身的功能,如 Migrator 既然能识别到字段缺失,那肯定也能获取到这2个元数据。也就是2个参数:registry 和 metadata。
了解了需要的数据,就有了思路:
public void migrateDB(DataSourceProperties dataSource, EntityManager entityManager, String ddlAuto, String dialectStr) {
log.