Overcoming the issue of Lazy Initialization and Performance using Hibernate in Struts 2

453 views Asked by At

In Hibernate, @ManyToOne relationship hardly results any problem since default fetch type is EAGER.

However, we encounter critical problems at the @OnetoMany end. As we attempt to fetch a collection,

LazyInitializationException: could not initialize proxy 

is thrown since the default fetch type is LAZY for one-to-many.

In such case, we shall either set:

  • @LazyCollection(LazyCollectionOption.FALSE), which although it resolves the problem, it hits the performance significantly when there are bunch of records.

  • fetch mode: left join but it throws

    org.hibernate.HibernateException: cannot simultaneously fetch multiple bags
    

According to my knowledge, Hibernate suggests couple of mechanisms to overcome this issue:

  • Option 1:

    • Specifying @IndexColumn instead of making LazyCollectionOption.FALSE. As a consequnce, the following behaviors are identified which also impacts on the performance:

    • A temporary table is created with primary keys of respective entities (@OnetoMany). So when there are many one-to-many relationships, temporary table is created for each.

  • Option 2:

    • Changing data type of collection from List to Set. This is leads to a problematic situation at the front-end with Struts 2 because Set is index based collection as we need to add records dynamically in an iterative manner.

    • In order to overcome this issue, we shall make use of DTOs to capture UI inputs. By making collection type List in DTO and Set in domain, and by having assembler we shall do the required conversion from ListSet (DTO → Domain), and vice versa.

Is the resolution mentioned under Option 2 a viable solution? If not, please provide suggestions and feedback.

2

There are 2 answers

0
jpkroehling On

In my experience, you usually have only one or two places where you need eager initialization (example: in a "record details" view). For such situations, where lazy will be always the case, except for a couple of places where eager is needed, there's a Hibernate feature called "Fetch profile". It's a relatively new feature, not very known, but it's very powerful and can probably help in this case.

Unfortunately, this is not in JPA yet, which means that you'll need to add a bit of proprietary Hibernate parts in your otherwise clean JPA code, but it's a low price to pay, IMO.

0
Roman C On

The LazyInitializationException is thrown if you are trying to access objects in one-to-many properties or collections and doesn't have an open session at the moment.

The association is designed by default for lazy initialization and this is good approach for performance issue to have one-to-many properties that could be initialized on demand.

The only problem is with the session state. For this purpose Hibernate has imposed Open Session In View pattern.

You could implement it manually using a custom interceptor or use already implemented via Full Hibernate Plugin for Struts2.

See how this plugin could be used with Struts2 jQuery Grid plugin in their showcase.