Tim Holloway wrote:I think that "user" is a detached object. Lazy references cannot be resolved when an object is detached - in fact a dummy object is inserted in place of the lazy object or collection to alert you to that fact.
If that's what happened, you'll need to re-attach "user' by doing a JPA merge() before you can access its lazy collection of Post's. Note that merge does not return the same object back that you pass to it. Once merged, discard the original User object and use the merged User object instead.
Tim Holloway wrote:I'm rusty on JPA - people owe me money, so I found other things to do until they start paying me again.
However, I believe that merge() is an EntityManager method.
You'll know when you attempt to reference a detached lazy object. In fact, I think it throws an Exception if you even try.
Tim Holloway wrote:If you use CrudRepository or JPARepository (or a subclass of one of them), then the EntityManager is used internally by their implementations. In my case, I use DAOs as repositories, so I inject an EntityManager via @PersistenceContext.
This might help: https://dzone.com/articles/accessing-the-entitymanager-from-spring-data-jpa
Tim Holloway wrote:Your setup is very different than mine, and I'm not sure I really understand it.
I think you were asking if it was "wrong" to access an associated object when it was lazy-fetched and detached. It's not wrong, as such, but since the lazy object wasn't fetched before detachment, it will throw an exception. If you need to resolve an associated lazy object before detaching, there's no formal method, but simply referencing that object will fetch it and replace the dummy with the actual object. In other words, to force resolution of a Department record for an Employee, just do something throw-away like "thisEmployee.getDepartment().getId()". For collections (OneToMany, ManyToMany), iterate the collection. For best results, resolve both the forward and backward links, if they exist.
Let me describe how I do things. It's fairly simple and it has worked well for me.
I have basically 3 tiers for persistence in my JPA apps.
1. The bottom tier is the Entity classes themselves.
2. The next-level tier is DAOs. My DAOs are finders and CRUD methods for single-table operations. Or in some cases, where parent/child relationships are tightly bound, parent and child entity DAOs.
3. The top level is persistence services.
Most of my apps don't work on a single table at a time, they work on a network of related table objects. So the persistence services are responsible for making the necessary collection of data available to the non-persistence layer (business logic), and for persisting changes made to that collection of data ("working set"). Both the service tier and the DAO tier are transactional at the class level, although DAOs inherit the transaction context of the service method that calls them. To make things more predictable, DAOs are never called directly by business logic, only by persistence methods.
The service methods work with attached objects, so if I need to expand a working set (which is always detached), I'll pass that set to a service method that re-attaches, resolves whatever lazy dependencies I need resolved, and then returns a new detached instance of the working set with the new relationships in it. The service methods use the DAOs for the low-level work, so all DAOs have an EntityManager injected into them (I haven't been using the Spring CRUD repo). The service methods never use an EntityManager directly.
Tim Holloway wrote:Auto-wiring is used at construction time and it generally does not work well when trying to connect dynamic objects, such as data pulled from a database. At least I think that's what you are getting at.