I got this problem when I try to update an instance of an object using cascade.
The situation is described below:
<class name="Object1" table="OBJECT1_TABLE" lazy="true" >
<id name="code" column="CD_OBJ1" >
<generator class="sequence">
<param name="sequence">SQ_CD_OBJ1</param>
</generator>
</id>
<timestamp name="timestamp" column="TS_OBJ1" />
<many-to-one class="Object2" name="object2" column="CD_OBJ2" cascade="all" unique ="true" not-null="false"/>
</class>
<class name="Object2" table="OBJECT2_TABLE" lazy="true">
<id name="code" column="CD_OBJ2" >
<generator class="sequence">
<param name="sequence">SQ_CD_OBJ2</param>
</generator>
</id>
<timestamp name="timestamp" column="TS_OBJ2" />
<bag name="telephones" table="OBJ2_TEL_TABLE" cascade="all" lazy="true" >
<key column="CD_OBJ2"/>
<many-to-many class="Telephone" column="CD_TEL" unique="true"/>
</bag>
</class>
<class name="Telephone" table="TELEPHONE">
<id name="code" column="CD_TEL" >
<generator class="sequence">
<param name="sequence">SQ_CD_TEL</param>
</generator>
</id>
<timestamp name="timestamp" column="TS_TEL" />
</class>
public class Object1 {
private int code;
private Timestamp timestamp;
private Object2 object2;
public Object1() {
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
ths.code = code;
}
public Timestamp getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public Object2 getObject2() {
return this.object2;
}
public void setObject2(Object2 object2) {
this.object2 = object2;
}
}
public class Object2 {
private int code;
private Timestamp timestamp;
private Collection<Telephone> telephones;
public Object2() {
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
ths.code = code;
}
public Timestamp getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public Collection<Telephone> getTelephones() {
return this.telephones;
}
public void setTelephones(Collection<Telephone> telephones) {
this.telephones = telephones;
}
}
public class Telephone {
private int code;
private Timestamp timestamp;
public Telephone() {
}
public int getCode() {
return this.code;
}
public void setCode(int code) {
ths.code = code;
}
public Timestamp getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
}
The problem occurs where I try to set execute the following code:
Object1 object1 = getInstance();//object1.getObject2() is not null
object1.setObject2(null);
session.update(object1);
Firstly, the foreign key CD_OBJ2 of OBJ2_TABLE in the table OBJ1_TABLE is set to null. But Hibernate doesn't delete the row
of CD_OBJ2 on table OBJ2_TABLE, although I set cascade="all".
So I have implemented an interceptor to delete the instance of Object2, because there's no sense of this dirty being in the
database.
public class InterceptorImplementation implements Interceptor {
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[]
propertyNames, Type[] types) {
if (entity instanceof Object1) {
for (int i = 0; i < propertyNames.length; i++) {
if (propertyNames[i].equals("object2")) {
Object2 newObj2 = (Object2)currentState[i];
Object2 oldObj2 = (Object2)previousState[i];
if (oldObj2 != null && newObj2 == null) {
session.delete(oldObj2);
return true;
}
}
}
}
return false;
}
}
Hibernate tries to delete firstly the telephones, instead of deleting the references to the object2 in the join table.
The correct form would be like this:
delete from OBJ2_TEL_TABLE where CD_OBJ2 = ?
delete from TELEPHONE where CD_TEL = ?
delete from OBJECT2_TABLE where CD_OBJ2 = ?
And Hibernate does this way:
delete from TELEPHONE where CD_TEL = ?
So I got the following error:
17:34:55,656 DEBUG SQL:310 - delete from TELEPHONE where CD_TEL=?
17:34:55,656 DEBUG AbstractBatcher:364 - preparing statement
17:34:55,656 DEBUG IntegerType:59 - binding '51345' to parameter: 1
17:34:55,734 DEBUG AbstractBatcher:284 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
17:34:55,750 DEBUG AbstractBatcher:392 - closing statement
17:34:55,765 DEBUG JDBCExceptionReporter:49 - could not delete: [Telephone#51345] [delete from TELEPHONE where CD_TEL=?]
java.sql.SQLException: ORA-02292: integrity constraint (ADMSIGA_UFPE.FK_TELF_TELF_ASSE_RELC_INTR) violated - child record
found
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:582)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1986)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1144)
at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2152)
at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:2035)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2876)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:609)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2085)
at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2227)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:59)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:675)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:293)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at siga.bd.TransacaoHB.confirmar(TransacaoHB.java:57)
at siga.bd.SmartTransacao.confirmar(SmartTransacao.java:96)
at siga.bd.Controlador.confirmarTransacao(Controlador.java:122)
at siga.fachada.ControladorEstruturaFisica.atualizarInstituicaoEnsinoSuperior(ControladorEstruturaFisica.java:6790)
at siga.Teste.main(Teste.java:151)
17:34:55,781 WARN JDBCExceptionReporter:57 - SQL Error: 2292, SQLState: 23000
17:34:55,781 ERROR JDBCExceptionReporter:58 - ORA-02292: integrity constraint (ADMSIGA_UFPE.FK_TELF_TELF_ASSE_RELC_INTR)
violated - child record found
17:34:55,796 ERROR AbstractFlushingEventListener:277 - Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: could not delete: [siga.util.telefone.Telefone#51345]
at org.hibernate.exception.ErrorCodeConverter.handledNonSpecificException(ErrorCodeConverter.java:92)
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:80)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2099)
at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2227)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:59)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:675)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:293)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at siga.bd.TransacaoHB.confirmar(TransacaoHB.java:57)
at siga.bd.SmartTransacao.confirmar(SmartTransacao.java:96)
at siga.bd.Controlador.confirmarTransacao(Controlador.java:122)
at siga.fachada.ControladorEstruturaFisica.atualizarInstituicaoEnsinoSuperior(ControladorEstruturaFisica.java:6790)
at siga.Teste.main(Teste.java:151)
Caused by: java.sql.SQLException: ORA-02292: integrity constraint (ADMSIGA_UFPE.FK_TELF_TELF_ASSE_RELC_INTR) violated - child
record found
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:582)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1986)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1144)
at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2152)
at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:2035)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2876)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:609)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.hibernate.persister.entity.BasicEntityPersister.delete(BasicEntityPersister.java:2085)
... 15 more
|