关于Java:Hibernate hbm2ddl.auto配置的可能值是什么,它们做了什么

What are the possible values of the Hibernate hbm2ddl.auto configuration and what do they do

我真的想知道更多关于更新、导出和可以提供给hibernate.hbm2ddl.auto的值的信息。我需要知道何时使用更新,何时不使用?还有什么选择呢?

这些是可能在数据库上发生的更改:

  • 新表
  • 旧表中的新列
  • 列删除
  • 列的数据类型已更改
  • 列的类型更改了其属性
  • 表下降
  • 列值已更改

在每种情况下,最好的解决方案是什么?


社区文件:

hibernate.hbm2ddl.auto Automatically validates or exports schema DDL to the database when the SessionFactory is created. With create-drop, the database schema will be dropped when the SessionFactory is closed explicitly.

e.g. validate | update | create | create-drop

所以可能的选择是,

  • 验证:验证架构,不更改数据库。
  • 更新:更新架构。
  • 创建:创建架构,销毁以前的数据。
  • create drop:在显式关闭sessionFactory时(通常在应用程序停止时)删除架构。

这些选项似乎是为了开发人员的工具而不是为了方便任何生产级别的数据库,您可能想看看下面的问题:hibernate:hbm2ddl.auto=update in production?


还有未记录的值"none"可以完全禁用它。


配置属性称为hibernate.hbm2ddl.auto

在我们的开发环境中,我们设置hibernate.hbm2ddl.auto=create-drop在每次部署时删除并创建一个干净的数据库,这样我们的数据库就处于已知状态。

理论上,您可以设置hibernate.hbm2ddl.auto=update以使用对模型的更改来更新您的数据库,但我不相信在生产数据库中这样做。早期版本的文档说,这是实验性的,至少;我不知道当前的状态。

因此,对于我们的生产数据库,不要设置hibernate.hbm2ddl.auto-默认情况是不进行数据库更改。相反,我们手动创建了一个将更改从一个版本应用到下一个版本的SQL DDL更新脚本。


我会用Liquibase更新你的数据库。Hibernate的模式更新功能在开发新功能的时候对开发人员来说真的很好。在生产环境中,需要更仔细地处理数据库升级。


虽然这是一个相当古老的帖子,但我做了一些关于这个话题的研究,所以想分享一下。

休眠.hbm2ddl.auto

根据文档,它可以有四个有效值:

创建更新验证创建删除

以下是这些值所示行为的解释:

  • 创建:-创建架构,架构中以前存在的数据(如果存在)将丢失
  • 更新:用给定的值更新架构。
  • validate:-验证架构。它不会改变数据库。
  • create drop:-创建模式并销毁以前存在的数据(如果存在)。它还将在关闭sessionFactory时删除数据库模式。

