使用 Native SQL Hibernate 从存储过程中检索值

Posted

技术标签:

【中文标题】使用 Native SQL Hibernate 从存储过程中检索值【英文标题】:Retrieving a value from Stored Procedure using Native SQL Hibernate 【发布时间】:2013-06-27 15:36:26 【问题描述】:

下面是存储过程:

create or replace procedure 
proc_emp_name(v_emp out emp.emp_name%TYPE, v_empid in emp.emp_id%TYPE)
is
begin
select emp_name into v_emp from emp where emp_id = v_empid;
dbms_output.put_line('Emp Name: ' || v_emp);
dbms_output.put_line('Procedure created successfully!!!');
end;

我想使用 Native SQL 调用它,点击此链接但不确定如何从过程中检索 OUT 参数。

http://www.mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate/

请告诉我调用该过程并从中获取结果的最简单方法。

编辑

按照建议,检查文档,我将 Proc 的第一个参数修改为 SYS_REFCURSOR,如下所示:

create or replace procedure
proc_empname_refcursor(v_empname OUT SYS_REFCURSOR, v_deptid in emp.emp_id%type)
is 
begin
open v_empname for select * from dept where dept_id = v_deptid;
end;

我可以使用NamedQuery 调用它,但由于其他一些限制,我不想在映射文件中添加任何内容。我尝试使用以下代码在不使用 NamedQuery 的情况下调用 proc,但没有成功:

Query query = session.createSQLQuery(
                "CALL proc_empname_refcursor(?, :deptId)")
                .addEntity(Dept.class)
                .setParameter("deptId", new Integer(2));

            List<Dept> departments = query.list();
            for(int i=0; i<departments.size(); i++)
                Dept department = (Dept)departments.get(i);
                System.out.println("Dept Id: " + department.getDeptId());
                System.out.println("Dept Name: " + department.getDeptName());
            

我遇到了异常:

org.hibernate.QueryException: Expected positional parameter count: 1, actual parameters: [] [CALL proc_empname_refcursor(?, :deptId)]
at     org.hibernate.impl.AbstractQueryImpl.verifyParameters(AbstractQueryImpl.java:319)
at org.hibernate.impl.SQLQueryImpl.verifyParameters(SQLQueryImpl.java:201)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:145)
at com.jdbc.HibernateStartup.main(HibernateStartup.java:70)

请告诉我如何解决这个问题。

【问题讨论】:

【参考方案1】:

我已经设法在 Hibernate 和 MS SQL Server 中使用以下代码从存储过程中获取输出参数:

@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException 
    Connection connection = session.connection();
    CallableStatement callable = null;
    try 
        callable = connection.prepareCall("execute [procedure] ?");
        callable.registerOutParameter(1, Types.INTEGER);
        callable.execute();
        int id = callable.getInt(1);

        return id;
     catch (SQLException e) 
        (...)
     finally 
        (...)
    

【讨论】:

session.connection() 已弃用,知道如何替换它吗? 能否告诉我您使用的是哪个 Hibernate 版本? 我使用的是 HIbernate v3.2.5 您确定要弃用session.connection() 吗?我在docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/engine/… 上查看了 Hibernate javadocs,但找不到已弃用的标签 检查这个:docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/Session.html【参考方案2】:

来自Hibernate Docs:

除非你遵循一些过程/函数规则,否则你不能在 Hibernate 中使用存储过程。

对于 Oracle,函数必须返回结果集。过程的第一个参数必须是返回结果集的 OUT。

【讨论】:

感谢您的信息。我可以通过将 proc 添加到映射文件中来以named query 的形式调用它。但现在的问题是我不想将它添加到映射中并将其用作命名查询,而是我想直接使用createSQLQuery 调用它。我试过了,但遇到了一个异常:org.hibernate.QueryException: Expected positional parameter count: 1, actual parameters: [] [CALL proc_empname_refcursor(?, :deptId)] 我已经更新了我的第一篇文章,提供了我尝试过的内容,请告诉我如何解决这个异常。 删除“?”。它应该是 CALL proc_empname_refcursor(:deptId)。见例子here 如果我删除“?”然后我得到了这个例外:java.sql.SQLException: ORA-06553: PLS-306: wrong number or types of arguments in call to 'PROC_EMPNAME_REFCURSOR' 你能解决这个问题吗,因为我在通过休眠调用存储函数时也遇到了同样的问题

以上是关于使用 Native SQL Hibernate 从存储过程中检索值的主要内容,如果未能解决你的问题,请参考以下文章

Native SQL(使用 MySQL)与使用 Hibernate ORM 的性能差异?

Hibernate Native SQL查询的两个问题.

将从 Hibernate Native Query 返回的值映射到模型

如何使用 IN 修复 Hibernate Named Native Query 的 Where 子句

PostGreSQL 结合 Hibernate 在项目中的使用小结

如何使用 Hibernate 从 Sql 数据库中更新、删除对象?