Spring Boot集成H2数据库自动创建表格

4
我正在使用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
5个回答

11

在这里应该使用update:

spring.jpa.hibernate.ddl-auto=update

这将在启动时创建表,如果它们尚未定义,则保持不变。另外,当您这样做时,您可能想删除以下行:
spring.jpa.generate-ddl=true

最好的方法是为不同的环境设置不同的属性,可以通过将它们作为运行时变量传递,或者理想情况下使用类似Spring配置服务器这样的外部化配置来实现。

很抱歉,但你为什么要投反对票呢?我已经做了数百次,我知道它是有效的。 - Daisy Day
因为这是明显错误的: https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl - JB Nizet
不,不是这样的。我认为在懒散地随意否决他人的答案之前,你应该努力理解自己所说的内容。去尝试更新一下,看看它会做什么。 - Daisy Day
看,Hibernate的官方文档说更新选项是用于“更新数据库模式”。Daisy Day的回答说它“保留表格不变”。这两者显然不兼容,所以其中一个是错误的。哪个更有可能是正确的?考虑到选项的名称是“更新”,而不是“保持不变”?FYI,我在这里回答了2239个关于Hibernate的问题,并通过这样做获得了70K+的声望值(不包括JPA问题)。所以也许,也许,我对自己所说的有一点了解。 - JB Nizet
这个问题主要是关于避免模式被破坏和数据被擦除的。使用更新(update)可以实现这一点,前提是他在启动应用程序时不会更改模型针对同一个数据库。我还说理想情况下你会为不同的环境设置不同的配置,这是非常有效的。这不是“完全错误”的。它是对他所问的问题的有效回答,能够正常工作,不仅值得否决。对于术语“按原样保留”表示歉意 - 在他的用例中确实如此。 - Daisy Day
显示剩余2条评论

5
您可以明确设置 spring.jpa.hibernate.ddl-auto 属性,标准的 Hibernate 属性值包括 none、validate、update、create 和 create-drop。
Spring Boot 会根据它认为的数据库是否是嵌入式的自动为您选择默认值。如果没有检测到模式管理器,则默认为 create-drop;否则为 none。通过查看连接类型来检测嵌入式数据库,hsqldb、h2 和 derby 是嵌入式数据库,其他数据库则不是。当从内存切换到“真正的”数据库时,请注意不要对新平台中的表和数据存在假设。您必须明确设置 ddl-auto 属性或使用其他机制来初始化数据库。
以下情况可能适用于您: update:
例如,升级操作将尝试添加新列、约束等,但永远不会删除先前存在但在先前运行的对象模型中不再存在的列或约束。
none:
在生产环境中,通常强烈建议您使用 none 或简单地不指定此属性。这是因为 DBA 通常会审查数据库更改的迁移脚本,特别是如果您的数据库在多个服务和应用程序之间共享。
此外,在类路径的根目录下有一个名为 import.sql 的文件,在启动时执行,如果 Hibernate 从头开始创建模式(即 ddl-auto 属性设置为 create 或 create-drop)。如果您小心谨慎,这可能对演示和测试很有用,但可能不是您希望在生产环境中存在于类路径上的内容。这是 Hibernate 的一个特性(与 Spring 无关)。

但我的问题是,我有一个 data.sql 文件,Spring 使用它来向我的表中插入行。如果将其设置为“更新”,则下次启动应用程序时,Spring 将尝试再次运行 data.sql,但由于尝试添加具有主键的相同值,因此无法添加这些行。我想要做的是,在用户第一次启动应用程序时,它将创建模式/表并将数据.sql 中的行添加到表中,下次启动应用程序时,它不会覆盖或添加这些内容。我希望保持表中的数据持久。 - Matahari
1
我已经编辑了我的答案,在你的情况下,你需要在生产环境中从类路径中删除它。 - Vivek Pakmode

3
对于 .yaml,您可以这样做:
spring:
  datasource:
    url: jdbc:h2:path
    username: sa
    password: 
    driverClassName: org.h2.Driver
  jpa:
    spring.jpa.database-platform: org.hibernate.dialect.H2Dialect
    generate-ddl: true
    hibernate.ddl-auto: update
  h2:
    console.enabled: true
  

0

我漏掉了下面这行。

spring.jpa.hibernate.ddl-auto=update


0
为了区分开发代码和生产环境,可以使用Spring配置文件。这样你就可以为每个环境定义不同的行为。
同时,在application.properties中定义通用(生产)行为也是可以的,然后在application-local.properties中覆盖它们(针对local配置文件)。Spring有一个复杂的回退机制来处理这种情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接