14

我正在使用休眠插入到所有列都定义为非空的 mysql 表中。它有一个唯一的主键和几个列上的另一个唯一索引。

我收到以下错误:

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

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

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

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

4

2 回答 2

13

如果你在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约束。

于 2012-11-05T20:21:20.193 回答
2

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

获取约束名称

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

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

我使用 contains 是因为我希望这个应用程序在多个数据库模式上运行。默认情况下 getConstraintName 带有数据库名称,如

MyDBName.ConstrainName

于 2013-08-15T11:36:41.277 回答