0

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;
}
Community
  • 1
  • 1
Lucio
  • 3,428
  • 3
  • 37
  • 67
  • How are you managing Hibernate sessions? The exception implies you have no session (it has been closed). Do you have transactions around your DAO methods? – JamesB May 01 '14 at 22:33
  • I've tried with and without transactions but I got the same exceptions message. – Lucio May 01 '14 at 22:45
  • When you were using them, how were they defined? – JamesB May 01 '14 at 22:49
  • Sorry, but I don't know what you mean by *them*. Do you mean the DAO methods? I already uploaded them. – Lucio May 01 '14 at 22:50
  • All that I have is the code that I write on the post, nothing else. The database doesn't have transactions or procedures. – Lucio May 01 '14 at 22:57

1 Answers1

1

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();
Community
  • 1
  • 1
JamesB
  • 7,314
  • 1
  • 19
  • 20
  • Wow, this worked. While debugging, it still shows error but the final result is correct, that is why I would never made it without actually *run* it. Thanks! – Lucio May 02 '14 at 00:37