精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-03-12
最近在做项目的时候遇到一个问题,客户在使用Hibernate往数据库插入记录时总是遇到这样的错误信息: Caused by: net.sf.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at net.sf.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:73) at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29) at net.sf.hibernate.impl.BatcherImpl.convert(BatcherImpl.java:328) at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:135) at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2438) at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2396) at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2261) ... 3 more Caused by: java.sql.BatchUpdateException: Duplicate entry '42808-0' for key 1 at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:894) at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:294) at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54) at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:128) ... 7 more
而这个问题在本地测试时并未出现,开始时猜测是客户的数据库结构与本地的数据库结构不同造成的,可是经过比对,客户的数据库结构和环境与本地完全一样。 接下来分析数据库中的数据库中的数据,发现在几个表中存在垃圾数据。为了说明情况,我们假定A表中有垃圾数据,A与B、C表通过外键关联(用的是MySQL4.0,我自己不太了解,似乎没有5.0来的那么严格),然而,有意思的是在B、C表中并没有相关的数据,而且A中相关记录的PK明显大于B、C表中的最大PK。 由于B、C两个表的主键由Hibernate生成,采用的生成机制是identity,因此,主键的生成实际上是依赖于MySQL数据库本身。对于MySQL而言,数据库本身会维护本身的index,如果数据库的当前的最大的index是2000,即使删除了后一千条数据,新生成的数据也应该从2001开始。反过来,既然在A表中存在大于B、C表中最大PK的记录,那么说明A中这些个对应记录的至少曾经在B、C表存在过,那么在重新生成时,不应该出现重复的记录出现才对啊! 继续检查代码,发现A表是在B、C生成的时候自动生成的,但是删除的时候却忘了删除,但是即使这样,也不该出现先前提到的情况啊! 询问客户的数据库的情况,才知道,客户的数据库是新装了之后用以前的SQL备份文件恢复的!这下终于找到症结了,使用SQL恢复时并将相应表的Index生成记录也恢复,以至于垃圾数据与现有的新生成的数据冲突了! 二话不说,先删除垃圾数据,本来想一条SQL搞定的,无奈4.0不支持增量查询,delete的where字句也不能使用in\not in作为谓词,晕,写程序吧,经过一个小时左右,各个功能搞定!OK 后来想起来,这个问题在平常使用时经常存在,总结一下吧:
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 1760 次