Hibernate: 数据库模式验证: 缺失表格

6

我尝试从MSSQL Server 2016数据库中读取现有表。如果我进行验证(hbm2ddl.auto-->验证),我会收到一个“模式验证:缺少表”的异常。

我比较了生成的Hibernate SQL代码(如果我从验证切换到使用MSSQL Server本身可以生成的SQL代码进行更新)。它看起来是相同的:

-- generated SQL from Hibernate 
create table Artikel (
       Artnr int not null,
        Artgruppe CHAR(5),
        Bezeichnung VARCHAR(30) not null,
        EPreis money,
        primary key (Artnr)
    )

-- generated SQL from MSSQL Server 2016
CREATE TABLE [dbo].[Artikel](
    [Artnr] [int] NOT NULL,
    [Bezeichnung] [varchar](30) NOT NULL,
    [EPreis] [money] NULL,
    [Artgruppe] [char](5) NULL,
PRIMARY KEY CLUSTERED 
(
    [Artnr] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Java模型如下:
@Entity
@Table(name = "Artikel")
public class Article {
    @Id
    @Column(name = "Artnr", nullable=true)
    private int article_id;

    @Column(name = "Bezeichnung", columnDefinition="VARCHAR(30)", nullable=false)
    private String description;


    @Column(name = "EPreis", columnDefinition = "money", nullable=true)
    private BigDecimal price;

    @Column(name = "Artgruppe", columnDefinition="CHAR(5)")
    private String article_group;


    // getters and setters
    // ... not shown here
}

那么问题出在哪里呢?也许与货币类型有关?

谢谢和问候

5个回答

6

这里有两个问题:表和列名的大小写敏感性以及命名策略

在错误消息中注意表名,注意大写和小写字母。当我面对这个问题时,我的假设是表名不区分大小写。至少在编写 SQL 查询时是如此(我使用的是 MSSQL)。但是显然,JPA关心大小写敏感性。

关于命名策略,如果没有指定任何策略,则 JPA 将使用一些大写字母将表和列名转换为全小写和下划线分隔的名称(例如 User_Detail 转换为 dbo.user_detail)。如果您在注释中提供表和列名,并且不希望 JPA 将它们转换,则将以下 2 行添加到您的 application.properties 文件中:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

你说得对,这帮助我缩小了问题搜索范围。我在下面添加了一个“CamelCaseToUnderscoresNamingStrategy”的答案。 - gavenkoa

4

最后我解决了这个问题。我替换了

@Table(name = "Artikel")
public class Article {

对抗

@Table(name = "Artikel", schema="dbo")
public class Article {

但是dbo是用户的默认架构,所以不需要schema="dbo"也可以工作。也许这是某种bug?如果有更多信息,请告诉我...


2

我在属性中添加了以下内容,现在它可以正常工作:

spring.jpa.properties.hibernate.default_schema=dbo

0
对于那些使用org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy作为spring.jpa.hibernate.naming.physical-strategy的人来说:这个实现会将每个标识符的大小写都转换成小写,甚至是从@Table(name="")中获取的名称!
您可以通过以下方式禁用此行为:
public class CustomCamelCaseToUnderscoresNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {
    @Override
    protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
        return false;
    }
}

或者甚至定义自己的行为:

public class CustomCamelCaseToUnderscoresNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {

    private static final Pattern LOWER_RE = Pattern.compile("[a-z]");

    /**
     * Lowercase only if there is lowercase (like if entity name is "User" we want a table with name "user").
     * Do not change the name if it is all uppercase.
     */
    @Override
    protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
        if (LOWER_RE.matcher(name).find()) {
            name = name.toLowerCase(Locale.ROOT);
        }
        return new Identifier( name, quoted );
    }
}

-1

由于这是指向另一个线程的链接,因此最好作为评论而不是答案。 - DanielM

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