Hibernate Lazy Load Application Design

I usually use Hibernate in combination with the Spring framework and declarative transaction demarcation (e.g. @Transactional ).

As we all know, hibernate tries to be non-invasive and transparent, however this proves a bit more complicated when using lazy-loaded .




I see a number of design alternatives with different levels of transparency.

  • Make relationships not lazy (e.g. fetchType=FetchType.EAGER)
    • These vioalites are the whole idea of โ€‹โ€‹lazy loading.
  • Initialize collections using Hibernate.initialize(proxyObj);
    • This implies a relatively high association with the DAO.
    • Although we can define an interface with initialize , other implementations do not guarantee the provision of any equivalent.
  • Add transaction behavior to persistent Model objects (using a dynamic proxy or @Transactional ).
    • I have not tried using a dynamic proxy approach, although I have never tried to get @Transactional to work with persistent objects. Probably due to the fact that sleep mode works with a proxy server.
    • Loss of control in transactions
  • Provide lazy / non-lacy APIs like loadData() and loadDataWithDeps()
    • Makes the application know when to use this procedure, again tight connection
    • Method overflow, loadDataWithA() , ...., loadDataWithX()
  • Find dependency search, for example, only when performing byId() operations
    • It takes a lot of non-object oriented routines, like findZzzById(zid) and then getYyyIds(zid) instead of z.getY()
    • It may be useful to get each object in the collection one by one if there is a large processing overhead between transactions.
  • Make @Transactional app part instead of DAO
    • Possible Considerations for Nested Transactions
    • Requires routines adapted to manage transactions (e.g. small enough)
    • A small software impact, although this can lead to large transactions.
  • Provide DAO with dynamic extraction profiles , for example loadData(id, fetchProfile);
    • Applications need to know which profile to use when
  • AoP type transaction type, for example, interception operations and, if necessary, transactions
    • Requires use of a bytecode or use of a proxy server
    • Loss of control in transactions
    • Black magic, as always :)

Did I miss any option?




What is your preferred approach when trying to minimize the impact of lazy-loaded relationships in the design of your application?

(Oh, and sorry for WoT )

+81
java spring hibernate lazy-loading application-design
Feb 17 '11 at 9:18
source share
3 answers

As we all know, sleep mode is trying to be as non-invasive and transparent as possible

I would say that the initial assumption is wrong. Transparent persistence is a myth, because the application must always take care of the life cycle of the object and load the size of the loaded object.

Note that Hibernate cannot read minds, so if you know that you need a certain set of dependencies for a specific operation, you need to somehow express your intentions in Hibernate.

From this point of view, decisions expressing these intentions explicitly (namely, 2, 4 and 7) look reasonable and do not suffer from a lack of transparency.

+25
Feb 17 '11 at 9:44
source share

I'm not sure what kind of problem (caused by laziness) you are hinting at, but for me the biggest pain is to avoid losing the session context in my own application caches. Typical case:

  • the foo object is loaded and placed on the map;
  • another thread takes this object from the map and calls foo.getBar() (something that has never been called before and is lazily evaluated);
  • boom!

So, to solve this problem, we have a number of rules:

  • end sessions as transparent as possible (for example, OpenSessionInViewFilter for webapps);
  • have a common API for threads / thread pools, where db session bind / unbind runs somewhere high in the hierarchy (wrapped in try/finally ), so subclasses don't need to think about it;
  • when transferring objects between threads, skip identifiers instead of the objects themselves. The receiving stream can load an object if it needs to;
  • when caching objects, it never caches objects, but their identifiers. Have an abstract method in your DAO or manager class to load an object from the second level Hibernate cache when you know the identifier. The cost of retrieving objects from the second-level Hibernate cache is still much cheaper than moving to DB.

This, as you can see, is really nowhere near non-invasive and transparent. But the cost is still bearable to compare with the price I would have to pay for impatient download. The problem with the latter is that sometimes this leads to a butterfly effect when loading a single link object, not to mention a collection of objects. Memory consumption, CPU usage, and latency, to mention the least, are also much worse, so I guess I can live with it.

+7
Feb 17 2018-11-17T00:
source share

A very common pattern is to use OpenEntityManagerInViewFilter if you are building a web application.

If you are creating a service, I would open TX for the public service method, and not for the DAO, since very often the method requires to retrieve or update multiple objects.

This will solve any "Lazy Load exception". If you need something more advanced for performance tuning, I think profile selections are the way to go.

+3
Feb 17 '11 at 9:28
source share



All Articles