Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)

Posted

技术标签:

【中文标题】Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)【英文标题】:Hibernate 5.1.x naming Strategy (backward compatible with Hibernate 4.x) 【发布时间】:2016-08-31 22:54:10 【问题描述】:

我正在使用 Spring Boot 1.3.3.RELEASE。默认情况下,Spring Boot 使用 Hibernate 版本 4.x。我正在尝试使用新的 Hibernate,即 5.1.0 FINAL(截至目前)。

我正在使用 Gradle 来覆盖 Hibernate 版本,我添加了以下行

ext['hibernate.version']="5.1.0.Final"

按照SpringBoot 1.3.0 support hibernate 5?的步骤进行

我使用以下命名策略

spring.jpa.properties.hibernate.naming.implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl

spring.jpa.properties.hibernate.naming.physical_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

我有一个实体类

@Entity
public class AppUser 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Length(max = 100)
    private String username;

    @NotNull
    @Length(max = 100)
    private String firstName;

    @NotNull
    @Length(max = 100)
    private String lastName;

    @Length(max = 100)
    private String middleName;

    @NotNull
    @Length(max=100)
    private String email;

    @NotNull
    @Length(max = 100)
    private String password;

    @NotNull
    private boolean enabled;


在 Hibernate 4.x 上,它执行查询

create table app_user (
        id bigint not null auto_increment,
        email varchar(100) not null,
        enabled bit not null,
        first_name varchar(100) not null,
        last_name varchar(100) not null,
        middle_name varchar(100),
        password varchar(100) not null,
        username varchar(100) not null,
        primary key (id)
    )

在 5.x 上它执行了查询

create table AppUser (
        id bigint not null auto_increment,
        email varchar(100) not null,
        enabled bit not null,
        firstName varchar(100) not null,
        lastName varchar(100) not null,
        middleName varchar(100),
        password varchar(100) not null,
        username varchar(100) not null,
        primary key (id)
    )

如何设置命名策略,使 Hibernate 在表名和列名上使用 5.x 下划线(如 4.x)

【问题讨论】:

你确定你用ext['hibernate.version']="5.1.0.Final"把hibernate版本改成5.1.0了吗?我认为您参考的链接中的解决方案适用于 maven,但不适用于 gradle。 是的。当 Classpath 包含 hibernate 5.1.0.Final Jars 【参考方案1】:

首先,你不需要 org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

因为它什么都不做,并且被 Hibernate 作为默认值使用。

Hibernate 5 没有您想要的策略。所有策略都符合 JPA(生成像 AppUser 这样的名称)。所以你需要自己实现。

例如物理命名策略

public class UnderscorePhysicalStartegy extends PhysicalNamingStrategyStandardImpl 

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) 
        return context.getIdentifierHelper()
                .toIdentifier(NamingStrategyUtils.classToName(name.getText()));
    


它使用NamingStrategyUtils。

请记住,如果您指定明确的名称

@Entity
@Table(name = "AppUser")
public class AppUser 


无论如何你都会有一个表名app_user。如果您不希望出现这种行为,请使用隐式命名策略。

我做了一些关于命名策略的研究工作。您可以参考Hibernate5NamingStrategy,它会根据您的需要生成带有下划线的表和列名称以及约束名称(唯一、外键)。

此类用于生成名称:HibernateNamingStrategy。

如何使用Hibernate5NamingStrategy

可以使用StrategyOptions配置命名策略。

例如,使用不带前缀的策略(如f_):

StrategyOptions options = StrategyOptions.builder().withoutPrefixes().build();
Hibernate5NamingStrategy strategy = new Hibernate5NamingStrategy(options);

其他示例:Hibernate 5 Implicit Naming Strategy

除此之外,ImprovedNamingStrategy for Hibernate 5 可以用来模拟 Hibernate 4 ImprovedNamingStrategy 的行为。

【讨论】:

如果没有f_ 前缀,有什么办法吗?默认设置太烦人了。 @Airhead 我更新了我的答案。我不知道哪个默认行为更好用。 我最终创建了自己的类,它扩展了上述类并以这种方式配置选项,以便能够从persistence.xml 中使用它,而不是不推荐使用的配置对象。 @Airhead 这很有趣。它需要将这种方式添加到文档中。【参考方案2】:

我将我的分析提供给任何人使用:

如果您在实体类中提供 @Table@Column 注释,并且名称带有下划线,即 user_id 即 @Column( name="user_id"),将列名作为user_id;如果您将其作为 userid 提供,那么如果您不使用策略或隐式策略(特别是 spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl),它将更改为 user_id。因此,如果您想要一个实体属性名称更改为带有下划线和小写字母的策略,即从 userId 到 user_id,您应该使用隐式或不使用策略(实际上使用隐式策略)。

如果您不希望您的命名策略在列名或类名中添加下划线,那么您需要使用的策略类似于:spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl。您在注释 @Table@Column 的 名称属性中提供的内容将保持原样。

如果您不想提供注释并希望手动处理表名和列名,则应扩展类 org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 并覆盖所需的方法。如果您仍然在此处的某些情况下使用注释,请记住覆盖的方法将应用于这些注释中编写的名称。 spring.jpa.hibernate.naming.physical-strategy=example.CustomStrategy

【讨论】:

以上是关于Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)的主要内容,如果未能解决你的问题,请参考以下文章

Apollo Graphql:重命名模式以实现向后兼容性

Hibernate命名策略

从类继承以保证向后兼容性

Hibernate 命名策略被忽略

Hibernate 命名策略更改表名

hibernate 命名策略