I’m trying to create a helper method in an entity class that can be called when the entity is removed. The idea is that this ‘onRemove()’ method will unlink itself from the owning parent entity, effectively this:
This doesn’t actually work. Confusingly if I tell my IDE to inline that method into my unit test, it actually does what is intended. In the unit test it looks like:
ChildEntity child = eman.find(...);
Putting a debugger on it I was able to figure out why this is, and I’m wondering if there’s something I should be doing differently.
What’s happening is that with the inlined code in the unit test the ‘child’ object is a HibernateProxy and so the call to ‘.remove()’ is seeing that proxy. But from inside ‘onRemove()’ I pass ‘this’, which is no longer a proxy but the proxy’s target - the concrete entity class itself. PersistentSet doesn’t account for this and simply calls ‘HashSet.remove()’, which doesn’t find the entity since it’s a different object (the HashSet itself contains proxies of course).
I should note that I don’t implement ‘equals()’ or ‘hashCode()’. And the ‘children’ collection is lazy.
This ‘onRemove()’ method is to be called from generic code, so having it figure out the various parent/child associations for each entity class would be less than ideal, of course.
Is there a way to get this to work?
Would it be difficult for PersistentSet to account for this by substituting the cached proxy when appropriate?
The simple solution is, just implement equals and hashCode based on the primary key.
I think then I’d risk running afoul of this for other cases where it is eager:
Is that correct?
I always use this approach and I never ran into the issue described on this ticket. So unless you do something very exotic, which I doubt, I think you can ignore the ticket.
There’s probably 10’s of thousands of lines of application code, and hundreds of entities using this infrastructure already so I’m not sure I’d bet against there being something ‘exotic’ already existing or coming soon!
That said, is it possible the entity ‘id’ is unlikely to encounter this? For all entities the ‘id’ is just a sequence-generated long.
Is it known a little more precisely what the circumstances are under which the problem described in that ticket occurs?
It appears this is only relevant if your id and thus hashCode depends on state that might not have been initialized yet. If you always depend on basic or embeddable attributes though, this is fine. I guess the issue in the ticket is that an id contains an entity and for that entity type the hashCode implementation is missing, but I didn’t check it out too deeply yet. Like I wrote, I use this approach since ages and never had issues. Just give it a try. You don’t have to do this in every entity, just create a mapped super class and put that stuff there (assuming you have a generically named
getId getter method to access the id).
Thanks for the extra info, I’ll give it a try.
Everything inherits from a single base entity class where the ‘id’ is coded for all entities; it’ll have to be coded there.