All entries for Wednesday 30 November 2005
November 30, 2005
So I was debugging a problem with some code and I discovered this little gem:
Assume you have the following hierarchy:
– ClassInterface (use as proxy in mapping files)
– AbstractClass implements ClassInterface (used as the persistent class)
– ClassImpl extends AbstractClass (mapped as subclass of AbstractClass)
Load an instance of ClassImpl ala "ClassImpl ci = (ClassImpl)session.load(AbstractClass.class, someId)"
Now if you are going to compare two instances (using hashCode/equals) then guess what; if you implement that logic in ClassImpl it won't work. You must implement that logic in the abstract class that you have specified in the mapping file.
This is all to do with the joy that is cglib; even though the instance you are loading will eventually be a ClassImpl (based on the discriminator) CGLIB claims not to know that until it is fully initialised :(
OK, what happens if you try and load an instance of ClassImpl? Same thing. The equals method AbstractClass is used.
I have also run into situations with hibernate where code works if you step through, but not if you run it without debugging. I can only think that stepping through is maybe causing toString to initialise the object properly, hence subclass logic is utilised, but I cannot reproduce it.
Lame. Understandable, but lame.
To be fair; hibernate is great. It rocks, but it is not transparent* :)