0

I have wasted too much time on this, it time to ask here, thank you.

Frameworkds: SpringMVC 4 + Hibernate 3.6.0

What I expect: Display a Pojo (one to many) object on a jsp page

My configuration

1.applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="driverUrl" value="jdbc:mysql://localhost:3306/xxx"/>
        <property name="user" value="-"/>
        <property name="password" value="-"/>
        <property name="maximumConnectionCount" value="10"/>
        <property name="minimumConnectionCount" value="5"/>
    </bean>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="packagesToScan" value="com.test.pojo"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <!-- auto generate table -->
            </props>
        </property>
    </bean>
</beans>

2.dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:task="http://www.springframework.org/schema/task"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/mvc 
                           http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.1.xsd
                           http://www.springframework.org/schema/tx 
                           http://www.springframework.org/schema/tx/spring-tx-3.1.xsd

                           http://www.springframework.org/schema/task
                           http://www.springframework.org/schema/task/spring-task-3.0.xsd">



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

    <tx:annotation-driven transaction-manager="transactionManager" />

    <task:annotation-driven />

    <mvc:annotation-driven />

    <context:component-scan base-package="com.test.module" />

    <!--HandlerMapping-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

    <!--HandlerAdapter-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

    <!--ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

3.Controller

@Transactional
@Controller
public class TESTS {

    @Resource(name="sessionFactory")
    private SessionFactory sessionFactory;

    @RequestMapping("/hello")
    public ModelAndView test(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/hello");
        mv.addObject("master", (Master) sessionFactory.getCurrentSession().createQuery("from Master where master_id = 1").uniqueResult());
        return mv;
    }
}

4.Pojos

public class Master {
    @Id
    @GeneratedValue
    private Integer master_id;
    private String master_name;

    @OneToMany(fetch = FetchType.LAZY, mappedBy="master", cascade = CascadeType.ALL,orphanRemoval=true)
    private List<Pet> pets;
}

public class Pet {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "master_id", nullable = false)
    private Master master;
}

Even I put @Transnational annotation ahead @Controller, I still can't get pet's information, always get a exception indicates that 'failed to lazily initialize a collection of role: com.test.pojo.Master.pets, no session or session was closed'

please advice thanks!

2 Answers 2

1

The exception says it all. You're trying to access a lazily loaded collection from your JSP. When your JSP is executed, the transactional method of the controller has returned, and the transaction and its associated session is closed. So Hibernate can't load the collection anymore.

Make sure to load the collection from the controller, or use an OpenSessionInViewFilter or an OpenSessionInViewInterceptor.

To load the collection from the controller:

  • call master.getPets().size() (or any other method of the collection), or
  • call Hibernate.initialize(master.getPets()), or
  • load the master and its pets in a single query: select m from Master m left join fetch m.pets where...

Note that your current code uses a query when it should simply use session.get() to get a Master by ID.

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

Comments

1
You have put **"fetch = FetchType.LAZY"**, while mapping pets, so hibernate will just load the proxies for Object "Pets" .
Either yo can make it to **"fetch = FetchType.EAGER"**, with only drawback that Hibernate will always load "Pets object" along with master object even if you do not need.
So better way is to intialize using Hibernate

**Hibernate.initialize(master.getPets()),**

Comments

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.