Using JPA over Hibernate 3.6.2 (disabled lvl 2 cache).
Relationship:Parent < Child < Toy, CascadeType.ALL, FetchType.EAGER from parent to child. FetchType.LAZY from child to parent.
["<" is for one-to-many, biderectional]
Child => Child
["=>" is many-to-many, unidirectional]
e.g., if Child 2 borrowed Toy 1 from Child 1 then Toy 1 belongs to Child 2 now and there's a link from Child 2 to Child 1.
Use case:In session 1: Created:
Parent 1
|------- Child 1
|------- Child 2 ------- Toy 1
In session 2: Loaded the four objects created in session 1, removed Child 1 (and Toy 1 respectively). Parent 1 and Child 2 remain.
In session 1 (again): Whilst trying JPA's refresh() method on Parent 1
Code:
entityManager.refresh(parent); // this should work but throws instead whilst trying to refresh cache for deleted entities.
Trace log snippet:...
DEBUG [o.h.e.Collections] - Collection found: [foo.Parent.children#1], was: [foo.Parent.children#1] (initialized)
DEBUG [o.h.e.Collections] - Collection found: [foo.Child.children#1], was: [foo.Child.children#1] (initialized)
DEBUG [o.h.e.Collections] - Collection found: [foo.Child.toys#1], was: [foo.Child.toys#1] (initialized)
DEBUG [o.h.e.Collections] - Collection found: [foo.Child.children#2], was: [foo.Child.children#2] (initialized)
DEBUG [o.h.e.Collections] - Collection found: [foo.Child.toys#2], was: [foo.Child.toys#2] (initialized)
...
DEBUG [o.h.e.d.EvictVisitor] - evicting collection: [foo.Child.children#1]
DEBUG [o.h.e.d.EvictVisitor] - evicting collection: [foo.Child.toys#1]
DEBUG [o.h.l.Loader] - loading entity: [foo.Child#1]
...
DEBUG [o.h.e.l.CollectionLoadContext] - no collections were found in result set for role: foo.Child.toys
DEBUG [o.h.e.StatefulPersistenceContext] - initializing non-lazy collections
DEBUG [o.h.l.Loader] - done entity load
DEBUG [o.h.e.AbstractEntityManagerImpl] - mark transaction for rollback
javax.persistence.EntityNotFoundException: No row with the given identifier exists: [foo.Child#1] at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1196)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:745)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:713)
...
There's a workaround - detaching(evicting) 'Parent 1' from the cache explicitly:
Code:
entityManager.detach(parent); // - this works of course but shouldn't Hibernate do this itself?
Parent tmp = entityManager.find(Parent.class, parent.getId());
Question: Is it expected for refresh() not to detect deleted objects and throw? Does it mean that detach() + find() is the proper way to do "full" refresh? It would be strange because refresh() works just fine if I add objects but throws if I delete any.
Thanks in advance.