以下是值得注意的要点:

  • 在更新的情况下,如果数据库中不存在架构,则创建架构。
  • 在验证的情况下,如果数据库中不存在架构,则不会创建该架构。相反,它会抛出一个错误:Table not found:
  • 如果创建删除,则在关闭会话时不会删除架构。它只在关闭会话工厂时下降。
  • 如果我给这个属性任何值(比如abc,而不是上面讨论的四个值),或者只留下空白。它显示以下行为:

    -如果数据库中不存在架构:-它将创建架构

    -如果数据库中存在架构:—更新架构。


  • 创建sessionFactory时,hibernate.hbm2ddl.auto自动验证DDL并将其导出到模式。

    默认情况下,它不会在数据库上自动执行任何创建或修改。如果用户设置了以下值之一,那么它将自动执行DDL模式更改。

    • 创建-正在创建架构

    1
    <entry key="hibernate.hbm2ddl.auto" value="create">
  • 更新-更新现有架构

    1
    <entry key="hibernate.hbm2ddl.auto" value="update">
  • validate-验证现有架构

    1
    <entry key="hibernate.hbm2ddl.auto" value="validate">
  • create drop-在会话开始和结束时自动创建和删除架构

    1
    <entry key="hibernate.hbm2ddl.auto" value="create-drop">

  • 首先,hbm2ddl配置属性的可能值如下:

    • none—不执行任何操作。将不会生成架构。
    • create-only—将生成数据库模式。
    • drop—数据库模式将被删除,然后再创建。
    • create—数据库模式将被删除,然后再创建。
    • create-drop—数据库模式将被删除,然后再创建。关闭SessionFactory后,数据库模式将被删除。
    • validate—将使用实体映射验证数据库模式。
    • update—将通过比较现有数据库模式与实体映射来更新数据库模式。

    我专门为最常见的Hibernate DDL生成策略写了一篇博文:

  • 如果您计划添加函数或执行一些自定义脚本,hibernate.hbm2ddl.auto="update"虽然方便,但灵活性较低。
  • 最灵活的方法是使用Flyway。
  • 但是,即使使用Flyway,也可以使用hbm2ddl生成初始迁移脚本。在本文中,您可以看到如何将JPA实体模型与JOOQ表模型结合起来。


    如果您不想在应用程序中使用字符串,并且正在查找预定义的常量,请查看Hibernate JAR中包含的org.hibernate.cfg.AvailableSettings类,在那里可以找到所有可能设置的常量。例如,在您的案例中:

    1
    2
    3
    4
    5
    /**
     * Auto export/update schema using hbm2ddl tool. Valid values are <tt>update</tt>,
     * <tt>create</tt>, <tt>create-drop</tt> and <tt>validate</tt>.
     */

    String HBM2DDL_AUTO ="hibernate.hbm2ddl.auto";


    我想你应该把注意力集中在

    1
    SchemaExport Class

    此类使您的配置成为动态的所以它可以让你选择你最喜欢的套房…

    签出[架构导出]


    • validate:验证模式,数据库没有变化。
    • update:用当前执行查询更新架构。
    • create:每次创建新的模式,并销毁以前的数据。
    • create-drop:当应用程序停止或显式关闭sessionFactory时,删除模式。

    validate:它验证模式,不更改数据库。假设您在映射文件中添加了一个新列并执行了插入操作,则会引发一个异常"缺少XYZ列",因为现有架构与要插入的对象不同。如果您通过手动添加新列来更改表,然后执行插入操作,那么它肯定会将所有列连同新列一起插入到表中。意味着它不会对现有的模式/表进行任何更改/更改。

    update:当您执行操作时,它会改变数据库中现有的表。可以使用hbm2ddl选项添加或删除列。但是,如果您要添加一个"非空"的新列,那么它将忽略向数据库添加该特定列。因为如果要向现有表中添加"非空"列,则该表必须为空。


    从5.0开始,您现在可以在专用的Enum中找到这些值:org.hibernate.boot.SchemaAutoTooling(从5.2开始,使用值NONE进行增强)。

    或者更好,因为5.1,您还可以使用结合了JPA2和"遗留"Hibernate DDL操作的org.hibernate.tool.schema.ActionEnum

    但是,您还不能用它以编程方式配置DataSource。与org.hibernate.cfg.AvailableSettings#HBM2DDL_AUTO结合使用会更好,但当前代码预期String值(摘自SessionFactoryBuilderImpl):

    1
    this.schemaAutoTooling = SchemaAutoTooling.interpret( (String) configurationSettings.get( AvailableSettings.HBM2DDL_AUTO ) );

    …和org.hibernate.boot.SchemaAutoToolingorg.hibernate.tool.schema.Action的内部Enum值没有公开披露。

    下面是一个示例程序化的DataSource配置(在我的一个Spring引导应用程序中使用),由于.name().toLowerCase(),它使用了一个gambit,但它只使用不带破折号的值(例如,不是create-drop):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Bean(name = ENTITY_MANAGER_NAME)
    public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier(DATA_SOURCE_NAME) DataSource internalDataSource) {

        Map<String, Object> properties = new HashMap<>();
        properties.put(AvailableSettings.HBM2DDL_AUTO, SchemaAutoTooling.CREATE.name().toLowerCase());
        properties.put(AvailableSettings.DIALECT, H2Dialect.class.getName());

        return builder
                .dataSource(internalDataSource)
                .packages(JpaModelsScanEntry.class, Jsr310JpaConverters.class)
                .persistenceUnit(PERSISTENCE_UNIT_NAME)
                .properties(properties)
                .build();
    }

    理论上,可以将hibernate.hbm2ddl.auto=update设置为使用对模型的更改来更新数据库,但我不信任生产数据库中的更改。早期版本的文档说,这是实验性的,至少;我不知道当前的状态。

    因此,对于我们的生产数据库,不要设置hibernate.hbm2ddl.auto-默认情况是不更改数据库。相反,我们手动创建了一个将更改从一个版本应用到下一个版本的SQL DDL更新脚本。