问题 org.springframework.dao.DataIntegrityViolationException误报原因?


我正在使用hibernate插入一个mysql表,其中所有列都定义为非null。它具有唯一的主键和多个列上的另一个唯一索引。

我收到以下错误:

org.springframework.dao.DataIntegrityViolationException:不能   执行JDBC批量更新; SQL [插入MY_TABLE(col1,col2,col3,   col4,ID_)值(?,?,?,?,?)];约束[null]

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

我的理解是“约束[null]”意味着违反了“非空”约束。但是,看看我的代码,我看不到任何可能的方式,任何数据在插入时都可能为null,除非hibernate试图插入一个空ID(这在hibernate中是一个非常糟糕的bug,所以似乎不太可能)。

但是,我可以看到如何发生违反唯一约束的情况。该消息是否可能具有误导性,我实际上是在获得一个独特的密钥违规? “constraint [null]”是否始终意味着违反了非空约束?


912
2017-11-05 19:32


起源

我猜不出为什么除非a引起异常 not null 列试图给出一个 null 值。顺便说一句,如果您使用的是较旧版本的JDBC驱动程序,请不要忘记将其替换为最新版本(10+)。否则,它将在以后引起其他问题。 - Lion
这是mysql 5.1,而不是Oracle。 - Dana


答案:


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

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

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


11
2017-11-05 20:21



我明白了,mysql没有给出名字但非常有帮助,这非常令人讨厌!我只是假设null意味着一个非空约束。谢谢。 - Dana


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

getConstraintName

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

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

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

MyDBName.ConstrainName


1
2017-08-15 11:36



ConstraintViolationException中不再有getConstraintName()方法 - Anna