Question

I'm using Hibernate 4 for a Java project.

I have the next scheme with two entities:

Units *has many* Users

So Units hold a foreign key of Users (see the table definition).

When I load a User, I can get the Unity were it belongs, but not the reverse.
When I load a Unity, I get an exception trying to get the User:

    GenericDao dao = (GenericDao)new UnitsDaoImpl();

    Units unity = (Units)dao.get(1); // user.ID => 1

    Users user = unity.getUsers(); 

    System.out.println(user); // Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session

See the full exception here.

The dao method called is this one:

@Override
public T get(PK id) {
    T object;

    Session session = HibernateUtil.getSessionFactory().openSession();
    object = (T) session.get(getType(), id);
    session.close();

    return object;
}

If you want to reproduce it, I have uploaded the code to GitHub. I'm running JDK 8. I read other posts but I do not know how to apply a solution here.


NOTE: the mentioned method doesn't handle transactions, but I tried the next one that does and I get the same result:

    UnitsDao dao = (UnitsDao)new UnitsDaoImpl();
    List<Units> unity = (List<Units>)dao.fetchAll();
    Users user = unity.get(0).getUsers();
    System.out.println(user); // Exception in thread "main" 

And the dao method:

@Override
public List<Units> fetchAll() {
    List resultList;
    String hql = "FROM Units";

    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();

    resultList = session.createQuery(hql).list();

    session.getTransaction().commit();
    session.close();

    return resultList;
}
Was it helpful?

Solution

Ok, the problem is you have closed the Hibernate session here:

session.close();

When you call getUsers(), the collection of related users is lazily loaded. However, this can only be done within an active Hibernate session (which you don't have).

For lazy loading, there is some decent answers from BalusC and Pascal Thivent here:

What is lazy loading in Hibernate?

It is never a good idea to open and close sessions within a single DAO method. It is always better to do this in the tier above (usually referred to as the business/service tier).

Change your DAO class to this:

public class UnitsDaoImpl implements UnitsDao {

    private Session session;

    public UnitsDaoImpl(final Session session) {
        this.session = session;
    }

    @Override
    public List<Units> fetchAll() {

        return session.createQuery("FROM Units").list();
    }
    // Other methods...
}

Change your calling code to this:

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

UnitsDao dao = (UnitsDao)new UnitsDaoImpl(session);
List<Units> unity = (List<Units>)dao.fetchAll();
Users user = unity.get(0).getUsers();
System.out.println(user);

session.getTransaction().commit();
session.close();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top