Hibernate 命名策略更改表名

Posted

技术标签:

【中文标题】Hibernate 命名策略更改表名【英文标题】:Hibernate naming strategy changing table names 【发布时间】:2017-01-02 22:19:45 【问题描述】:

我对休眠(5.1 版)命名策略有点困惑——即它改变了我的表名,我想避免这种情况。另外 - 根据 intelij,spring.jpa.hibernate.naming_strategy 似乎已被弃用,但我找不到正确配置它的(其他)方法。

我在application.properties中有如下配置:

spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.mysql5Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.properties.hibernate.current_session_context_class=thread

如前所述,第一个被标记为已弃用。

现在我有了一个实体:

@Entity
@Table(name = "usaUploadTable", schema = "usertable201", catalog = "")
public class UsaUploadTable 
    ....

表名,如@Table(name = "")usaUploadTable。

现在当我运行我的应用程序时,我得到了

表 'usertable201.usa_upload_table' 不存在

这是正确的 - 它的名称不像 hibernate 是如何改变它的那样。

如何让 hibernate 正确使用我的表名?

编辑:

我也试过

DefaultNamingStrategy
ImprovedNamingStrategy

他们都改变了它

版本:

spring-boot-1.4.0.RELEASE
hibernate 5.1
javax-transaction-api 1.2
hibernate-validator 5.2.4
javassist 3.20

【问题讨论】:

这个 github 线程对 Hibernate 4 n 5 都很有用。 github.com/spring-projects/spring-boot/issues/2129 【参考方案1】:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

它对我有用。这是我正在使用的版本:

Spring Boot (v1.4.2.RELEASE)
Hibernate Core 5.0.11.Final

【讨论】:

【参考方案2】:

问题在于 spring-boot-1.4 - 似乎他们已经更改了属性(或其他)我现在找到了这个答案ImprovedNamingStrategy no longer working in Hibernate 5,但它仍然没有正确解决。所以我稍微修改了代码,不使用下划线方法,并扩展了新引入的类SpringPhysicalNamingStrategy

package com.foo;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

import java.io.Serializable;
import java.util.Locale;


public class RealNamingStrategyImpl extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable 

    public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) 
        return new Identifier(name.getText(), name.isQuoted());
    

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) 
        return new Identifier(name.getText(), name.isQuoted());
    


application.properties 中,我已将弃用的行更改为

spring.jpa.properties.hibernate.physical_naming_strategy=<package>.RealNamingStrategyImpl

现在它使用的正是我在实体文件中的表名和列名。

【讨论】:

有没有办法通过 Java 配置而不是属性文件来定义 NamingStrategy?显然,这是一个很可能根本不会改变的配置。因此,我想对其进行硬编码。 黄金!这就是我一直在寻找的。两个调整 1) public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl(); 应该是 public static final PhysicalNamingStrategyStandardImpl INSTANCE = new PhysicalNamingStrategyStandardImpl(); 2) remove `import java.util.Locale;【参考方案3】:

对于想要在 Postgresql 和 Spring boot 1.5.2 中大写的人

public class CustomDatabaseIdentifierNamingStrategy extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable 

    public static final long serialVersionUID = 1L;
    public static final CustomDatabaseIdentifierNamingStrategy INSTANCE = new CustomDatabaseIdentifierNamingStrategy();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) 
        return new Identifier(name.getText().toUpperCase(), true);
    

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) 
        return new Identifier(name.getText().toUpperCase(), true);
    


【讨论】:

在土耳其服务器上运行上述代码时要小心。 toUpperCase() 会将items 转换为İTEMS(拉丁文大写字母i,上面带有点)。要解决此问题,请始终使用toUpperCase(Locale.ROOT)【参考方案4】:

如果您在实体类中提供@Table 和@Column 注释,其名称带有下划线,即user_id 即@Column(name="user_id"),它将采用列名作为用户身份;如果您将其作为用户 ID 提供,那么如果您不使用策略或隐式策略(特别是 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 的 name 属性中提供的内容将保持原样。

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

【讨论】:

【参考方案5】:

Spring 启动 2.0.0 和 Hibernate 5

    public class MySqlNamingStrategyImpl extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable 

protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) 
    return false;

【讨论】:

请您详细说明您的答案如何解决 OP 问题?

以上是关于Hibernate 命名策略更改表名的主要内容,如果未能解决你的问题,请参考以下文章

JPQL / Hibernate 查询的动态表名

Hibernate 命名查询的表名问题

Hibernate入门-----Hiberna核心文件详解

hibernate

Hibernate 命名策略被忽略

hibernate 命名策略