简体   繁体   English

使用 Hibernate Session.doWork 生成序列 ID

[英]Using Hibernate Session.doWork for Sequence ID Generation

Hibernate Session' doWork() method gives direct access to java.sql.Connection . Hibernate Session 的doWork()方法可以直接访问java.sql.Connection

Following is one of the way to create and execute a PreparedStatement to generate sequence以下是创建和执行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];
}

First, is there a better way to do this ?首先,有没有更好的方法来做到这一点?

Second Q do we need to explicitly close the PreparedStatement created above ?第二个问题我们是否需要明确关闭上面创建的PreparedStatement

An instance of PreparedStatement is created as part of method Work.execute and thus should be handled within that scope, including closing (an instance itself will be collected by GC once method finishes its execution since variable ps would become out of scope, but any external resources such as open cursor require an explicit call ps.close() ). PreparedStatement的实例是作为Work.execute方法的一部分创建的,因此应该在该范围内处理,包括关闭(一旦方法完成执行,实例本身将被 GC 收集,因为变量ps将超出范围,但任何外部诸如打开游标之类的资源需要显式调用ps.close() )。

An instance of Connection on the other hand is passed into the method by Hibernate and should not be closed manually -- this is Hibernate's responsibility.另一方面, Connection的实例由 Hibernate 传递到方法中,不应手动关闭——这是 Hibernate 的责任。

    String query = ((SessionFactoryImplementor)sessionFactory).getDialect().getSequenceNextValString(seqName);
    Session session = sessionFactory.getCurrentSession();
    return (Long) session.createSQLQuery(query).addScalar("nextval", Hibernate.LONG).uniqueResult();

You may want to tweak the scalar part a bit to fit your database's column name and return type.您可能需要稍微调整标量部分以适合您的数据库的列名和返回类型。

1) For returning value we can use doReturningWork 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)Yes We have to explicitly close the PreparedStatement See below example 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 参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM