0
votes

I am using Hibernate in NetBeans. I am using the hibernate util class that comes with the Hibernate plugin for NetBeans to get the current session. That is, I am using the following code to get my current session:

this.session = HibernateUtil.getSessionFactory().getCurrentSession();

But when I try to lazy fetch anything it gives following error:

org.hibernate.LazyInitializationException: failed to lazily initialize a course. 

I am using 2 DAO. One is Abstract DAO and second is CoutseDAO which extends AbstractDAO. code is as follows

public class AbstractDAO<T> {


    Session session = null;


    public AbstractDAO()
    {
      this.session = HibernateUtil.getSessionFactory().getCurrentSession();

   }

    public void createObject(T object)
    {
         Transaction tx = null;
        try
        {

            tx = session.beginTransaction();
            session.save(object);
            tx.commit();

        }
        catch (HibernateException e)
        {
            tx.rollback();
            throw new DataAccessLayerException(e);

        }
        finally
        {


        }
    }
    public  void updateObject(T object )
    {
         Transaction tx = null;
        try
        {

            tx = session.beginTransaction();
            session.update(object);
            tx.commit();

        }
        catch (HibernateException e)
        {
            tx.rollback();
            throw new DataAccessLayerException(e);

        }
        finally
        {


        }
    }

      public  void deleteObject(T object )
    {
         Transaction tx = null;
        try
        {

            tx = session.beginTransaction();
            session.delete(object);
            tx.commit();

        }
        catch (HibernateException e)
        {
            tx.rollback();
            throw new DataAccessLayerException(e);

        }
        finally
        {


        }
    }

}

second classs is as follows

public class CourseDAO extends AbstractDAO<Course>{

    public CourseDAO()
    {
        super();
    }

    public Course findByID(int cid){


        Course crc = null;
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Query q = session.createQuery("from Course  as course where course.cid = "+cid+" ");
            crc = (Course) q.uniqueResult();
            tx.commit();
        } 
        catch (HibernateException e)
        {
            e.printStackTrace();
            tx.rollback();
            throw new DataAccessLayerException(e);
        }

        finally
        {


        }
        return crc;
}


    public List<Course> findAll(){

        List lst = null;
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            Query q = session.createQuery("from Course  ");
            lst =  q.list();
            tx.commit();
        }
        catch (HibernateException e)
        {
            e.printStackTrace();
            tx.rollback();
            throw new DataAccessLayerException(e);
        }

        finally
        {



        }
        return (List<Course>)lst ;
}







}
4
You should post the complete code you use to load the DAO, not just how you retrieve your session. - Elie
This appears to be a horrible mis-use of DAOs, to do the job Hibernate is intended to do. createObject( T object), writing queries longhand where Hibernate should do the work, transaction boundaries terminated at the DAO method boundary.. The whole thing's completely wrong, it's an absolute crock. Get rid of all the DAO stuff & use Hibernate directly. - Thomas W

4 Answers

0
votes

The lazy fields are only accessible within the boundaries of the transaction that fetched the object.

0
votes

You need to set the transaction manager so that hibernate can do the queries for the lazy fetching in the same transaction.

The hibernate site seems to be down but google has the cache

To enable the thread-bound strategy in your Hibernate configuration:

set hibernate.transaction.factory_class to org.hibernate.transaction.JDBCTransactionFactory
set hibernate.current_session_context_class to thread

There are other options, like JPA, EJB or rolling your own.

Your code have to start a transaction "manually" if you are not running in an appserver or use something else that handles transactions for you in some other way.

try {
  factory.getCurrentSession().beginTransaction();

   // Do some work
  factory.getCurrentSession().load(...);
  factory.getCurrentSession().persist(...);

  factory.getCurrentSession().getTransaction().commit(); 
}
catch (RuntimeException e) {
    factory.getCurrentSession().getTransaction().rollback();
    throw e; 
}
0
votes

This appears to be a horrible mis-use of DAOs, to do the job Hibernate is intended to do.

  1. transaction boundaries should not be terminated at the DAO method boundary..
  2. you shouldn't write queries longhand, where Hibernate can do the work,
  3. findById() should just be a call to Session.load( Course.class, id).
  4. createObject( T object) is mis-named; it should be 'save'.
  5. exception-catching is wrongly placed also; it should be on the Tx boundary.

The whole thing's completely wrong, it's an absolute crock, everything you've written is wrong & unnecessary. You're trying to write JDBC & transaction management, for Heaven's sake, when this is already done for you.

Here's how your code should go:

Session hb = sf.openSession();  // or wherever you get a Session from

// load by ID
Course course = (Course) hb.load( Course.class, id);

// list all courses
Criteria crit = hb.createCriteria( Course.class);
List<Course> allCourses = crit.list();

// create a new Course
Course newCourse = new Course("Hibernate 101");
hb.save( newCourse);

// delete the old one
hb.delete( course);

// flush & commit all changes, in a transaction.
Transaction tx = hb.beginTransaction();
/* hb.flush() */
tx.commit();

Get rid of all this DAO rubbish & use Hibernate directly, until you know what you're doing. DAO/ Business methods should be simple and not try to do transaction/ or exception management; they run within a transaction.

-1
votes

You may be the victim of 'stale' objects. When using Seam, I have this issue for injected objects. Our solution has been to re-fetch the main object before using, like calling:

getEm().find( MyClass.class, id );

Basically, whenever you call a method in our action classes, you need to do this to make sure that the object isn't stale in your current session / transaction.

Also, an exception (even if caught!) can close the current session, causing LazyInitialization errors.