Hibernate/Spring: failed to lazily initialize - no session or session was closed

Posted by Niko on Stack Overflow See other posts from Stack Overflow or by Niko
Published on 2010-06-14T22:01:03Z Indexed on 2010/06/14 22:02 UTC
Read the original article Hit count: 966

Filed under:
|
|
|

I know something similar has been asked already, but unfortunately I wasn't able to find a reliable answer - even with searching for over 2 days.

The basic problem is the same as asked multiple time. I have a simple program with two POJOs Event and User - where a user can have multiple events.


@Entity
@Table
public class Event {
    private Long id;
    private String name;
    private User user;

    @Column
    @Id
    @GeneratedValue
    public Long getId() {return id;}
    public void setId(Long id) { this.id = id;  }

    @Column
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}

    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {return user;}
    public void setUser(User user) {this.user = user;}

}


@Entity
@Table
public class User {
    private Long id;
    private String name;
    private List events;

    @Column
    @Id
    @GeneratedValue
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    @Column
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    @OneToMany(mappedBy="user", fetch=FetchType.LAZY)
    public List getEvents() { return events; }
    public void setEvents(List events) { this.events = events; }

}

Note: This is a sample project. I really want to use Lazy fetching here.

I use spring and hibernate and have a simple basic-db.xml for loading:


<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"  scope="thread">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://192.168.1.34:3306/hibernateTest" />
        <property name="username" value="root" />
        <property name="password" value="" />
        <aop:scoped-proxy/>
    </bean>

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="thread">
                    <bean class="org.springframework.context.support.SimpleThreadScope" />
                </entry>
            </map>
        </property>
    </bean>

    <bean id="mySessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" scope="thread">
        <property name="dataSource" ref="myDataSource" />
        <property name="annotatedClasses">
            <list>
                <value>data.model.User</value>
                <value>data.model.Event</value>
            </list>
        </property>
        <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">create</prop>
            </props>
        </property>
        <aop:scoped-proxy/>

    </bean>

    <bean id="myUserDAO" class="data.dao.impl.UserDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>

    <bean id="myEventDAO" class="data.dao.impl.EventDaoImpl">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>

</beans>

Note: I played around with the CustomScopeConfigurer and SimpleThreadScope, but that didnt change anything.

I have a simple dao-impl (only pasting the userDao - the EventDao is pretty much the same - except with out the "listWith" function:


public class UserDaoImpl implements UserDao{

    private HibernateTemplate hibernateTemplate;

    public void  setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);

    }

    @SuppressWarnings("unchecked")
    @Override
    public List listUser() {
        return hibernateTemplate.find("from User");
    }

    @Override
    public void saveUser(User user) {
        hibernateTemplate.saveOrUpdate(user);

    }

    @Override
    public List listUserWithEvent() {

        List users = hibernateTemplate.find("from User");
        for (User user : users) {
            System.out.println("LIST : " + user.getName() + ":");
            user.getEvents().size();
        }
        return users;
    }

}

I am getting the org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed at the line with user.getEvents().size();

And last but not least here is the Test class I use:


public class HibernateTest {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("basic-db.xml");


        UserDao udao = (UserDao) ac.getBean("myUserDAO");
        EventDao edao = (EventDao) ac.getBean("myEventDAO");


        System.out.println("New user...");
        User user = new User();
        user.setName("test");

        Event event1 = new Event();
        event1.setName("Birthday1");
        event1.setUser(user);

        Event event2 = new Event();
        event2.setName("Birthday2");
        event2.setUser(user);

        udao.saveUser(user);
        edao.saveEvent(event1);
        edao.saveEvent(event2);

        List users = udao.listUserWithEvent();
        System.out.println("Events for users");
        for (User u : users) {

            System.out.println(u.getId() + ":" + u.getName() + " --");
            for (Event e : u.getEvents())
            {
                System.out.println("\t" + e.getId() + ":" + e.getName());
            }
        }

        ((ConfigurableApplicationContext)ac).close();
    }

}

and here is the Exception I get:

1621 [main] ERROR org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
    at data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
    at HibernateTest.main(HibernateTest.java:44)
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: data.model.User.events, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
    at data.dao.impl.UserDaoImpl.listUserWithEvent(UserDaoImpl.java:38)
    at HibernateTest.main(HibernateTest.java:44)

Things I tried but did not work:

  • assign a threadScope and using beanfactory (I used "request" or "thread" - no difference noticed):
        // scope stuff
        Scope threadScope = new SimpleThreadScope();
        ConfigurableListableBeanFactory beanFactory = ac.getBeanFactory();
        beanFactory.registerScope("request", threadScope);
        ac.refresh();
...
  • Setting up a transaction by getting the session object from the deo:
...
        Transaction tx = ((UserDaoImpl)udao).getSession().beginTransaction();
        tx.begin();
        users = udao.listUserWithEvent();
...
  • getting a transaction within the listUserWithEvent()
    public List listUserWithEvent() {
        SessionFactory sf = hibernateTemplate.getSessionFactory();
        Session s = sf.openSession();
        Transaction tx = s.beginTransaction();
        tx.begin();

        List users = hibernateTemplate.find("from User");
        for (User user : users) {
            System.out.println("LIST : " + user.getName() + ":");
            user.getEvents().size();
        }
        tx.commit();
        return users;
    }

I am really out of ideas by now. Also, using the listUser or listEvent just work fine.

© Stack Overflow or respective owner

Related posts about java

Related posts about hibernate