【问题标题】:Using Hibernate Session.doWork for Sequence ID Generation使用 Hibernate Session.doWork 生成序列 ID
【发布时间】:2012-05-24 11:09:12
【问题描述】:

Hibernate Session'doWork() 方法提供对java.sql.Connection 的直接访问。

以下是创建和执行PreparedStatement以生成序列的方法之一

public Long generateId() {
    final Long id[] = { null };

    getSessionFactory().openSession().doWork(new Work() {
        public void execute(Connection connection) throws SQLException {
            PreparedStatement ps = connection
                    .prepareStatement("SELECT HIB_SEQ.nextval FROM DUAL");
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                id[0] = rs.getLong(0);
            }
        }
    });
    return id[0];
}

首先,有没有更好的方法来做到这一点?

第二个问题,我们是否需要显式关闭上面创建的PreparedStatement

【问题讨论】:

    标签: java hibernate connection prepared-statement


    【解决方案1】:

    PreparedStatement 的实例是作为方法 Work.execute 的一部分创建的,因此应在该范围内处理,包括关闭(一旦方法完成执行,实例本身将由 GC 收集,因为变量 ps 将变为超出范围,但任何外部资源(例如打开游标)都需要显式调用 ps.close())。

    另一方面,Connection 的实例由 Hibernate 传递到方法中,不应手动关闭 - 这是 Hibernate 的责任。

    【讨论】:

      【解决方案2】:

      1) 对于返回值,我们可以使用doReturningWork

      public int updateEmployeeStatusWithCount(final List<String> employeeList) throws DBException
      {
             Session session = null;
             try
             {
                    session = HibernateUtil.getSession();
                    session.beginTransaction();
                    int cnt = session.doReturningWork(new ReturningWork<Integer>() {
                           @Override
                           public Integer execute(Connection conn) throws SQLException {
                                 PreparedStatement pStmt = null;
                                 try
                                 {
                                        int updatedCnt = 0;
                                        String sqlQry = "UPDATE EMP_DETAILS set IS_ACTIVE='N' WHERE EMP_ID=?";
                                        pStmt = conn.prepareStatement(sqlQry);
                                        for(String empId:employeeList)
                                        {
                                               System.out.println(empId);
                                               pStmt.setString(1, empId);
                                               int cnt = pStmt.executeUpdate();
                                               updatedCnt+=cnt;
                                        }
                                        return updatedCnt;
                                 }
                                 finally
                                 {
                                        pStmt.close();
                                 }                                
                           }
                    });
                    session.getTransaction().commit();
                    return cnt;
             }
             catch(HibernateException e)
             {
                    throw new DBException("Error occured while updating Employee Status",e);
             }
             finally
             {
                    HibernateUtil.closeSession(session);
             }            
      }
      

      2)是的,我们必须明确关闭PreparedStatement 见下例

      public void updateEmployeeStatus(final List<String> employeeList) throws DBException
      {
             Session session = null;
             try
             {
                    session = HibernateUtil.getSession();
                    session.beginTransaction();
                    session.doWork(new Work() {
                           @Override
                           public void execute(Connection conn) throws SQLException {
                                 PreparedStatement pStmt = null;
                                 try
                                 {
                                        String sqlQry = "UPDATE EMP_DETAILS set IS_ACTIVE='N' WHERE EMP_ID=?";
                                        pStmt = conn.prepareStatement(sqlQry);
                                        for(String empId:employeeList)
                                        {
                                               pStmt.setString(1, empId);
                                               pStmt.addBatch();
                                        }
                                        pStmt.executeBatch();
                                 }
                                 finally
                                 {
                                        pStmt.close();
                                 }                                
                           }
                    });
                    session.getTransaction().commit();
             }
             catch(HibernateException e)
             {
                    throw new DBException("Error occured while updating Employee Status",e);
             }
             finally
             {
                    HibernateUtil.closeSession(session);
             }            
      }
      

      Reference

      【讨论】:

        【解决方案3】:
            String query = ((SessionFactoryImplementor)sessionFactory).getDialect().getSequenceNextValString(seqName);
            Session session = sessionFactory.getCurrentSession();
            return (Long) session.createSQLQuery(query).addScalar("nextval", Hibernate.LONG).uniqueResult();
        

        您可能需要稍微调整标量部分以适合您的数据库的列名和返回类型。

        【讨论】:

          猜你喜欢
          • 2013-02-26
          • 2012-04-09
          • 2011-01-10
          • 1970-01-01
          • 2019-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-09
          相关资源
          最近更新 更多