Hibernate 调用函数及过程

来源:互联网 发布:女高中生知乎 编辑:程序博客网 时间:2024/06/13 01:05

一、函数

第一种方式:获得connection

Connection conn = session.connection();CallableStatement call = conn.prepareCall("{?=call getemp.getempc(?)}");call.registerOutParameter(1, OracleTypes.CURSOR);// 设置输出变量类型call.setInt(2, 10);call.executeQuery();ResultSet rs = (ResultSet) call.getObject(1);while (rs.next()) {System.out.println(rs.getString(3));}

对应函数包体:

create or replace package body getemp is       function getempc(dno number) return sys_refcursor       is       type emp_cursor_type is ref cursor;       emp_cursor emp_cursor_type;       begin             open emp_cursor for select * from scott.emp where deptno=dno;             return emp_cursor;       end;end getemp;

第二种方式:通过配置XML

<sql-query name="funtest" callable="true"><return alias="emp" class="org.han.entity.Emp"><return-property name="empno" column="empno"></return-property><return-property name="ename" column="ename"></return-property><return-property name="job" column="job"></return-property><return-property name="mgr" column="mgr"></return-property><return-property name="hiredate" column="hiredate"></return-property><return-property name="sal" column="sal"></return-property><return-property name="comm" column="comm"></return-property><return-property name="dept" column="deptno"></return-property><return-property name="version" column="version"></return-property></return>{?=call getemp.getempc(?)}</sql-query>

List<Emp> emps=session.getNamedQuery("funtest").setInteger(0, 10).list();for (Emp emp : emps) {System.out.println(emp);}

第三种方式:自定义方言


二、过程

对应的过程:

create or replace procedure getdeptbyid(d out sys_refcursor,dno number,num number )isbegin       open d for select * from dept where deptno=dno and 1=num;end;

第一种方式:获得connection

Connection conn = session.connection();CallableStatement call = conn.prepareCall("{call getdeptbyid(?,?,?)}");call.registerOutParameter(1, OracleTypes.CURSOR);// 设置输出变量类型call.setInt(2, 10);call.setInt(3, 1);call.executeQuery();ResultSet rs = (ResultSet) call.getObject(1);while (rs.next()) {System.out.println(rs.getString(2));}

第二种方式:通过配置XML

<sql-query name="getdeptbyid" callable="true"><return alias="dept" class="org.han.entity.Dept"><return-property name="deptno" column="deptno"></return-property><return-property name="dname" column="dname"></return-property><return-property name="loc" column="loc"></return-property></return>{call getdeptbyid(?,?,?)}</sql-query>


Dept dept=(Dept)session.getNamedQuery("getdeptbyid").setInteger(0, 10).setInteger(1, 1).uniqueResult();System.out.println(dept.getDname());

三、使用限制

为了在 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,这可能会效率更高,但这不是必需的。