使用 H2 数据库自动创建的 Spring Boot

Posted

技术标签:

【中文标题】使用 H2 数据库自动创建的 Spring Boot【英文标题】:Spring boot with H2 Database auto create 【发布时间】:2019-01-12 11:25:02 【问题描述】:

我正在通过 Spring Boot 在我的 Java 应用程序中使用嵌入式 H2。目前,它在数据库中创建(覆盖)我的表。但是一旦我将它投入生产 我不希望我的表被擦除并重新创建,所以我不会丢失表中以前的数据。但我不确定如何做到这一点。不知道该放什么在线spring.jpa.hibernate.ddl-auto=create。我尝试了验证和其他选项,但没有成功。这是我的application.properties。谢谢

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.initialization-mode=always
spring.jpa.hibernate.naming.physical- 
strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

【问题讨论】:

【参考方案1】:

要将您的开发代码与生产代码区分开来,请使用 Spring 配置文件。然后你可以为每个环境定义你想要的任何行为。

也可以在application.properties 中定义一般(生产)行为,并覆盖它们(对于local 配置文件)application-local.properties。 Spring 对此有一个复杂的回退机制。

【讨论】:

【参考方案2】:

我在下面的行中丢失了。

spring.jpa.hibernate.ddl-auto=update

【讨论】:

【参考方案3】:

您可以显式设置 spring.jpa.hibernate.ddl-auto,标准的 Hibernate 属性值为 none、validate、update、create 和 create-drop

Spring Boot 会根据它是否认为你的数据库是嵌入式的来为你选择一个默认值。如果未检测到模式管理器或在所有其他情况下均未检测到,则默认为 create-drop。通过查看连接类型来检测嵌入式数据库。 hsqldb、h2 和 derby 是嵌入的,而其他的则不是。从内存中切换到“真实”数据库时要小心,不要假设新平台中是否存在表和数据。您要么必须显式设置 ddl-auto,要么使用其他机制之一来初始化数据库

以下情况可能适用于您:

更新:

例如,更新操作将尝试添加新列、约束等,但绝不会删除以前可能存在但不再作为先前运行的对象模型的一部分的列或约束。

无:

在生产中,通常强烈建议您使用 none 或干脆不指定此属性。这是因为 DBA 通常会检查迁移脚本以了解数据库更改,尤其是当您的数据库在多个服务和应用程序之间共享时。

此外,如果 Hibernate 从头开始​​创建模式(也就是说,如果 ddl-auto 属性设置为 create或创建删除)。如果您小心的话,这对于演示和测试很有用,但可能不是您希望在生产中的类路径上出现的东西。这是一个 Hibernate 特性(与 Spring 无关)。

【讨论】:

但我的问题是我有一个 data.sql 文件,spring 使用该文件将行插入到我的表中。如果它在下次启动应用程序时将其设置为“更新”,则 spring 将尝试再次运行 data.sql 但由于尝试那些已经存在的行并且无法使用主键添加相同的值而无法运行。我想要做的是,当用户第一次启动应用程序时,它将创建模式/表并将行添加到我在 data.sql 中的表中,以及下次启动应用程序时。它不会覆盖或添加这些。我想将我的数据持久保存在表格中 我已经编辑了我的 ans,在您的情况下,您需要在生产环境中将其从类路径中删除。【参考方案4】:

你应该在这里使用更新:

spring.jpa.hibernate.ddl-auto=update

如果它们尚未定义,这将在启动时构建表,否则它将保持原样。

另外,当你这样做时,你可能想放弃:

spring.jpa.generate-ddl=true

最后,最好的方法是为不同的环境设置不同的属性集,或者将它们作为运行时变量传递,或者使用类似 spring config server 的东西将它们外部化。

【讨论】:

很抱歉,您为什么要投反对票?我已经这样做了数百次,我知道它有效。 因为完全错误:docs.jboss.org/hibernate/orm/current/userguide/html_single/… 否;它不是。我认为你应该努力理解你在说什么,然后再无精打采地到处投票否决人们的答案。去尝试自己更新,看看它的作用。 看,Hibernate 的官方文档说更新选项是“更新数据库模式”。 Daisy Day 的回答说它“保持原样”。这些显然不兼容,所以其中一个是错误的。其中哪一个最有可能是正确的。考虑到选项的名称是“Update”,而不是“LeaveAsTheyAre”?仅供参考,我在这里回答了 2239 个关于 Hibernate 的问题,并通过这样做获得了 70K+ 代表点(不包括 JPA 问题)。所以也许,也许,我知道我在说什么。 问题是关于避免架构被破坏和数据被擦除。假设他在针对同一个数据库启动应用程序之前不打算更改模型,则使用 update 将实现这一点。我还说理想情况下,您可以针对不同的环境进行不同的配置,这是非常有效的。这不是“完全错误”。对于他的要求,这是一个有效的答案,并且会起作用,而且不应该被否决。为术语“保持原样”道歉 - 在他的用例中是正确的。

以上是关于使用 H2 数据库自动创建的 Spring Boot的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot学习

Spring REST - 无法强制 H2 数据库手动创建密钥

嵌入式。 H2 DB自动增量(Java测试用例)

java - 如何在java桌面应用程序中使用spring(事务)和hibernate创建嵌入式H2 DB?

H2 嵌入式数据库在 Spring Boot 测试期间未获取属性

Spring boot h2自动配置不起作用