@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的主要内容,如果未能解决你的问题,请参考以下文章

JPA 自动建表- @Column

Symfony UniqueEntity vs UniqueConstraint vs unique=true

Flask-用户角色及权限

flask简单的注册功能

flask登陆功能与权限

SQLAlchemy - Column详解