java - 仅当生成 Schema 时,如何在 JPA 中初始化数据

标签 java spring hibernate jpa h2

你好,

我正在努力将 Java 应用程序从使用 postgres 更改为嵌入式数据库。我希望应用程序能够使用数据库中的一组初始数据进行部署。在过去的安装过程中,我执行了一个 sql 脚本来完全生成架构并将数据插入到我的表中。

理想情况下(因为我真的不想弄清楚如何连接到嵌入式数据库来生成它)我想让 JPA 第一次创建我的架构,当它创建时我希望能够运行我的 SQL 来插入数据。

我的搜索发现了明显的 hibernate 和 JPA 属性,它们允许运行 SQL 脚本。

首先,我发现在使用“hibernate.hbm2ddl.auto”时,您可以定义一个 import.sql 文件,这让我高兴了一天,直到我意识到它只适用于创建而不适用于更新。我的应用程序在使用 postgres 时需要更新此设置。我真正想要的是让它知道是否必须创建架构以及是否运行了 import.sql。但没有喜悦。

然后我继续使用“javax.persistence.schema- Generation.database.action”设置为“create”,我认为使用 JPA 规范可能更明智,所以我定义了“javax.persistence.sql-load-脚本源”规范中所说的“创建”

The provider will create the database artifacts on application deployment. The artifacts will remain unchanged after application redeployment.

这让我相信它会完全按照我想要的方式执行,仅在“应用程序部署时”创建表,但是当我使用它运行测试时,每个测试(创建新的 spring 上下文)都尝试创建所有表再次并且显然失败了,这让我意识到应用程序部署并不意味着我认为它意味着什么(一厢情愿的想法),现在我意识到 JPA 似乎甚至没有相当于 Hibernates 的“更新”属性,所以它总是会发生生成表格?

我想要的是在您第一次启动应用程序时生成我的表和数据,并在后续执行时知道数据在那里并使用它,我假设它太希望它存在,但我确定这一定是一个常见的要求吗?所以我的问题是,一般推荐的方法是什么来实现允许 JPA 创建我的架构但能够将一些数据插入到在执行之间保留的数据库中的目标?

最佳答案

答案是flyway 。它是一个数据库迁移库,如果您使用 Spring boot,它是无缝集成的,使用常规 Spring,您必须创建一个 bean,它获取对连接池的引用,创建连接并进行迁移。

Flyway 创建一个表,以便跟踪哪些脚本已应用到数据库,并且脚本只是资源的一部分。

我们通常使用 JPA 来生成初始脚本。这个脚本变成了V1__initial.sql,如果我们需要添加一些数据我们可以添加V2__addUsers.sqlV3__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 实现并没有考虑到这一点(上次我检查过) )。

关于java - 仅当生成 Schema 时,如何在 JPA 中初始化数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43681457/

相关文章:

java - 添加动态数量的监听器(Spring JMS)

java - Hibernate - 如何持久化 HashMap

java - 将资源作为类成员尝试使用资源

java - Spring Security with session get online users 返回空

java - Spring Junit org.h2.jdbc.JdbcSQLException : Exception opening port "9092" (port may be in use)

java - Hibernate列同时用作复合主键的一部分和复合外键的一部分

java - hibernate 。为什么删除单个子项会导致单向一对多关联中的所有子项被删除?

Java获取我的项目/bin/文件夹中文件的路径?

java - 带有 Android 的 Google Cloud Endpoints - 缓存响应?

java - 如何多次读取Jetty HttpInput(ServletInputStream)?