Spring and hibernate- Lazy loading collections in desktop (swing) applications

9 years ago

So here's something you can't find on the internets. Or at least i couldn't, when i was trying to find a way to do this.

The problem:

Traditionally, spring and hibernate have been mostly used in web applications. In this case, you can easily define your domain objects to have lazy collections because spring/hibernate will keep an open session during the whole handling of each web request. This means that you can access lazy loading objects even in your views (provided you use the open session in view filter ;)).

Now, in desktop applications you usually don't go around having open sessions all the time which means that, unfortunately, when you try to get a lazy loading collection, hibernate will give you a big finger in the form of a LazyInitializationException due to the fact of no open sessions existing.

One solution:

My application's structure is such that no UI classes are being managed by spring (and by this i mean your mileage may vary with this solution), only my services and data access objects (DAOs) are. The UI accesses the services by use of a ServiceLocator pattern (which can be more or less complex, depending on your needs) and the DAOs in the services are autowired. The rest is just spring plumbing.

The way i found more elegant to deal with the lazy loading problem is the following. Take this bean (for the sake of simplicity some annotations or methods might be missing, beware): @Entity public class MyBean { @Column(name = "NAME") private String name;

@CollectionOfElements(fetch = FetchType.LAZY) private Set<AnotherBean> children;

public Set<AnotherBean> getChildren() { return children; } } If you try to access getChildren() hibernate will complain so i changed the method to this: public Set<AnotherBean> getChildren() {

children = DBUtils.initializeIfNeeded(this, children); return children; } And here's the definition of that static method: public static <T> Set<T> initializeIfNeeded(Object obj, Set<T> collection) {

if (!(collection instanceof PersistentCollection)) {

return Sets.newHashSet(); }

if (!((PersistentCollection) collection).wasInitialized()) {

ServiceLocator.get(CompanyDA.class).initializeLazyCollection(obj, collection); }

return collection != null ? collection : Sets.<T>newHashSet(); } What we are doing is checking whether this collection is a instance of hibernate's PersistentCollection and, if not, getting out. If it is, and hasn't been initialized, we call a special method in the super of all my DAO's that is responsible for asking hibernate to initialize the collection. Take into account that this method has to be inside a spring managed bean (i.e. non static) otherwise it won't be able to open a new session and you're back to square one.

Here's the definition of that method in the DAO: public void initializeLazyCollection(Object obj, Collection<? extends Object> collection) { sessionFactory.getCurrentSession().lock(obj, LockMode.NONE); new HibernateTemplate(sessionFactory).initialize(collection); } Hope this helps anyone and if you know of a better way to do the same thing, please share :)

Peace out.