为什么Spring Data / Hibernate在表名为"productDef"的情况下查询"product_def"表?

21 浏览
0 Comments

为什么Spring Data / Hibernate在表名为"productDef"的情况下查询"product_def"表?

我正在使用Spring Boot 2.3.4 / Spring Data / Hibernate / MySQL 8。

我的数据库表名为"productDef"。我有一个实体对象"ProductDef"。

当我执行"list all"查询时,我收到以下错误消息...

java.sql.SQLSyntaxErrorException: 表'mydatabase.product_def'不存在

为什么Hibernate在寻找"product_def"表?

我尝试给实体添加注解@Table(name="productDef"),但没有起作用。

如果我将数据库表重命名为"product_def",我的代码就可以工作。但不幸的是,我不能为我的项目重命名数据库表。

我错过了什么?

更新:

解决方案是实现一个自定义的PhysicalNamingStrategy,防止"productDef"变成"product_def"。

然而,尽管这对@Table名称注解起作用,但对@Column名称注解没有起作用。

根据这个讨论线程,忽略@Column名称注解是一个bug。

在application.properties中添加以下内容:

spring.jpa.properties.hibernate.physical_naming_strategy=com.myapp.dao.RealNamingStrategyImpl

并实现以下类:

package com.myapp.dao;
import java.io.Serializable;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class RealNamingStrategyImpl extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable {
    public static final PhysicalNamingStrategy INSTANCE = new PhysicalNamingStrategyStandardImpl();
    @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());
    }
}

0
0 Comments

问题出现的原因是Hibernate默认使用的命名策略将驼峰命名转换为下划线命名,所以在查询"productDef"表时会转为查询"product_def"表。解决方法是配置自定义的命名策略,可以通过配置文件或者注解来实现。

在Hibernate中,默认的命名策略是由JPA 2.0定义的,即physicalNamingStrategy。它将驼峰命名转换为下划线命名。可以通过配置"hibernate.physical_naming_strategy"来指定使用的命名策略。

在Spring中,可以通过配置属性"spring.jpa.hibernate.naming.physical-strategy"来配置命名策略。

默认情况下,Spring Boot使用的是SpringPhysicalNamingStrategy作为物理命名策略。它与Hibernate 4的表结构相同,将所有的点替换为下划线,并将驼峰命名也替换为下划线。默认情况下,所有表名都是小写的,但如果需要,可以覆盖该标志。

然而,如果希望强制Hibernate使用表名"productDef",需要实现自定义的命名策略。这是因为Hibernate有两种策略类型,分别是"implicit"和"physical"。注解可以绕过"implicit"策略,但无论是否有注解,所有的操作都会经过"physical"策略。因此,需要重写"physical"策略来达到目的。

在实现了自定义的SpringPhysicalNamingStrategy后,表名的问题得到了解决。然而,对于列名仍然存在同样的问题。经过一番调查发现,这是一个已知的bug,注解被忽略了。可以在该讨论线程中找到更多信息。

提问者在另外的问题中提到了关于"ignored"注解的问题,并发表了相关讨论。

0