java中对mysql操作 关于Cannot add or update a child row: a foreign key constraint fails的错误

话不多说,直接上错误

ERROR: HHH000346: Error during managed flush [could not execute statement]
org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:112)
….
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at luoqi.com.Bid.ff(Bid.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)…..

Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`rocky`.`bid`, CONSTRAINT `bidders` FOREIGN KEY (`bidder`) REFERENCES `representative` (`account`) ON DELETE CASCADE ON UPDATE CASCADE)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:931)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)

其中的 at luoqi.com.Bid.ff(Bid.java:81) 错误对应代码如下:

即transaction实例ts,对数据库的操作使用commit()函数提交

这是在数据库插入一条bid数据时出现的问题

一共涉及到三个表:

投标表:bid(主键id)    公司代表表:representative(主键id)    总账户表:sum_acccount(主键id)

其中bid.bidders属性拥有外键,对应representative.acccount

同时representative.account属性也拥有外键,对应sum_account.id

这个bug改了一天,现在整理一下bug修复历程:

1.因为使用Hibernate自动生成的dao类

其中有save(),delete(),findxxx()等函数,封装了对数据库的操作,而且对数据库的操作也是基于hql的,面向对象的数据库操作。在这个对bid插入数据的操作中,用sumAccount对象替代了representative的account属性,用representative对象替代了bid的bidder对象。由于对这个dao类生成方法的不熟悉,起初怀疑时hql语句本身的设计问题,因为也没有报hql语句错误之类的信息

2.之后在网上找了许多解决方法,但是没有适用的。其中针对root error的翻译,解释是对子表进行操作时,建立外键的值,在父表中不可找到。但是本身bid表中的Bidder属性就是使用父类对象替代的,这就很矛盾,挣扎了半天,最后选择先做其他的。

3.寻找身边的朋友,最后找到问题的根源,就是数据库设计的问题。在bid连接外键向representative表的时候,对应属性不是representative的主键,而是account。虽然account和id在实际上都是唯一的,在设计数据库表的时候就没有想太多,导致了这个概念上的错误,不满足基本范式要求。

4.大佬也提供了一种思路,将representative的account属性建立索引,并且设置unique属性,希望通过索引时值的唯一性来获得将bidder的外键连接到representative主键的同样效果

总结:

1.针对这个错误,明白添加数据时要顾及父表中是否存在对应数据,而且数据库设计要满足基本要求,外键的设置必须是对应父表的主键

2.不要习惯性的相信类似的代码在不同机子上跑出的结果一样。起初,做注册的朋友说他的representative注册可以正常用,也就是代表表和账户表之间的连接没有问题,我就想当然的认为投标表和代表表的连接同样也不会有问题。应该时刻保持怀疑的态度谨慎对待这类问题,找出其中的不同

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注