1

This is asked many times in SO. But they didn't solve my issue so posting again.

Getting following exception while trying to access my application

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.wpt.models.Item.itemCategory, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:348)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:224)
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:155)
    at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:256)

web.xml

<filter>
        <filter-name>HibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>hibernate4AnnotatedSessionFactory</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>HibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Spring config:

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
    p:sessionFactory-ref="hibernate4AnnotatedSessionFactory">
</bean>

Item.java

@Entity
@Table(name="item")
public class Item {
    @OneToMany(mappedBy="item", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    private List<ItemCategory> itemCategory = new ArrayList<ItemCategory>();
}

ItemServiceImpl.java

@Override
    @Transactional(readOnly=true)
    public List<Item> getItemsByCategory(int categoryId) {
        return itemDAO.getItemsByCategory(categoryId);
    }

In all of the blogs, it's suggested to either go for EAGER fetch, or use OpenSessionInViewFilter with @Transactional support.

It works will if I use EAGER fetch. But not working the other way. I have implemented all service methods with @Transactional annotation. What mistake I am doing here? Can someone please help?

svjn
  • 904
  • 2
  • 19
  • 35

4 Answers4

0

First of all you have realize what happend if you make an eager fetch. It means the query to the database always bring itemCategory when you request item's. Maybe that is not the behaviour you are expecting.

Second, lazyInitialization exception occurs because you are trying to access to the object itemCategory after close the session. And I suppose the session is closed when you receive the List from the method "getItemsByCategorymethod".

The way I usually resolve this situation (is not making eager fetch) has two ways:

  • Pick the itemCategory before close the session. Wherever you call to execute the query, there you should be able to say List listItemCategroy = item.getItemCategory().

  • Add a fetch.JOIN to the table itemCategory and it will bring the ItemCategory.

If you want to avoid this error you can add this in your code:

if (Hibernate.isInitilized()){
    ....
}

It will return true if the object is initialized or false if its not.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Yeah, I've noticed that. But fatch.JOIN isn't the same as FetchType.EAGER? Sorry I am bit confused at this area. Can you provide me a reference where it's explained in detail. (I've gone through some links, but the details weren't sufficient) – svjn Feb 03 '15 at 15:18
  • 1
    If you indicate FetchType.EAGER in the entity it will concern to all item object you retrieve from the DB. But if you have the relationship lazy and indicates fetch.JOIN in the criteria, you are saying only for that query make the relationship eager. Think you not always want itemCategory when you request items. Imgine you only need item_pk for a list, do you need retrieve itemCategory object as well? – user1659580 Feb 05 '15 at 16:34
0

Okay, after a lot of struggle, I have finally figured out the solution for this issue.

The issue got resolved after I've added contextConfigLocation to DispatcherServlet's <init-param>. After the changes, my DispatcherServlet configuration looks like the following.

<servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Reference: This post

Community
  • 1
  • 1
svjn
  • 904
  • 2
  • 19
  • 35
0

The contextConfigLocation is used to indicate where the xml files (eg Spring, spring-security) are located.

Lazy issues doesnt make any sense with Spring configuration to me.

Can you explain it in detail?

  • Yeah I too understand that. I think DispatcherServlet is able to recognize the sessionFactoryBean in spring config file when we use OpenSessionInViewFilter only we initialize it through it's init-param. Doing some analysis on that. Will post it once find the valid reason why it's happening like this. – svjn Feb 04 '15 at 18:03
0

use below filter instead of HibernateFilter

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Hope it will help you.

Nalla Srinivas
  • 913
  • 1
  • 9
  • 17
  • I don't think that's the issue. It's just the user defined filter name. It can be anything. This issue is already resolved & I have provided the answer already. – svjn Feb 05 '15 at 09:33
  • It was due to missed initialization of contextConfigLocation into DispatcherServlet. It was resolved once I initialized it. – svjn Feb 05 '15 at 09:46