org.springframework.dao.DataIntegrityViolationException misreporting cause?

2022-09-04 03:03:30

我正在使用休眠来插入到mysql表中,其中所有列都被定义为不为空。它在多个列上具有唯一的主键和另一个唯一索引。

我收到以下错误:

org.springframework.dao.DataIntegrityViolationException: 無法執行 JDBC batch update;SQL [插入到MY_TABLE(col1, col2, col3, col4, ID_) values (?, ?, ?, ?, ?)];约束 [空]

此错误位于客户日志中,我无法自己重现问题,因此我无法进行调试以查看 insert 语句中的值。

我的理解是,“约束[null]”意味着违反了“not null”约束。但是,查看我的代码,我看不到任何可能的方式,即在插入时任何数据都可以为空,除非休眠尝试插入空ID(这将是休眠中非常糟糕的错误,因此似乎不太可能)。

但是,我可以看到如何发生违反唯一约束的情况。该消息是否有可能具有误导性,而我实际上遇到了唯一的密钥冲突?“constraint[null]”是否总是意味着违反了非 null 约束?


答案 1

如果你在Spring源代码中搜索DataIntegrityViolationException的构造函数的调用方,你会发现它被调用:org.springframework.orm.hibernate3.SessionFactoryUtils

return new DataIntegrityViolationException(ex.getMessage()  + "; SQL [" + jdbcEx.getSQL() +
                "]; constraint [" + jdbcEx.getConstraintName() + "]", ex);

因此,异常是由违反的约束引起的,并且是 JDBC 异常返回的约束的名称。因此,您应该责怪MySQL驱动程序没有在JDBC异常中填充违反的约束名称。但违反的约束可以是任何约束,而不一定是约束。nullnot null


答案 2

你可以直接从Hibernate的异常类型中获取Constain名称。用

getConstraintName

属性以获取数据库约束名称。

} catch (ConstraintViolationException conEx) {
            if (conEx.getConstraintName().contains("PROJECT_UK")) {
                //TODO Project Entity is violating it's constrain

我使用了包含,因为我希望此应用在多个数据库架构上运行。默认情况下,getConstraintName 带有 DB 名称,如

MyDBName.ConstrainName


推荐