的Bonjour,
我正在努力将Java应用程序从使用postgres改为嵌入式数据库。我希望应用程序使用数据库中的初始数据集进行部署。在安装过程中,我已经执行了一个sql脚本来完全生成模式并将数据插入到我的表中。
理想情况下(因为我真的不想弄清楚如何连接到嵌入式数据库来生成它)我想让JPA第一次创建我的模式,当它发生时我想成为能够运行我的SQL来插入数据。
我的搜索已经显示了允许运行SQL脚本的明显的hibernate和JPA属性。
首先我发现使用" hibernate.hbm2ddl.auto"你可以定义一个import.sql文件,这让我很高兴一天,直到我意识到它只适用于创建而不是更新。我在使用postgres时的应用程序已将此设置更新。我真正想要的是它知道它是否必须创建模式,如果它已经运行了import.sql。虽然没有喜悦。
然后我继续使用" javax.persistence.schema-generation.database.action"设置为"创建"我认为使用JPA规范可能更明智,所以我定义了" javax.persistence.sql-load-script-source"规范说"创建"
提供程序将在应用程序上创建数据库工件 部署。应用后,工件将保持不变 重新部署。
这让我相信它会完全符合我的要求,只会在应用程序部署时创建表格#34;但是当我使用它运行我的测试时,每次测试(创建一个新的弹簧上下文)都试图再次创建所有表并且显然失败了,这让我意识到应用程序部署并不意味着我认为它意味着什么(一厢情愿的想法) )现在我意识到JPA似乎甚至没有相当于Hibernates" update"属性,所以总是要生成表格?
我想要的是在你第一次启动应用程序时生成我的表和数据,并且为了后续执行而知道数据是否存在并使用它,我假设它太过于希望这个存在,但我确定这必须是一个共同的要求?所以我的问题是,实现允许JPA创建我的模式但是能够将一些数据插入到执行之间持续存在的数据库的目标的一般推荐方法是什么?
答案 0 :(得分:1)
答案是flyway。它是一个数据库迁移库,如果你使用的是Spring引导,它是无缝集成的,通常需要Spring创建一个bean,它可以获得对连接池的引用,创建连接并进行迁移。
Flyway创建了一个表,以便跟踪哪些脚本已应用于数据库,而脚本只是资源的一部分。
我们通常使用JPA来生成初始脚本。该脚本变为V1__initial.sql
,如果我们需要添加一些数据,我们可以添加V2__addUsers.sql
和V3__addCustomers.sql
等。
稍后当我们需要重命名列或添加其他表时,我们只需添加新脚本作为War文件的一部分,当应用程序加载时,Flyway会查看它的内部表,以查看当前版本,然后应用任何新脚本将其提升到所需的版本。
在Spring中,代码看起来像这样
private void performFlywayMigration(DataSource dataSource) {
Flyway flyway = new Flyway();
flyway.setLocations("db/migration");
flyway.setDataSource(dataSource);
log.debug("Starting database migration.");
flyway.migrate();
log.debug("Database migration completed.");
MigrationInfo current = flyway.info().current();
if (current.getState() == MigrationState.FUTURE_SUCCESS) {
log.warn("The Database schema is version " + current.getVersion() + ", this application expects version " + flyway.getBaselineVersion().getVersion());
}
}
通常,您不应该直接创建表格JPA。因为你有时需要修改脚本,例如在Sybase上Varchar(255)意味着255个字节,所以如果要存储2或3个字节的Unicode字符,则需要更多空间 - JPA实现不考虑(上次检查时) )。