4

How to use lazy loading in Spring MVC? I'm using eager at this moment, but this makes my app works slowler. This is part of my domain:

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "NEWS_TAG", joinColumns = @JoinColumn(name = "NEWS_ID"), inverseJoinColumns = @JoinColumn(name = "TAG_ID"))
private List<Tags> tags = new ArrayList<Tags>();

public List<Tags> getTags() {
    return this.tags;
}

And dao:

public List<News> getSomeNews(long b, long hm) {

    List<News> news = (List<News>) sessionFactory
            .getCurrentSession()
            .createQuery(
                    "from News WHERE title!='About' ORDER BY publish_time")
            .setMaxResults((int) hm).setFirstResult((int) b).list();
    return news;
}

Servlet-context:

    <context:annotation-config />

    <context:component-scan base-package="net.babobka.blog" />



    <import resource="../../db/db-config.xml" />

    <bean id="urlForwardController"
        class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

</beans>

Db-config:

<bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        p:location="/WEB-INF/db/jdbc.properties" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>/WEB-INF/db/hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">${jdbc.show_sql}</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven />

</beans>

Web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets 
        and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>

        <param-value>
        /WEB-INF/spring/root-context.xml
        /WEB-INF/spring/application-security.xml
        </param-value>
    </context-param>



    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>



    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

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

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>*.gif</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

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

    <filter>
        <filter-name>hibernateFilterChain</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>




</web-app>

What I have to do to solve my problem?

2 Answers 2

6

You can use OpenSessionInViewFilter to prevent hibernate session get closed. Add this to web.xml:

  <filter>
    <filter-name>hibernateFilterChain</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>hibernateFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

@see read more here: OpenSessionInViewFilter

And remove fetch = FetchType.EAGER. @ManyToMany is LAZY by default.

Sign up to request clarification or add additional context in comments.

22 Comments

No bean named 'sessionFactory' is defined
@user2639377: If you using JPA entity managed you need replace filter-class with org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter. Please provide your spring context configuration.
@user2639377: where configuration related to database connection? This file content "../../db/db-config.xml" required
@user2639377: From you code: List<News> news = (List<News>) sessionFactory.getCurrentSession(). Where and how defined sessionFactory?
@Autowired private SessionFactory sessionFactory; in DAOImpl
|
1

Change your annotation to (fetch = FetchType.LAZY). Be aware that if you're passing the result to some code outside the transaction (such as a view template), you might encounter errors if associated objects needed by the external code haven't already been loaded.

12 Comments

No. With adding FetchType.LAZY only I will have some errors with session or something.
Your comment isn't clear. Are you saying that if you change to LAZY you start getting errors? Are those errors the result of trying to access unloaded associated entities after you've left the transaction?
I've got this: failed to lazily initialize a collection of role: net.babobka.blog.domain.News.tags, no session or session was closed
Also I use @Transaction in services only.
"Session was closed" means that your code tried to read information out of the tags field, but the field hadn't been loaded, and it couldn't load it because the transaction (session) was over. You can't lazy-load more data after the end of the transaction; you have to eager-load, specifically load the fields that will be used, or execute the code that gave you the error inside the transaction.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.