Spring Boot JPA 不会在查询中的表中添加模式名称

Tim*_*Tim 6 hibernate jpa spring-boot

据我所知(例如,从这里),如果我为我的实体指定架构,那么它应该在创建查询时使用该架构名称。

所以,如果我有一个实体:

@Entity
@Table(name="proposalstatuses",schema="sales")
public class ProposalStatus implements Serializable {
    private static final long serialVersionUID = 1L;
    private int proposalStatusID;
    private String proposalStatusName;

    public ProposalStatus() {}

    public ProposalStatus(String proposalStatusName) {
        this.proposalStatusName = proposalStatusName;
    }

    @Id
    @Column(name="pk_proposalstatusid")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getProposalStatusID() {
        return proposalStatusID;
    }

    public void setProposalStatusID(int proposalStatusID) {
        this.proposalStatusID = proposalStatusID;
    }

    @Column(name="proposalstatusname", unique=true, nullable=false)
    public String getProposalStatusName() {
        return proposalStatusName;
    }

    public void setProposalStatusName(String proposalStatusName) {
        this.proposalStatusName = proposalStatusName;
    }
}
Run Code Online (Sandbox Code Playgroud)

那么我希望 Hibernate 生成它的查询,如select ... from sales.proposalstatuses. 然而,我看到的是:

select proposalst0_.pk_proposalstatusid as pk_propo1_8_, proposalst0_.proposalstatusname as proposal2_8_ 
from proposalstatuses proposalst0_ 
order by proposalst0_.proposalstatusname asc
Run Code Online (Sandbox Code Playgroud)

对于这种情况,这不是什么大问题,但现在我希望能够使用不同模式中的表的连接,但这是失败的,因为它认为这些表不存在(并且它们在默认情况下不存在)模式)。

所以,我有一个具有多个模式的数据库(一个连接)。如何让 Hibernate 在引用表时使用模式名称?看起来它应该非常简单,但我一定错过了一些东西。
谢谢!

我正在使用 Spring Boot 1.5.7,它使用 Hibernate JPA 2.1 和 Hibernate Core 5.0.12。 如果我使用 H2 数据源,这确实有效。如果 MySQL 是数据源,我只会看到问题。

我已阅读有关在默认架构中为要引用的表创建视图的信息。但是,这不是一个可行的选择,因为我必须创建很多视图;似乎 Hibernate 应该能够毫不费力地处理这个问题。

以下是 application.properties 中的配置设置:

spring.datasource.url=jdbc:mysql://localhost/sales?verifyServerCertificate=false&useSSL=true
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
Run Code Online (Sandbox Code Playgroud)

更改 url 中架构的名称允许我访问该架构中的数据,但除了 url 中列出的架构之外,我无法访问任何其他架构。

Tim*_*Tim 6

我缺少的关键是配置和数据库类型。在 MySQL 中,数据库和模式之间没有真正的区别。使用 @Table 注释中的 schema 属性,它引用“真实”模式,但不是 MySQL 中定义的那样。这解释了为什么 schema 属性适用于 H2 数据库而不适用于 MySQL。

@Table(name="SCHEMA_NAME.TABLE_NAME") 注释最初不起作用,因为我的数据源 URL 中有一个默认架构。网址需要是

spring.datasource.url=jdbc:mysql://localhost?verifyServerCertificate=false&useSSL=true
Run Code Online (Sandbox Code Playgroud)

通过此更改,MySQL 一切正常。

进一步说明,为了使其也适用于 H2,请确保您没有定义hibernate.default_schema属性。


小智 6

我刚刚将一个应用程序从使用手工EntityManager配置的配置迁移到 Spring Boot 2.0,然后这些问题立即出现。

正确的做事方式是使用

@Table(name="proposalstatuses",catalog = "sales")
Run Code Online (Sandbox Code Playgroud)

...正如@suneet-khurana 上面建议的那样。请注意,MySQL 不支持模式,您需要catalog改用。

但是,在我们的情况下,这需要更改大量实体,在短期内,我希望避免代码更改并使用配置恢复到将模式名称嵌入到表名称中的旧行为。

因此,经过一些研究和调试后,我发现明确设置以下属性可以解决问题:

spring.jpa.properties.hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Run Code Online (Sandbox Code Playgroud)

看起来 Spring Boot JPA 中的默认实现是SpringPhysicalNamingStrategy,它通过用下划线替换所有点来清理名称。


Abd*_*han 3

处理此问题的方法是为具有名称冲突的实体指定架构。

使用

@Table(name="TABLE_NAME", schema="SCHEMA_NAME")
Run Code Online (Sandbox Code Playgroud)

或者

@Table(name="SCHEMA_NAME.TABLE_NAME")
Run Code Online (Sandbox Code Playgroud)