public Boolean doInHibernate(Session session)
throws HibernateException, SQLException {
try{
Transaction tr = session.beginTransaction();
SQLQuery query = session.createSQLQuery("{call CommandAdapter(?,?,?,?)}");
query.setString(0,"ls");
query.setInteger(1, machineid);
query.setString(2, param);
query.setInteger(3, 0); //
query.executeUpdate();
tr.commit();
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}finally{
session.close();
}
}
使用hibernate调用带参数返回值的存储过程方法
在调用带参数返回值的方法时,需使用到CallableStatement对象。因此,首先得设法获取一个Connection。
获取Connection 方法:
(1)session.connection();//此方法目前已被弃用
(2)SessionFactoryUtils.getDataSource(sessionFactory).getConnection()
不
过我在使用SessionFactoryUtils.getDataSource(sessionFactory)时,一直获取的都是空值,为此参考
SessionFactoryUtils的源代码直接利用ConnectionProvider对象来获取一个Connection实例。
完整代码:
SessionFactory sessionFactory=this.getSessionFactory();
if (sessionFactory instanceof SessionFactoryImplementor){
ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
try {
CallableStatement statement = cp.getConnection().prepareCall(
"{call MachineDataQuery(?,?,?,?,?,?,?,?,?,?,?,?,?,?)}");
statement.setInt(1, machineId);
statement.setInt(2, jobId);
statement.setInt(3, partTypeId);
statement.setInt(4, compentId);
statement.setInt(5, opId);
statement.setInt(6, roleId);
statement.setInt(7, userId);
statement.setString(8, sd);
statement.setString(9, ed);
statement.registerOutParameter(10, Types.FLOAT);
statement.registerOutParameter(11, Types.FLOAT);
statement.registerOutParameter(12, Types.FLOAT);
statement.registerOutParameter(13, Types.FLOAT);
statement.registerOutParameter(14, Types.FLOAT);
statement.execute();
System.out.println(statement.getFloat(10));
System.out.println(statement.getFloat(11));
System.out.println(statement.getFloat(12));
System.out.println(statement.getFloat(13));
System.out.println(statement.getFloat(14));
} catch (SQLException e) {
e.printStackTrace();
}finally{
cp.close();
}
}
ps:切记存储过程中不可有多余的print或select语句,否则会抛出异常“com.microsoft.sqlserver.jdbc.SQLServerException: 已生成用于更新的结果集。”
hibernate 3 引入了对存储过程查询(stored procedure)和函数(function)的支持。以下的说明中,这二者一般都适用。存储过程/函数必须返回一个结果集,作为 hibernate 能够使用的第一个外部参数。下面是一个 oracle9 和更高版本的存储过程例子。
create or replace function selectallemployments
return sys_refcursor
as
st_cursor sys_refcursor;
begin
open st_cursor for
select employee, employer,
startdate, enddate,
regioncode, eid, value, currency
from employment;
return st_cursor;
end;
在 hibernate 里要要使用这个查询,你需要通过命名查询来映射它。
<sql-query name="selectallemployees_sp" callable="true">
<return alias="emp" class="employment">
<return-property name="employee" column="employee"/>
<return-property name="employer" column="employer"/>
<return-property name="startdate" column="startdate"/>
<return-property name="enddate" column="enddate"/>
<return-property name="regioncode" column="regioncode"/>
<return-property name="id" column="eid"/>
<return-property name="salary">
<return-column name="value"/>
<return-column name="currency"/>
</return-property>
</return>
{ ? = call selectallemployments() }
</sql-query>
注意存储过程当前仅仅返回标量和实体现在。不支持 <return-join> 和 <load-collection>。
使用存储过程的规则和限制:
为了在 hibernate 中使用存储过程,你必须遵循一些规则。不遵循这些规则的存储过程将不可用。如果你仍然想使用他们,你必须通过 session.connection() 来执行他们。这些规则针对于不同的数据库。因为数据库提供商有各种不同的存储过程语法和语义。
对存储过程进行的查询无法使用 setfirstresult()/setmaxresults() 进行分页。
建议采用的调用方式是标准 sql92: { ? = call functionname(<parameters>) } 或者{ ? = call procedurename(<parameters>) }。原生调用语法不被支持。
对于 oracle 有如下规则:
函数必须返回一个结果集。存储过程的第一个参数必须是 out,它返回一个结果集。这是通过 oracle 9 或 10 的sys_refcursor 类型来完成的。在 oracle 中你需要定义一个 ref cursor 类型,参见 oracle 的手册。
对于 sybase 或者 ms sql server 有如下规则:
存储过程必须返回一个结果集。注意这些 servers 可能返回多个结果集以及更新的数目。hibernate 将取出第一条结果集作为它的返回值,其他将被丢弃。
如果你能够在存储过程里设定 set nocount on,这可能会效率更高,但这不是必需的。