我真的很想知道更多关于更新、导出和可以给我的值hibernate.hbm2ddl.auto
我需要知道什么时候使用更新,什么时候不使用?什么是替代方案?
这些是可能在 DB 上发生的变化:
- 新表
- 旧表中的新列
- 已删除的列
- 列的数据类型已更改
- 一种类型的列改变了它的属性
- 表被丢弃
- 列的值已更改
在每种情况下,最好的解决方案是什么?
从社区文档:
hibernate.hbm2ddl.auto 在创建 SessionFactory 时自动验证模式 DDL 或将其导出到数据库。使用 create-drop,当 SessionFactory 显式关闭时,数据库模式将被删除。
例如验证 | 更新 | 创建 | 创建删除
所以可能的选项列表是,
这些选项似乎旨在成为开发人员工具,而不是促进任何生产级数据库,您可能想看看以下问题;休眠:hbm2ddl.auto=生产中的更新?
还有“无”的未记录值可以完全禁用它。
配置属性被称为hibernate.hbm2ddl.auto
在我们的开发环境中,我们设置hibernate.hbm2ddl.auto=create-drop
为在每次部署时删除并创建一个干净的数据库,以便我们的数据库处于已知状态。
理论上,您可以设置hibernate.hbm2ddl.auto=update
通过更改模型来更新数据库,但我不相信在生产数据库上这样做。文档的早期版本说这是实验性的,至少;我不知道目前的状态。
因此,对于我们的生产数据库,不要设置hibernate.hbm2ddl.auto
——默认是不做数据库更改。相反,我们手动创建一个 SQL DDL 更新脚本,将更改从一个版本应用到下一个版本。
hbm2ddl
首先,配置属性的可能值如下:
none
- 不执行任何操作。不会生成架构。create-only
- 将生成数据库模式。drop
- 数据库模式将被删除。create
- 数据库模式将被删除并在之后创建。create-drop
- 数据库模式将被删除并在之后创建。关闭 后SessionFactory
,将删除数据库模式。validate
- 将使用实体映射验证数据库架构。update
- 将通过将现有数据库模式与实体映射进行比较来更新数据库模式。如果您计划添加功能或执行一些自定义脚本,这hibernate.hbm2ddl.auto="update"
很方便但不太灵活。
因此,最灵活的方法是使用Flyway。
但是,即使您使用 Flyway,您仍然可以使用 hbm2ddl 生成初始迁移脚本。
我会使用liquibase来更新您的数据库。hibernate 的模式更新功能实际上只适用于开发新功能的开发人员。在生产情况下,需要更加小心地处理数据库升级。
虽然这是一篇相当老的帖子,但由于我对该主题进行了一些研究,所以想分享它。
休眠.hbm2ddl.auto
根据文档,它可以有四个有效值:
创建 | 更新 | 验证 | 创建删除
以下是对这些值显示的行为的解释:
以下是值得注意的要点:
Table not found:<table name>
如果我给这个属性赋予任何值(比如 abc,而不是上面讨论的上述四个值),或者它只是留空。它显示以下行为:
- 如果数据库中不存在模式:- 它创建模式
- 如果数据库中存在架构:-更新架构。
hibernate.hbm2ddl.auto
创建 sessionFactory 时自动验证 DDL 并将其导出到模式。
默认情况下,它不会在 DB 上自动执行任何创建或修改。如果用户设置了以下值之一,那么它会自动进行 DDL 模式更改。
create - 创建模式
<entry key="hibernate.hbm2ddl.auto" value="create">
update - 更新现有模式
<entry key="hibernate.hbm2ddl.auto" value="update">
validate - 验证现有模式
<entry key="hibernate.hbm2ddl.auto" value="validate">
create-drop - 在会话开始和结束时自动创建和删除模式
<entry key="hibernate.hbm2ddl.auto" value="create-drop">
如果您不想在应用程序中使用字符串并且正在寻找预定义的常量,请查看org.hibernate.cfg.AvailableSettings
Hibernate JAR 中包含的类,您将在其中找到所有可能设置的常量。以您为例:
/**
* 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";
validate
: 验证模式,数据库没有变化。update
:使用当前执行查询更新架构。create
:每次都创建新的模式,并销毁以前的数据。create-drop
: 当应用程序停止或 SessionFactory 显式关闭时删除模式。validate
:它验证架构并且不对数据库进行任何更改。
假设您在映射文件中添加了一个新列并执行了插入操作,它将抛出一个异常“缺少 XYZ 列”,因为现有架构与您要插入的对象不同。如果您通过手动添加新列来更改表,然后执行插入操作,那么它肯定会将所有列与新列一起插入到表中。意味着它不会对现有架构/表进行任何更改/更改。
update
:当您执行操作时,它会更改数据库中的现有表。您可以使用 hbm2ddl 的此选项添加或删除列。但是,如果您要添加一个“NOT NULL”的新列,那么它将忽略将该特定列添加到数据库中。因为如果要向现有表添加“NOT NULL”列,表必须为空。
从 5.0开始,您现在可以在专用的Enum
:中找到这些值(自 5.2 起org.hibernate.boot.SchemaAutoTooling
使用值增强)。NONE
或者更好的是,从 5.1 开始,您还可以使用结合了 JPA 2 和“旧版”Hibernate DDL 操作的 。org.hibernate.tool.schema.Action
Enum
但是,您还不能使用它以DataSource
编程方式配置。结合使用它会更好,org.hibernate.cfg.AvailableSettings#HBM2DDL_AUTO
但当前代码需要一个String
值(摘自SessionFactoryBuilderImpl
):
this.schemaAutoTooling = SchemaAutoTooling.interpret( (String) configurationSettings.get( AvailableSettings.HBM2DDL_AUTO ) );
......以及enum
两者的内部价值观org.hibernate.boot.SchemaAutoTooling
并org.hibernate.tool.schema.Action
没有公开。
下面是一个示例编程DataSource
配置(在我的 Spring Boot 应用程序中使用),它使用了一个策略,.name().toLowerCase()
但它只适用于没有破折号的值(不是create-drop
例如):
@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();
}
对于搜索默认值的任何人...
它是在 Spring-boot 的 2.0.5 版本和 JpaProperties 的 1.1.0 版本的源代码中编写的:
/**
* DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto"
* property. Defaults to "create-drop" when using an embedded database and no
* schema manager was detected. Otherwise, defaults to "none".
*/
private String ddlAuto;
综上所述......注意这个属性被调用dll.auto
并且应该只控制dll操作(创建/删除模式/表),我惊讶地发现它也与dml有关:只update
允许插入数据,这是dml操作.
尝试将数据填充到内存数据库中时被此抓住;只update
工作。