we have a strange problem with hibernate we can't explain.
What we have:
The hibernate mappings for classes A and B look like:
<hibernate-mapping>
<class name="A" table="A" lazy="false">
<id name="id" column="ID" type="java.lang.Integer">
<generator class="org.hibernate.id.enhanced.TableGenerator">
<param name="segment_value">a</param>
</generator>
</id>
<version name="olVersion" column="VERSION" type="integer" unsaved-value="negative" />
<joined-subclass name="SubA1" table="SUB_A1" lazy="false">
<key column="ID_A" foreign-key="FK_SUB_A1_A"/>
<property name="p1" column="p1" length="255" unique="true"/>
<property name="p2" column="p2" length="255" not-null="true" />
</joined-subclass>
<joined-subclass name="SubA2" table="SUB_A2" lazy="false">
<key column="ID_A" foreign-key="FK_SUB_A2_A"/>
<property name="p3" column="p3" length="255" not-null="true" unique="true" />
<property name="p4" column="p4" length="4000" />
</joined-subclass>
</class>
</hibernate-mapping>
and
<hibernate-mapping>
<class name="B" table="B" lazy="false">
<cache usage="read-write"/>
<id name="id" column="ID" type="java.lang.Integer">
<generator class="org.hibernate.id.enhanced.TableGenerator">
<param name="segment_value">b</param>
</generator>
</id>
<version name="olVersion" column="VERSION" type="integer" unsaved-value="negative" />
<joined-subclass name="SubB1" table="SUB_B1" lazy="false">
<key column="ID_B" foreign-key="FK_SUB_B1_B"/>
<many-to-one name="subA" column="ID_A" not-null="false" update="false" foreign-key="FK_SUB_B1" lazy="false" class="A"/>
</joined-subclass>
</class>
</hibernate-mapping>
Now the question: sometimes hibernate loads items of SubA2 as instances of SubA1 by loading items of SubB1, but not all items will casted wrong, only a few of them and everytime not the same items.
Maybe someone can explain, what is going wrong or what is wrong with our hibernate mappings.
Thank you in advance.
Ps. This problem occurs for:
I didn't try for other configuration.
Unfortunately, I don't have sample application, but I also can't give the source code of the real applicaton.
I think your hibernate mappings are right. So if you have errors I am sure it happens on casting time. I faced with this problem many times, and I always solved it using Visitor Pattern.
Another advantage of Visitor Pattern is that you don't need to force lazy=false
, because it solves perfectly real type of a proxied object.
I recommend you to create a Visitor
class which implements two visit
methods for every A concrete subclass:
void visit(SubA1 object)
void visit(SubA2 object)
The implementation of both methods is the code you want to execute when A instance is a SubA1 or a SubA2 concrete class. I put void return, but obviously you can change it.
On the other hand, A class has to add an abstract visit method public abstract void visit(Visitor visitor);
. Once again, I put void
return, but you have to adapt it to the return type of visit
methods.
SubA1 and SubA2 has to implement this method as follows:
public void accept(Visitor visitor) {
visitor.visit(this);
}
This way, when you run this code objectA.accept(visitor)
Java has to resolve in runtime the real type of objectA
without casting, and with no errors. It really works, I am using it for years with Hibernate 3.x and 4.x.
Here you have a really nice article Proxy Visitor Pattern where you can find how to apply visitor pattern to hibernate when using proxied and non proxied objects.
Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With