Vinze
Vinze

Reputation: 2539

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...

Upvotes: 5

Views: 24443

Answers (4)

Ryan Shillington
Ryan Shillington

Reputation: 25197

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" />

Upvotes: 1

jon077
jon077

Reputation: 10449

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.

Upvotes: 6

gub
gub

Reputation: 5239

Old post I know, but I had this and fixed it the end by changing @ManyToMany to @OneToMany if the other side is @ManyToOne.

Upvotes: 0

paxdiablo
paxdiablo

Reputation: 882596

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))

Upvotes: 1

Related Questions