首页 > 解决方案 > 如何使用 H2 数据库在 DataIntegrityViolationException 上获取约束名称?

问题描述

我在生产中使用 PostgreSQL,在开发中使用 H2。

DataIntegrityViolationException在 SpringBoot ControllerAdvice 中处理,我想获取驱动此异常的约束的名称。

我的表是这样定义的:

@Table(name = "user", uniqueConstraints = {
    @UniqueConstraint(name = "users_unique_email_idx", columnNames = {"email"})
})
class User ...

当我使用 PostgreSQL 时,它可以完美运行。我得到异常的原因是 aConstraintViolationException然后得到约束名称。类似的东西:

((ConstraintViolationException)ex.getCause()).getConstraintName()

但是使用 H2 数据库我找不到获取约束名称的方法。DataIntegrityViolationException不包含或ConstraintViolationException约束名称。使用 H2 时,错误消息为空:

DataIntegrityViolationException:
  could not execute statement; SQL [n/a]; constraint [null];
Caused by:
  JdbcSQLException: Violation dindex unique ou clé primaire: {0}
  Unique index or primary key violation: {0}; SQL statement:

注意:在我的 H2INFORMATION_SCHEMA.CONSTRAINTS表中,我对电子邮件字段的约束存在并且具有良好的名称 ( users_unique_email_idx)

这是 H2 数据库的限制吗?
如何在 H2 中启用约束名称?

谢谢 !

标签: javahibernateh2

解决方案


答案是 Hibernate 根据数据库消息翻译 PostgreSQL 约束异常。
在类org.hibernate.dialect.PostgreSQL81Dialect中,我们可以找到一个对象TemplatedViolatedConstraintNameExtracter来检查来自数据库的消息是否包含字符串violates unique constraint。如果您更改了数据库的语言,hibernate 无法翻译异常,因为它是基于英语的。这就是 Hibernate 找不到约束名称的原因。有2个解决方案:

  1. 将环境变量LC_MESSAGES更改为英文。来自 PostgreSQL 的消息将以英文显示。
  2. 扩展 PostgreSQL 方言类(有少数类取决于 PostgreSQL 版本)并覆盖getViolatedConstraintNameExtracter. 创建您自己的ViolatedConstraintNameExtracter对象,而不是翻译您的语言。

在 H2 数据库案例中根据上述检查。


推荐阅读