hibernate会话问题新

时间:2009-04-21 14:36:42

标签: hibernate session

我在NetBeans中使用Hibernate。我正在使用NetBeans的Hibernate插件附带的hibernate util类来获取当前会话。也就是说,我使用以下代码来获取当前会话:

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

但是当我尝试懒惰取任何东西时,它会出现以下错误:

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

我正在使用2个DAO。一个是抽象DAO,第二个是扩展AbstractDAO的CoutseDAO。 代码如下

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
        {


        }
    }

}

第二课如下

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 个答案:

答案 0 :(得分:0)

只能在获取对象的事务的边界内访问惰性字段。

答案 1 :(得分:0)

您需要设置事务管理器,以便hibernate可以在同一事务中执行延迟提取的查询。

hibernate网站似乎已关闭但谷歌有cache

在Hibernate配置中启用线程绑定策略:

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

还有其他选项,例如JPA,EJB或自己滚动。

如果您没有在应用服务器中运行或使用其他以其他方式为您处理事务的其他方式,您的代码必须“手动”启动事务。

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; 
}

答案 2 :(得分:0)

这似乎是对DAO的一次可怕的误用,是为了完成Hibernate的工作。

  1. 不应在DAO方法边界终止事务边界..
  2. 你不应该在Hibernate可以完成工作的情况下手写编写查询,
  3. findById()应该只是对Session.load(Course.class,id)的调用。
  4. createObject( T object)的名字错误;它应该是'保存'。
  5. 异常捕获也被错误地放置;它应该在Tx边界上。
  6. 整件事情完全错了,这绝对是一件坏事,你所写的一切都是错误的。不必要。你正在尝试编写JDBC&amp;交易管理,为了上帝的缘故,这已经为你完成了。

    以下是您的代码应该如何:

    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();
    

    摆脱所有这个DAO垃圾&amp;直接使用Hibernate,直到你知道你在做什么。 DAO /业务方法应该简单,而不是尝试进行事务/或异常管理;他们在交易中运行

答案 3 :(得分:-1)

你可能是'陈旧'对象的受害者。使用Seam时,我对注入的对象有这个问题。我们的解决方案是在使用之前重新获取主对象,如调用:

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

基本上,每当你在我们的动作类中调用一个方法时,你需要这样做以确保该对象在你当前的会话/事务中不是陈旧的。

此外,异常(即使被捕获!)可以关闭当前会话,从而导致LazyInitialization错误。