Hello,
has anyone had the same problem?
I work with a mapping of 200 persistent classes where the most important classes live in two hierarchies, connected by an association at the highest level. I tried several ways to get around the problem described below. Meanwhile I believe it might be a current limitation of hibernate - although not a fundamental one (please let me know if I'm wrong in either direction).
The essential setting to reproduce the error is as follows: given is a hierarchy of three Classes:
Partner, Person, Organisation
Persons and Organisations are Partners, but a Person is not an Organisation and an Organisation is not a Person.
All three classes are mapped with proxy Interfaces (IPartner, IPerson, IOrganisation) in order to avoid ClassCastExceptions when lazily loading Partners.
All three classe implement the method istPerson() (which is a kind of a custom instanceof method). It is important that this method does not need any persistent data.
Then:
Quote:
Only one of the following calls to istPerson() produces a Class Cast exception:
Code:
IPartner p1 = (IPartner) s.load(Partner.class, person1.getId());
p1.istPerson();
IPartner p2 = (IPartner) s.load(Partner.class, organisation1.getId());
p2.istPerson();
The debugger shows me, that the proxy of Partner implements all three interfaces (which all contain the method istPerson())
It seems that hibernate chooses the first Interface containing a method with a matching signature. But then the chosen method belongs to a specific Interface e.g. IPerson, causing an Error if invoked on a target implementign an other Interface, e.g. IOrgansiation (this ist true even if the Interface contains a Method with the same signature).
Note: No Class Cast Exception arises if we call getName() – which is a Method retrieving persistent data - on p1 an p2.
I would appreciate any comments on this
lnz
I'm working with hibernate 3.0.5
enclosed: mappings, java code and exception
Code:
<class name="Partner"
proxy="IPartner"
table="PARTNER"
discriminator-value="partner">
<id name="id" type="long">
<column name="id" not-null="true"/>
<generator class="native"/>
</id>
<discriminator column="HIBERNATE_TYPE"
type="string" />
<property name="name">
<column name="NAME"/>
</property>
</class>
<subclass name="Person"
extends="Partner"
proxy="IPerson"
discriminator-value="person">
</subclass>
<subclass name="Organisation"
extends="Partner"
proxy="IOrganisation"
discriminator-value="organisation">
</subclass>
public class Person extends Partner implements IPerson {
Person() {}
public Person(String name) {
super(name);
}
public boolean istPerson() {
return true;
}
public boolean istOrganisation() {
return false;
}
}
public class Partner implements IPartner {
private Long id;
private String name;
Partner(){
}
public Partner(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean istPerson() {
return false;
}
public boolean istOrganisation() {
return false;
}
}
public class Organisation extends Partner implements IOrganisation {
public Organisation(String name) {
super(name);
}
Organisation() {}
public void setDatumOrganisation(Date datumOrganisation) {
this.datum = datumOrganisation;
}
public boolean istPerson() {
return false;
}
public boolean istOrganisation() {
return true;
}
}
java.lang.ClassCastException
at at.hibernate3.polyquery3.IOrganisation$$FastClassByCGLIB$$c29c383e.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:137)
at org.hibernate.proxy.HibernateProxy$$EnhancerByCGLIB$$6a493d5b.istPerson(<generated>)
at at.hibernate3.polyquery3.MainTest.testLazyPoly(MainTest.java:217)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)