Hy,
I am having a "Solve failed to lazily initialize a collection of role.... exception" in jpa. I understand that outside a session, when you want to retrieve a lazy collection if there is not session bound you will get this error, fine. But what I dont understand is if I have this spring controller(the code is not 100% correct, is just to explain my case):
@Controller
@Autowired
EnterpriseService enterpriseService ;
public List<Enterprise> getAll(){
List<Enterprise> enterprises = enterpriseService.getAll();
for(Enterprise enterprise:enterprises){
enterprise.getEmployees();
}
return enterprises;
}
When I call "enterprise.getEmployees()", I know there is not anymore a session but why when I try to do "enterprise.getEmployees()", why enterprise is treated like a jpa entity and not just like a normal bean?, I mean; for what I understand a jpa entity is treated like this inside a session but outside like in this case it should be treated like a normal java bean so the calling to enterprise.getEmployees() should be treated like the calling of a get method of a java bean and should not throw any lazy exception....
Maybe is because spring controller treats the enterprise objects like jpa entities and not just only like java beans? this behaviour is specific to spring controllers?
Thanks
An entity returned from an
EntityManager
is not necessarily an instance of your entity class, but a proxy class which extends your class. In many cases the same is true for the persistent properties of such entities (especially for those annotated with (One/Many)To(One/Many)).For example if you are using field based access:
Here the JPA provider will create a proxy class that extends
Enterprise
and remembers the previous state from the DB somehow. In addition it will change theemployees
list to its own implementation ofList
(which does not need to extendArrayList
).Because the proxy class can "overwrite" your methods, it could know when you are calling
getEmployees()
and check for the session. But I don't think that this would happen here, as the method is not annotated with any JPA specific annotation.In addition some frameworks like
Hibernate
do support byte code enhancement or byte code instrumentation. That changes the implementation of your class (in byte code) and replaces every access toemployees
with some provider specific code. I don't know if Spring JPA provides this, but this could lead to check for a session.Otherwise any call to
enterprise.getEmployees()
should just return the current value ofemployees
- without any check for the session and without the LazyInitializationException.But calling
enterprise.getEmployees().size()
will try to initialize the list and check for the session - this could lead to the mentioned exception.If you are using property based access things are a little bit different:
Here the proxy class will not delegate to your implementation, but overwrite the
getEmployees()
method and return its ownList
implementation, without changingemployees
. Thus here it is possible to get a LazyInitalizationException forenterprise.getEmployees()
.Remark: This describes how most JPA implementations are working - but as this is implementation specific some unusual frameworks could do things differently.