[英]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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.