如何将使用camelCase命名的Hibernate实体字段映射到snake_case(下划线)数据库标识符

41

我的数据库字段是下划线命名法,实体字段是驼峰命名法。我不能改变它们中的任何一个。

有没有什么东西,比如类级别注释,可以将实体列名称注释默认为驼峰式等效物?

例如,我有这样一个实体:

@Entity
public class AuthorisationEntity {

    @Column(name = "non_recoverable")
    private BigDecimal nonRecoverable;

    @Column(name = "supplier_recoverable")
    private BigDecimal supplierRecoverable;

    @Column(name = "refund_amount")
    private BigDecimal refundAmount;

}

我梦想着这个:

@Entity
@DatabaseIsUnderscoreAndThisAnnotationConvertsThemToCamelCaseByDefault
public class AuthorisationEntity {

    private BigDecimal nonRecoverable;

    private BigDecimal supplierRecoverable;

    private BigDecimal refundAmount;

}

6
我找不到类@DatabaseIsUnderscoreAndThisAnnotationConvertsThemToCamelCaseByDefault... 开玩笑的,但我真的想把这个贴给我的朋友。 :) - Kenny Cason
5个回答

21

您可以使用自定义的Hibernate命名策略来实现此目标。

您只需要使用开源项目hibernate-types即可。

Hibernate 5.2或更高版本

您需要添加以下Maven依赖项:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

并设置以下 Hibernate 配置属性:

<property name="hibernate.physical_naming_strategy"
          value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy"
/>

Hibernate 5.0和5.1

您需要添加以下Maven依赖项:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-5</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

并设置以下 Hibernate 配置属性:

<property name="hibernate.physical_naming_strategy"
          value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy"
/>

Hibernate 4.3

您需要添加以下Maven依赖项:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-43</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

并设置以下Hibernate配置属性:

<property name="hibernate.ejb.naming_strategy"
          value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy"
/>

Hibernate 4.2和4.1

您需要添加以下Maven依赖:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-4</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

并设置以下 Hibernate 配置属性:

<property name="hibernate.ejb.naming_strategy"
          value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy"
/>

测试时间

假设您拥有以下实体:

@Entity(name = "BookAuthor")
public class BookAuthor {
 
    @Id
    private Long id;
 
    private String firstName;
 
    private String lastName;
 
    //Getters and setters omitted for brevity
}
 
@Entity(name = "PaperBackBook")
public class PaperBackBook {
 
    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE
    )
    private Long id;
 
    @NaturalId
    private String ISBN;
 
    private String title;
 
    private LocalDate publishedOn;
 
    @ManyToOne(fetch = FetchType.LAZY)
    private BookAuthor publishedBy;
 
    //Getters and setters omitted for brevity
}

使用CamelCaseToSnakeCaseNamingStrategy自定义命名策略时,Hibernate将使用hbm2ddl工具生成以下数据库架构:

CREATE SEQUENCE hibernate_sequence
START WITH 1 INCREMENT BY 1
 
CREATE TABLE book_author (
    id          BIGINT NOT NULL,
    first_name  VARCHAR(255),
    last_name   VARCHAR(255),
    PRIMARY KEY (id)
)
 
CREATE TABLE paper_back_book (
    id              BIGINT NOT NULL,
    isbn            VARCHAR(255),
    published_on    DATE, 
    title           VARCHAR(255),
    published_by_id BIGINT, 
    PRIMARY KEY (id)
)

很酷,对吧?


1
这位绅士来两杯威士忌!这个修复了Hibernate 5的蛇形命名策略问题! - AbstractVoid
这个不起作用。你有任何想法是什么原因吗?javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet。我正在使用implementation("com.vladmihalcea", "hibernate-types-52","2.10.0"),并将属性放在hibernate.cfg中。 - Braian Coronel
你可以在GitHub上找到大量的测试用例来证明它的工作原理。将我的测试与你的测试进行比较,看看它们的不同之处。 - Vlad Mihalcea
hibernate-types 真是太棒了!我正在使用它来支持 Postgres 扩展。 - mokaymakci
我很高兴你喜欢它。 - Vlad Mihalcea

16

这看起来像是我需要的,不错。 - Paul Stanley

5

我在一个Spring boot应用程序中遇到了同样的问题,我尝试将上面的Hibernate配置添加到Spring属性文件中,但没有成功,然后尝试将其作为Java bean添加,但仍然没有成功。

我正在使用Hibernate Properties对象,在其中添加Hibernate配置解决了我的问题:

    protected Properties buildHibernateProperties() {
        Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
        hibernateProperties.setProperty("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());

        return hibernateProperties;
    }

3
从Hibernate 5.5.4.Final开始,引入了CamelCaseToUnderscoresNamingStrategy,这个新策略相当于Spring的SpringPhysicalNamingStrategy。
CamelCaseToUnderscoresNamingStrategy将所有的点替换为下划线,将所有的驼峰式命名替换为下划线,并将所有表名生成为小写。
例如,LineItem实体将被映射到line_item表。

1
import org.hibernate.cfg.DefaultNamingStrategy;
import org.hibernate.cfg.ImprovedNamingStrategy;

public class NamingStratagyTest {
    public static void main(String[] args) {
        String colName = DefaultNamingStrategy.INSTANCE.columnName("UserName");
        System.out.println(colName); // UserName
        colName = ImprovedNamingStrategy.INSTANCE.columnName("UserName");
        System.out.println(colName);// user_name
    }
}

选择适合您需求的命名策略。

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