I tend to use Hibernate in combination with Spring framework and it's declarative transaction demarcation capabilities (e.g., @Transactional).
As we all known, hibernate tries to be as non-invasive and as transparent as possible, however this proves a bit more challenging when employing lazy-loaded
relationships.
I see a number of design alternatives with different levels of transparency.
fetchType=FetchType.EAGER)
Hibernate.initialize(proxyObj);
initialize
, other implementations are not guaranteed to provide any equivalent. Model
objects themselves (using either dynamic proxy or @Transactional
) loadData()
and loadDataWithDeps()
loadDataWithA()
, ...., loadDataWithX()
byId()
operations findZzzById(zid)
, and then getYyyIds(zid)
instead of z.getY()
loadData(id, fetchProfile);
Did I miss any option?
Which is your preferred approach when trying to minimize the impact of lazy-loaded
relationships in your application design?
(Oh, and sorry for WoT)
Hibernate now can "lazy-load" the children, which means that it does not actually load all the children when loading the parent. Instead, it loads them when requested to do so. You can either request this explicitly or, and this is far more common, hibernate will load them automatically when you try to access a child.
Lazy loading (also known as asynchronous loading) is a design pattern commonly used in computer programming and mostly in web design and development to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program's operation if properly and appropriately used.
1. Working with lazy associations. By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
Eager Loading is a design pattern in which data initialization occurs on the spot. Lazy Loading is a design pattern which is used to defer initialization of an object as long as it's possible.
As we all known, hibernate tries to be as non-invasive and as transparent as possible
I would say the initial assumption is wrong. Transaparent persistence is a myth, since application always should take care of entity lifecycle and of size of object graph being loaded.
Note that Hibernate can't read thoughts, therefore if you know that you need a particular set of dependencies for a particular operation, you need to express your intentions to Hibernate somehow.
From this point of view, solutions that express these intentions explicitly (namely, 2, 4 and 7) look reasonable and don't suffer from the lack of transparency.
I am not sure which problem (caused by lazyness) you're hinting to, but for me the biggest pain is to avoid losing session context in my own application caches. Typical case:
foo
is loaded and put into a map;foo.getBar()
(something that was never called before and is lazy evaluated);So, to address this we have a number of rules:
OpenSessionInViewFilter
for webapps);try/finally
) so subclasses don't have to think about it;This, as you can see, is indeed nowhere close to non-invasive and transparent. But the cost is still bearable, to compare with the price I'd have to pay for eager loading. The problem with latter is that sometimes it leads to the butterfly effect when loading single referenced object, let alone a collection of entities. Memory consumption, CPU usage and latency to mention the least are also far worse, so I guess I can live with it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With