I would like to challenge the documentation:
"No-proxy" fetching: a single-valued association is fetched when the instance variable is accessed. Compared to proxy fetching, this approach is less lazy; the association is fetched even when only the identifier is accessed. It is also more transparent, since no proxy is visible to the application. This approach requires buildtime bytecode instrumentation and is rarely necessary.
I would argue that in most applications, avoiding proxies is entirely necessary. I have found way too many problems with proxies
1. Putting partially loaded objects into sessions causes many problems when processed by another controller action in the application at a later time. This is annoying because it's not easily testable. You basically have to play with your app in the browser and see it bomb. Fixing the problem is not always so trivial either.
2. Unexpected equals() and hashCode() when called by frameworks can cause crashes. For example @Valid executed by Spring MVC will initiate an equals() or hashCode() call, which will bomb the application. This is because the lazily-loaded properties are not equaling properly, or are not producing the hash codes. No such problem exists when lazy=false.
3. equals() and hashCode() when called by frameworks or by your applications either return false when it SHOULD be true. I'm not sure why this is the case, but I am finding myself doing entity.getId() = anotherEntity.getId() rather than saying entity.equals(anotherEntity). I really I didn't have to do this, because the first few times I came across this, I spent several hours trying to figure out what the heck was wrong.
4. Using deserializers like Jackson cause unexpected errors that are NOT easy to debug. Even if you carefully use @JsonIgnore or @JsonIgnoreProperties, getHandler() and other get*() methods on the Proxy object will be processed by jackson! Argh!
Overall, I think proxies for lazy-loading add so much mental load and ruin the regular flow of Java programming that they should be avoided by default.
I am so stressed by the level of complexity of Proxies. When lazy=false is the default, Hibernate is a joy to use, but really stinks when it comes to performance. When lazy=true is used, performance is good, but then you have so many programming pitfalls. If there was a way to get lazy=false coding experience when lazy=true... that would totally fix the problem.
|