在Hibernate / JPA中,如何判断ConstraintViolationException是PK,FK还是唯一键冲突?

时间:2019-03-10 13:16:35

标签: java hibernate jpa

我正在开发一种具有通用处理方式的通用方法,以将实体保留在数据库中,但是我很难知道ConstraintViolationException是否违反了主键,外键或唯一键

public Collection<T> salvar(final Collection<T> e) {        
        try {
            return dao.salvar(e);
        } catch (ConstraintViolationException e1) {
            if (PK_violation) {
                handle PK error 
            } else if (FK_violation) {
                handle FK error
            }
        }

    }

我怎么知道我的异常是哪种类型的违规(PK_violation或FK_violation)?

谢谢

1 个答案:

答案 0 :(得分:1)

您将需要解析异常消息以提取触发异常的键的名称。一旦有了索引名称,就必须能够基于命名约定或基于数据库架构的元数据来识别索引的类型。

以下是一些方便的日志示例:

Duplicate entry '1023' for key 'PRIMARY'
Duplicate entry 'test-user-817fe6b0-587a-4003-9dec-8d2ea8f87cad' for key 'UKwqsqlvajcne4rlyosglqglhk'

第一种情况是主键冲突-在这种情况下,“ PRIMARY”似乎是显示的键名。第二个是唯一键冲突-在我们的例子中,我们的唯一键名称以“ UK”开头,因此我们可以使用它来确定违反该索引的类型。

因此,将正则表达式应用于具有键名的组的e1.getMessage(),提取该组值,应用另一个正则表达式或其他业务逻辑,以基于本地确定要处理的索引类型命名约定或通过查询数据库以获取有关索引的信息。

您可以查询数据库以获取有关异常中提到的索引的性质的信息。如果要使用数据库查询,则可以在启动时进行单个查询,以收集有关所有索引的元数据,并在其余的运行中使用此缓存的数据。

如果使用带注释的Java类来指定JPA映射,则可以利用这些注释(可能带有注释处理器,或者在运行时通过反射)来提取有关索引的信息。特别是,javax.persistence.Id注释会产生主键,而javax.persistence.Table具有uniqueConstraints属性,该属性利用javax.persistence.UniqueConstraint来定义唯一约束。在异常处理时尝试执行此操作将很困难,因为您可能无法确定哪个实体对象触发了违规-在一般情况下,有许多实体同时刷新到数据库;我不知道确定哪个触发问题的方法。

我不知道任何允许您从EntityManager或持久性单元提取此信息的JPA API。