两种常用的数据初始化方式
这里只讨论两种最基本、最常用的数据初始化方式,即:
- Spring JDBC 的 DataSource Initializer
应用启动时,执行 classpath 下的 schema.sql 和 data.sql - JPA/Hibernate 的 ddl-auto
配置spring.jpa.hibernate.ddl-auto : create-drop
,在应用启动时,自动根据 Entity 生成表,并且执行 classpath 下的 import.sql
关于数据初始化详细资料,参考:spring-boot-reference#How-to guides#Database initialization
空的 schema.sql 文件
在使用 JDBC DataSource Initializer 初始化数据时,如果只提供了 data.sql 没提供 schema.sql ,那么 data.sql 脚本不会执行。
根据 stackoverflow 网友的回答,需要提供一个空的 schema.sql 文件,经测试 - 报错。
最后,在空的 schema.sql 文件中写入一个 ;
符号,解决了
JDBC DataSource Initializer 和 JPA ddl-auto 的执行顺序问题
注意1:讨论的前提是 ddl-auto 的值为 create-drop
注意2:ddl-auto = create-drop 只适合在开发环境中使用,此处讨论的顺序问题也是在开发环境中发现的。
- JPA ddl-auto 早于 JDBC DataSource Initializer 执行(正常情况)
应用启动时整个流程为:drop table if exists -> create table -> 执行 data.sql -
JDBC DataSource Initializer 早于 JPA ddl-auto 执行(非正常情况,偶遇)
应用启动时整个流程为:执行 data.sql -> drop table if exists -> create table
注意:执行 data.sql 很容易导致 table doesn't exist 错误
导致上述执行顺序问题的原因是什么??????如何解决???
另一个疑问:在 spring-boot-reference#Spring Boot features#Working with SQL databases#JPA and Spring Data#Creating and dropping JPA databases 一节中有这样一句话:
By default the DDL execution (or validation) is deferred until the ApplicationContext has started.
并存 => 互斥 (JDBC DataSource Initializer & JPA ddl-auto)
只有在同时使用 JDBC DataSource Initializer & JPA ddl-auto 两种数据初始化方式时,才会导致上述的执行顺序问题!
偶然间发现 spring-boot 的一个 commit,更新了数据初始化相关的文档内容,我是这么理解的:
将来,JDBC DataSource Initializer & JPA ddl-auto 是互斥的,建议二选一,当然还有更高级的方式,比如
Liquibase
参考资料
- spring-boot-reference
- Spring Boot running data.sql before creating entities in presence of schema.sql