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
的详细信息
我在使用 Hibernate 时遇到问题。 我正在通过 Flyway 迁移创建 tables。 下面显示了部分初始迁移脚本的片段。 该脚本确实 运行(我可以在 DEBUG 模式下看到它)。
在脚本 运行ning 之后,Hibernate 的验证器似乎没有使用我通过 javax.persistence
.
为了清楚起见,这里有一些遗漏的实体:
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.
@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
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