Hello, everybody
I encountered a strange exception when using <any> mapping together with collections on the "any" side. The codes is as following, and the exception is at the end of the post:
Cable.java
Code:
package test.any;
/**
* @hibernate.class table="test_any_cable"
*/
public class Cable {
private Long id;
private int length;
/**
* @return
*
* @hibernate.id generator-class="native"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @return
*
* @hibernate.property
*/
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}//class Cable
CRTMonitor.java
Code:
package test.any;
import java.util.HashSet;
import java.util.Set;
/**
* @hibernate.class table="test_any_crtmonitor"
*/
public class CRTMonitor {
private Long id;
private String model;
private int size;
private Set cables = new HashSet();
/**
* @return
*
* @hibernate.id generator-class="native"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @return
*
* @hibernate.property
*/
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
/**
* @return
*
* @hibernate.property
*/
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/**
* @return
*
* @hibernate.set lazy="true" cascade="all"
* @hibernate.collection-key column="monitor_id"
* @hibernate.collection-one-to-many class="test.any.Cable"
*/
public Set getCables() {
return cables;
}
public void setCables(Set cables) {
this.cables = cables;
}
}//class CRTMonitor
MicroWaveOven.java
Code:
package test.any;
/**
* @hibernate.class table="test_any_microwaveoven"
*/
public class MicroWaveOven {
private Long id;
private String model;
private int power;
private Cable cable;
/**
* @return
*
* @hibernate.id generator-class="native"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @return
*
* @hibernate.property
*/
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
/**
* @return
*
* @hibernate.property
*/
public int getPower() {
return power;
}
public void setPower(int power) {
this.power = power;
}
/**
* @return
*
* @hibernate.many-to-one cascade="all"
*/
public Cable getCable() {
return cable;
}
public void setCable(Cable cable) {
this.cable = cable;
}
}//class MicroWaveOven
The testing code is as follows:
Code:
session = HibernateUtil.openSession();
tx = session.beginTransaction();
CRTMonitor monitor = new CRTMonitor();
monitor.setModel("Acer");
monitor.setSize(17);
Cable cable1 = new Cable();
cable1.setLength(1);
session.persist(cable1);
monitor.getCables().add(cable1);
cable1 = new Cable();
cable1.setLength(7);
session.persist(cable1);
monitor.getCables().add(cable1);
session.persist(monitor);
Cable cable2 = new Cable();
cable2.setLength(10);
session.persist(cable2);
MicroWaveOven oven = new MicroWaveOven();
oven.setModel("Haier");
oven.setPower(300);
oven.setCable(cable2);
session.persist(oven);
Box box1 = new Box();
box1.setShipping("Los Angeles");
box1.setThing(monitor);
session.persist(box1);
box1Id = box1.getId();
Box box2 = new Box();
box2.setShipping("Washington D.C.");
box2.setThing(oven);
session.persist(box2);
box2Id = box2.getId();
System.out.println("Done with inserting.");
tx.commit();
session.close();
session = HibernateUtil.openSession();
tx = session.beginTransaction();
Box box1 = (Box) session.load(Box.class, box1Id);
box1.setShipping("Miami");
session.update(box1);
Box box2 = (Box) session.load(Box.class, box2Id);
box2.setShipping("Hongkong");
session.update(box2);
System.out.println("Done with updating.");
tx.commit();
session.close();
The exception occurs in the second session when trying to update the Box object:
Code:
[junit] (hibernate.AssertionFailure 22 ) an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
[junit] org.hibernate.AssertionFailure: collection [test.any.CRTMonitor.cables] was not processed by flush()
[junit] at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:205)
[junit] at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:332)
[junit] at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:28)
[junit] at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:993)
[junit] at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:340)
[junit] at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
[junit] at test.any.TestAny.testInsertThenUpdate(TestAny.java:119)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[junit] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[junit] at java.lang.reflect.Method.invoke(Method.java:585)
[junit] at junit.framework.TestCase.runTest(TestCase.java:154)
[junit] at junit.framework.TestCase.runBare(TestCase.java:127)
[junit] at junit.framework.TestResult$1.protect(TestResult.java:106)
[junit] at junit.framework.TestResult.runProtected(TestResult.java:124)
[junit] at junit.framework.TestResult.run(TestResult.java:109)
[junit] at junit.framework.TestCase.run(TestCase.java:118)
[junit] at junit.framework.TestSuite.runTest(TestSuite.java:208)
[junit] at junit.framework.TestSuite.run(TestSuite.java:203)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:297)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeInVM(JUnitTask.java:1072)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:682)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1434)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:632)
[junit] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
[junit] at org.apache.tools.ant.Task.perform(Task.java:364)
[junit] at org.apache.tools.ant.Target.execute(Target.java:341)
[junit] at org.apache.tools.ant.Target.performTasks(Target.java:369)
[junit] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
[junit] at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
[junit] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
[junit] at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
[junit] at org.apache.tools.ant.Main.runBuild(Main.java:668)
[junit] at org.apache.tools.ant.Main.startAnt(Main.java:187)
[junit] at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
[junit] at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
[junit] org.hibernate.AssertionFailure: collection [test.any.CRTMonitor.cables] was not processed by flush()
[junit] at org.hibernate.engine.CollectionEntry.postFlush(CollectionEntry.java:205)
[junit] at org.hibernate.event.def.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:332)
[junit] at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:28)
[junit] at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:993)
[junit] at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:340)
[junit] at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
[junit] at test.any.TestAny.testInsertThenUpdate(TestAny.java:119)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[junit] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[junit] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[junit] at java.lang.reflect.Method.invoke(Method.java:585)
[junit] at junit.framework.TestCase.runTest(TestCase.java:154)
[junit] at junit.framework.TestCase.runBare(TestCase.java:127)
[junit] at junit.framework.TestResult$1.protect(TestResult.java:106)
[junit] at junit.framework.TestResult.runProtected(TestResult.java:124)
[junit] at junit.framework.TestResult.run(TestResult.java:109)
[junit] at junit.framework.TestCase.run(TestCase.java:118)
[junit] at junit.framework.TestSuite.runTest(TestSuite.java:208)
[junit] at junit.framework.TestSuite.run(TestSuite.java:203)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:297)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeInVM(JUnitTask.java:1072)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:682)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1434)
[junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:632)
[junit] at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
[junit] at org.apache.tools.ant.Task.perform(Task.java:364)
[junit] at org.apache.tools.ant.Target.execute(Target.java:341)
[junit] at org.apache.tools.ant.Target.performTasks(Target.java:369)
[junit] at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
[junit] at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
[junit] at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
[junit] at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
[junit] at org.apache.tools.ant.Main.runBuild(Main.java:668)
[junit] at org.apache.tools.ant.Main.startAnt(Main.java:187)
[junit] at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
[junit] at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
It's strange that, the exception only occurs when the "Any" object contains a collection mapping, such as CRTMonitor has a set of Cable objects; but will not occur when it (such as MicroWaveOven) contains only a many-to-one mapping to Cable object, the update operation can succeed.
The exception can be suppressed if "Any" object collection is preloaded by (before update box1):
Code:
CRTMonitor monitor = (CRTMonitor)box1.getThing();
monitor.getCables();
//update box1 now
Any idea?