Hibernate 在启动时执行 DDL 验证时不使用 @Table。使用 Flyway 和 TestContainer

Hibernate not using @Table when doing DDL validation on startup. Using Flyway and TestContainers

我在使用 Hibernate 时遇到问题。 我正在通过 Flyway 迁移创建 tables。 下面显示了部分初始迁移脚本的片段。 该脚本确实 运行(我可以在 DEBUG 模式下看到它)。

在脚本 运行ning 之后,Hibernate 的验证器似乎没有使用我通过 javax.persistence.

提供的实体的 table 名称

为了清楚起见,这里有一些遗漏的实体:


import javax.persistence.*;


@Entity
@Table(name = "IngredientCategories")
public class IngredientCategory implements IEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(nullable = false, length = 128)
    private String name;

    ...
}
CREATE TABLE `IngredientCategories` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `description` varchar(255) DEFAULT NULL,
  `name` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

查看日志,Flyway 迁移是 运行 然后 之后 我得到休眠验证错误。

2020-10-24 11:22:11.952 DEBUG 91583 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully completed migration of schema `test` to version 1 - init
2020-10-24 11:22:11.961 DEBUG 91583 --- [           main] o.f.c.i.s.JdbcTableSchemaHistory         : Schema History table `test`.`flyway_schema_history` successfully updated to reflect changes
2020-10-24 11:22:11.970  INFO 91583 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 1 migration to schema `test` (execution time 00:00.107s)
2020-10-24 11:22:11.972 DEBUG 91583 --- [           main] org.flywaydb.core.Flyway                 : Memory usage: 82 of 354M
2020-10-24 11:22:12.088  INFO 91583 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-10-24 11:22:12.125  INFO 91583 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.20.Final
2020-10-24 11:22:12.237  INFO 91583 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-10-24 11:22:12.350  INFO 91583 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2020-10-24 11:22:12.998  WARN 91583 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [ingredient_categories]
2020-10-24 11:22:12.998  INFO 91583 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-10-24 11:22:13.420  INFO 91583 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2020-10-24 11:22:13.428  INFO 91583 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-10-24 11:22:13.434 ERROR 91583 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [ingredient_categories]

我无法确定这是休眠问题、Flyway 问题还是测试问题。

这只是“启动”应用程序的测试:

@SpringBootTest
@Testcontainers
class DataApplicationTests {

    @Test
    void contextLoads() {
    }

}

我环顾四周,可以看到很多人在 Spring 2x 之前遇到了一个问题,其中 tables 在 flyway 生成模式之前得到了验证……但似乎已被“修复”,默认为 Flyway migrations are 运行 before.

我认为问题所在的行显示 Hibernate 需要一个 table 名称 Schema-validation: missing table [ingredient_categories] 因此,当 运行 构建 context/beans.

时,似乎没有使用 javax.constaint.Table @Table(name="IngredientCategories") 注释

应用程序属性并不过分令人兴奋...我正在使用 TestContainers:

#=========INTEGRATION TESTS========#

## Using TestContainers
spring.datasource.url=jdbc:tc:mysql:8.0.22:///

# Validate Schema
spring.jpa.hibernate.ddl-auto = validate

logging.level.org.flywaydb=DEBUG

来自官方doc

By default, Spring Boot configures the physical naming strategy with SpringPhysicalNamingStrategy. This implementation provides the same table structure as Hibernate 4: all dots are replaced by underscores and camel casing is replaced by underscores as well. By default, all table names are generated in lower case, but it is possible to override that flag if your schema requires it.

For example, a TelephoneNumber entity is mapped to the telephone_number table.

于是IngredientCategories变成了ingredient_categories。对于数据库 table 名称一般约定使用 snake-case。您可以在 snake case

中使用名称创建 table
CREATE TABLE `ingredient_categories`

或者如果您更喜欢使用 Hibernate 5 的默认设置,请设置以下 属性:

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

那么您的 table 的名字仍然是 IngredientCategories,如 @Table 注释中给出的那样。关于 Hibernate 5 Naming Strategy Configuration

的详细信息