【问题标题】:hibernate session problem new休眠会话问题新
【发布时间】:2009-04-21 14:36:42
【问题描述】:

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

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

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

org.hibernate.LazyInitializationException: 延迟初始化课程失败。 

我正在使用 2 DAO。一个是 Abstract 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 ;
}







}

【问题讨论】:

  • 您应该发布用于加载 DAO 的完整代码,而不仅仅是您检索会话的方式。
  • 这似乎是对 DAO 的可怕误用,以完成 Hibernate 打算做的工作。 createObject( T object),在 Hibernate 应该在哪里工作的地方写查询,事务边界在 DAO 方法边界处终止。整个事情完全错了,这绝对是一个骗局。摆脱所有 DAO 的东西并直接使用Hibernate。

标签: hibernate session


【解决方案1】:

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

【讨论】:

  • 你能建议我为我的问题推荐一个 DAO 实现
【解决方案2】:

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

hibernate 站点似乎已关闭,但 google 有 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; 
}

【讨论】:

  • 我在哪里可以设置这个选项?在 hibernate.cfg.xm 文件中。如果是怎么办?
  • 我尝试设置此参数,但它不适用于相同的代码
  • 您的代码必须在执行任何操作之前启动事务。尝试阅读文档,因为它有点复杂。试试谷歌缓存链接。
【解决方案3】:

这似乎是对 DAO 的可怕误用,以完成 Hibernate 打算做的工作。

  1. 事务边界不应在 DAO 方法边界处终止..
  2. 您不应该直接编写查询,因为 Hibernate 可以完成这项工作,
  3. findById() 应该只是对 Session.load(Course.class, id) 的调用。
  4. createObject( T object) 命名错误;它应该是“保存”。
  5. 异常捕获也被错误地放置;它应该在 Tx 边界上。

整个事情完全错了,这绝对是垃圾,你写的一切都是错误的和不必要的。看在上帝的份上,您正在尝试编写 JDBC 和事务管理,而这已经为您完成了。

你的代码应该是这样的:

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 垃圾并直接使用 Hibernate,直到您知道自己在做什么。 DAO/业务方法应该简单,不要试图做事务/或异常管理;他们在一个事务中运行

【讨论】:

    【解决方案4】:

    您可能是“陈旧”物品的受害者。使用 Seam 时,我遇到了注入对象的问题。我们的解决方案是在使用之前重新获取主对象,例如调用:

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

    基本上,每当您在我们的操作类中调用方法时,您都需要这样做以确保该对象在您当前的会话/事务中不会过时。

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

    【讨论】:

    • 问题在于他在所有 DAO 方法上设置了 TX 边界。这保证了延迟加载对象的问题。
    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 2017-08-05
    • 2012-06-02
    相关资源
    最近更新 更多