I have an application that I use as my "laboratory for learning". Everything worked well for a mapped class until I added a business method that changes two properties (Integer and String) then updates the object. Even though no collection nor reference to collection is changed, Hibernate throws an exception:
Don't change the reference to a collection with cascade="all-delete-orphan": eventmanager.Registration.attendancy. Anybody knows what could be the cause or solution to this?
This is an RMI call, so the object is actually a serialized version, if that somehow matters.
Hibernate version: 3.0.2 3.1
Mapping documents:
Registration.hbm.xml (snippet)
Code:
<?xml version="1.0"?>
<!DOCTYPE ...>
<hibernate-mapping default-lazy="false">
<class name="eventmanager.Registration" table="registration">
<id name="barcode" type="java.lang.String" />
<!-- ... -->
<set name="attendancy" cascade="all-delete-orphan" table="registration_attendancy">
<key column="barcode" not-null="true" />
<one-to-many class="eventmanager.Attendancy"/>
</set>
</class>
</hibernate-mapping>
Attendancy.hbm.xml (snippet)
Code:
<?xml version="1.0"?>
<!DOCTYPE ...>
<hibernate-mapping default-lazy="false">
<class name="eventmanager.Attendancy" table="registration_attendancy">
<id name="id" column="attendancy_id" type="java.lang.Integer">
<generator class="identity"/>
</id>
<property name="barcode" insert="false" update="false" />
<!-- ... -->
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():I have inlined two methods for easier understanding.
Code:
public boolean lostBadge(Registration reg) throws ApplicationException {
if (reg.getReprint())
return false;
reg.setReprint(true);
createBarcode(reg); // changes the 'barcode' property
update(reg);
return true;
}
public void update(Registration reg) throws ApplicationException {
Transaction tx = null;
try {
Session session = currentSession();
tx = session.beginTransaction();
session.update(reg);
tx.commit();
}
catch (RuntimeException rt) { /* exception handling */ }
finally {
closeSession();
}
}
Full stack trace of any exception that occurs:
org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": eventmanager.Registration.attendancy
at org.hibernate.engine.Collections.prepareCollectionForUpdate(Collections.java:226)
at org.hibernate.engine.Collections.processReachableCollection(Collections.java:185)
at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:37)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:124)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:195)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at eventmanager.persistence.RegistrationEngine.update(RegistrationEngine.java:260)
at eventmanager.persistence.RegistrationEngine.lostBadge(RegistrationEngine.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
... (RMI call trace)
Name and version of the database you are using: MySQL 4.1.11-