简体   繁体   中英

Hibernate : Foreign key constraint violation problem

I have a com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException in my code (using Hibernate and Spring) and I can't figure why. My entities are Corpus and Semspace and there's a many-to-one relation from Semspace to Corpus as defined in my hibernate mapping configuration :

<class name="xxx.entities.Semspace" table="Semspace" lazy="false" batch-size="30">
    <id name="id" column="idSemspace" type="java.lang.Integer" unsaved-value="null">
        <generator class="identity"/>
    </id>
    <property name="name" column="name" type="java.lang.String" not-null="true" unique="true" />
    <many-to-one name="corpus" class="xxx.entities.Corpus" column="idCorpus"
                insert="false" update="false" />
    [...]
</class>
<class name="xxx.entities.Corpus" table="Corpus" lazy="false" batch-size="30">
    <id name="id" column="idCorpus" type="java.lang.Integer" unsaved-value="null">
        <generator class="identity"/>
    </id>
    <property name="name" column="name" type="java.lang.String" not-null="true" unique="true" />
</class>

And the Java code generating the exception is :

Corpus corpus = Spring.getCorpusDAO().getCorpusById(corpusId);
Semspace semspace = new Semspace();
semspace.setCorpus(corpus);
semspace.setName(name);
Spring.getSemspaceDAO().save(semspace);

I checked and the corpus variable is not null (so it is in database as retrieved with the DAO) The full exception is :

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`xxx/Semspace`, CONSTRAINT `FK4D6019AB6556109` FOREIGN KEY (`idCorpus`) REFERENCES `Corpus` (`idCorpus`))
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:931)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2941)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1623)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1715)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3249)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1541)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1455)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1440)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:102)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2638)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:642)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:639)
at xxx.dao.impl.AbstractDAO.save(AbstractDAO.java:26)
at org.apache.jsp.functions.semspaceManagement_jsp._jspService(semspaceManagement_jsp.java:218)
[...]

The foreign key constraint has been created (and added to database) by hibernate and I don't see where the constraint can be violated. The table are innodb and I tried to drop all tables and recreate it the problem remains...

EDIT : Well I think I have a start of answer... I change the log level of hibernate to DEBUG and before it crash I have the following log

insert into Semspace (name, [...]) values (?, [...])

So it looks like it does not try to insert the idCorpus and as it is not null it uses the default value "0" which does not refers to an existing entry in Corpus table...

I get confused w/ the association mappings all the time. Review the association needed and the hibernate mapping config used to create the assiocation.

http://docs.jboss.org/hibernate/core/3.5/reference/en/html/associations.html

is a great recipe book of associations.

Old post, I know, but I found all of these solutions lacking.

In the hibernate mapping, you have:

<many-to-one name="corpus" class="xxx.entities.Corpus" column="idCorpus"
            insert="false" update="false" />

You should change the second line to:

<many-to-one name="corpus" class="xxx.entities.Corpus" column="idCorpus"
            cascade="save-update" not-null="true" insert="true" />

Seems simple enough. The first line of your exception clearly states that the violation is from the column idCorpus to another column in another table, Corpus/idCorpus .

You should be able to access the database directly to figure out what the constraint is. I suspect it's a simple lookup on the other table.

Then print out the value that you're using in the supplied Java code and, hopefully, voila, you'll know what value you're trying to insert in Semspace that isn't in Corpus.

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails ( diaz/Semspace , CONSTRAINT FK4D6019AB6556109 FOREIGN KEY ( idCorpus ) REFERENCES Corpus ( idCorpus ))

我知道的老帖子,但是如果另一方是@ManyToOne的话,我有这个并通过将@ManyToMany更改为@OneToMany来修复它。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM