Hibernate Java中的会话和事务

时间:2016-08-10 16:08:52

标签: java hibernate session transactions

在Java Hibernate中,当我们需要对DB做一些事情时,我们需要: 1.公开会议 2.开始交易 3.完成交易 4.关闭会话

  • 例如,如果我想获得学生列表:

    public static List<Student> getStudentList() 
    {
       List<Student> l = null;
       Session session = HibernateUtil.getSessionFactory().openSession();
       try {
           String hql = "from Student";
           Query query = session.createQuery(hql);
           l = query.list();
       } catch (HibernateException ex) {
           //Log the exception
           System.err.println(ex);
       } finally {
           session.close();
       }
       return l;
    }
    
  • 插入学生

    public static boolean addStudent(Student s) 
    {
    Session session = HibernateUtil.getSessionFactory().openSession();
    
    if (... /* check if student is already exists*/) 
    {
        return false;
    }
    Transaction transaction = null;
    
    try {
        transaction = session.beginTransaction();
        session.save(s);
        transaction.commit();
    } catch (HibernateException ex) {
        //Log the exception
        transaction.rollback();
        System.err.println(ex);
        } finally {
            session.close();
    }
    return true;
    } 
    

为什么getStudentList()中没有事务?提前谢谢

1 个答案:

答案 0 :(得分:0)

这个hibernate article解释了未在事务中显式执行的SELECT操作的行为。

本文给出了以下示例,但对于您的查询示例也是如此。

  

Session session = sessionFactory.openSession();
      session.get(Item.class,123l);
      session.close();

     
      
  1. 打开一个新会话。此时它不会获得数据库连接。
  2.   
  3. 对get()的调用会触发SQL SELECT。 Session现在从连接池获取JDBC连接。默认情况下,Hibernate会立即使用setAutoCommit(false)关闭此连接上的自动提交模式。这有效地启动了JDBC事务!
  4.   
  5. SELECT在此JDBC事务中执行。会话关闭,连接返回到池并由Hibernate释放 - Hibernate在JDBC Connection上调用close()。未提交的交易会发生什么?
  6.         

    该问题的答案是,“它取决于!”在连接上调用close()时,JDBC规范没有提及有关挂起事务的任何信息。发生的情况取决于供应商如何实施规范。例如,使用Oracle JDBC驱动程序,对close()的调用将提交事务!当JDBC Connection对象关闭并且资源返回到池时,大多数其他JDBC供应商采用相同的路由并回滚任何挂起的事务。   显然,这对SELECT [...]

    来说不是问题

让我们扩展上面的例子以引发可能的问题。

Session session = sessionFactory.openSession();
Item item = session.get(Item.class, 123l);
item.setPrice(10);
session.close();

现在,如果Item的新价格持续存在,它依赖于JDBC驱动程序。

因此,只要没有数据库更改,即使JDBC驱动程序将回滚事务,您也可以忽略纯SELECT操作的开始和提交事务。

但无论如何,我强烈建议在任何操作中使用交易以避免误解和问题。