@Column(unique = true) 产生一个 WARN o.h.engine.jdbc.spi.SqlExceptionHelper:SQL 警告代码:0,SQLState:00000
Posted
技术标签:
【中文标题】@Column(unique = true) 产生一个 WARN o.h.engine.jdbc.spi.SqlExceptionHelper:SQL 警告代码:0,SQLState:00000【英文标题】:@Column(unique = true) produces a WARN o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Warning Code: 0, SQLState: 00000 【发布时间】:2018-08-23 07:07:40 【问题描述】:在Spring Boot 2.0.0.RELEASE 的项目中,当我第一次启动应用程序时,在创建数据库表时,我收到以下警告消息:
Hibernate: alter table if exists bpermission drop constraint if exists UK_qhp5om4s0bcb6j0j8pgcwitke
2018-03-14 11:32:03.833 WARN 15999 --- [ restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Warning Code: 0, SQLState: 00000
2018-03-14 11:32:03.833 WARN 15999 --- [ restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper : constraint "uk_qhp5om4s0bcb6j0j8pgcwitke" of relation "bpermission" does not exist, skipping
注意约束名称 -> uk_qhp5om4s0bcb6j0j8pgcwitke
...下面我看到这个被记录了:
Hibernate: alter table if exists bpermission add constraint UK_qhp5om4s0bcb6j0j8pgcwitke unique (label)
Hibernate: alter table if exists bpermission drop constraint if exists UK_ow4uw3orjjykeq869spvqtv6u
从上一条消息中我们可以看到 Hibernate 正在添加约束 UK_qhp5om4s0bcb6j0j8pgcwitke
,与警告中显示的相同,但第一个字母是大写的。这与label
属性中的unique
约束有关(参见下面的类)。
收到此警告的(可能)涉及的实体是:
BPermission
@Data
@NoArgsConstructor(force = true)
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true, exclude = "roles")
@ToString(callSuper = true, exclude = "roles")
@Entity
public class BPermission extends GmsEntity
@NotNull()
@NotBlank()
@Size(max = 255)
@Pattern(regexp = "someDefinedRegexp")
@Column(unique = true, nullable = false, length = 255)
private final String name;
@NotNull()
@NotBlank()
@Size(max = 255)
@Column(unique = true, nullable = false, length = 255)
private final String label;
@ManyToMany(mappedBy = "permissions")
private Set<BRole> roles;
BPermission
与
BRole
@Data
@NoArgsConstructor(force = true)
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true, exclude = "permissions")
@ToString(callSuper = true, exclude = "description", "permissions")
@Entity
public class BRole extends GmsEntity
@NotNull()
@NotBlank()
@Size(max = 255)
@Pattern(regexp = "someDefinedRegexp"))
@Column(unique = true, nullable = false, length = 255)
private final String label;
@Size(max = 10485760)
@Column(length = 10485760)
private String description;
private Boolean enabled = false;
@ManyToMany
@JoinTable(
name = "brole_bpermission",
joinColumns = @JoinColumn(name = "brole_id"),
inverseJoinColumns = @JoinColumn(name = "bpermission_id")
)
private Set<BPermission> permissions;
public void addPermission(BPermission... p)
// code for adding permissions
public void removePermission(BPermission... p)
// code for removing permissions
public void removeAllPermissions()
// code for removing permissions
它们被映射到PostgreSQL9.5.11数据库如下:
相关的弹簧配置有:
spring.datasource.url = jdbc:postgresql://127.0.0.1/mydbname
spring.datasource.username = postgres
spring.datasource.password = postgres
spring.datasource.driver-class-name = org.postgresql.Driver
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation = true
spring.jpa.open-in-view = false
我收到所有带有@Column(unique = true)
注释属性的实体的警告消息
问题
为什么会抛出此警告?也许……一个错误? 我怎样才能摆脱它?当然,警告有时一点也不坏,但我觉得这里要么没有必要,要么表明“应该做不同的事情”,尽管SQLCode 0000 表示“成功完成”。
PS:我使用的是Lombok。
【问题讨论】:
create、create-drop、validate 和 update 是 spring.jpa.hibernate.ddl-auto = update 的选项,也许尝试将其更改为 validate,因为您总是在启动您的应用程序 【参考方案1】:Spring Boot 2.0(Hibernate 5?)显然使用DROP_RECREATE_QUIETLY
作为unique constraint update strategy 作为默认选项确实是错误的,因为每次启动应用程序时它所做的只是删除唯一索引并再次创建它。如果您使用包含一些(大量?)数据的数据库,我可以想象使用此选项开始一切的速度会有多慢。
在这种情况下,当您在空数据库上启动时,删除索引的操作会产生警告,您可以在日志中看到该警告。当您重新开始时,警告会消失,但它会默默地执行重新创建索引的昂贵操作。
要禁用此功能,您需要使用以下参数将策略切换回RECREATE_QUIETLY
:
# for plain hibernate
hibernate.schema_update.unique_constraint_strategy=RECREATE_QUIETLY
# for spring data
spring.jpa.properties.hibernate.schema_update.unique_constraint_strategy=RECREATE_QUIETLY
【讨论】:
谢谢。很有用!我将您的答案标记为正确,因为这可以直接处理问题而无需使用其他工具(如 @Oleksandr Shpota 的,这也是一个很好的答案)【参考方案2】:这看起来像一个错误。
我建议您通过 flywaydb
等更高级别的迁移工具创建架构,并让 hibernate 仅验证生成的架构。它集成在 spring-boot 中,设置起来非常简单,参见the documantation 和examples。
好处是您可以完全控制架构,升级休眠时不会发生意外的架构更改。
通常仅在开发过程中使用自动模式生成,而不是在生产过程中。您可以找到更多关于它为何如此重要的详细信息here。
进行这样的设置后,您可以让 hibernate 仅在开发模式下生成模式,但 flyway 将负责其余情况。
【讨论】:
未来的读者可能不同意添加一个新工具来解决这个问题,但就我而言,没关系。我发现flyway非常有用。谢谢!以上是关于@Column(unique = true) 产生一个 WARN o.h.engine.jdbc.spi.SqlExceptionHelper:SQL 警告代码:0,SQLState:00000的主要内容,如果未能解决你的问题,请参考以下文章