在 Hibernate 中调用存储过程

Posted

技术标签:

【中文标题】在 Hibernate 中调用存储过程【英文标题】:Calling a Stored Procedure in Hibernate 【发布时间】:2011-04-10 12:15:37 【问题描述】:

我昨晚刚开始学习休眠,它很有趣。我在使用休眠将存储过程调用为 sql 查询时遇到了一些麻烦。我附上了来源和错误,请帮助我。谢谢:)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Example" table="example">
   <id name="user_id" column="id" >
   <generator class="increment"/>
  </id>
  <property name="user_data">
    <column name="data"/>
  </property>
 </class>

<!-- sql-query must be after class --> 

<sql-query name="getRecordsSP" callable="true" >
<return class="Example">
<return-property name="user_id" column="user_id"></return-property>
<return-property name="user_data" column="user_data"></return-property>
</return>
call getRecords
</sql-query>

</hibernate-mapping>

这是java文件:::

    import java.util.Iterator;
    import java.util.List;

    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;


    public class SelectProc 


        public static void main(String[] args) 

            Session session = null;
            //String query = "select example.id, example.data from Example example";

            try

                SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
                session = sessionFactory.openSession();

                System.out.println("selecting records");
                Query q = session.getNamedQuery("getRecordsSP");
        //      Query q =  session.createSQLQuery("call getRecords","",Example.class);

                System.out.print("Done");
                List l = q.list();


                for(Iterator it = l.iterator() ;it.hasNext();)
                    Object row [] = (Object [])it.next();
                    System.out.println(row.length);
            //      System.out.println(row[0]);
            //      System.out.println("ID " + row[0]);
            //  System.out.println("Data "+ row[1]);
                

            
            catch (Exception e) 
                e.printStackTrace();
            
            finally
                session.flush();
                session.close();

        
    

错误是:::

call getRecords

18:33:41,346  WARN JDBCExceptionReporter:38 - SQL Error: 0, SQLState: S0022
18:33:41,347 ERROR JDBCExceptionReporter:46 - Column 'id0_' not found.
18:33:41,348  WARN JDBCExceptionReporter:38 - SQL Error: 0, SQLState: S0022
18:33:41,349 ERROR JDBCExceptionReporter:46 - Column 'id0_' not found.
18:33:41,349 ERROR JDBCExceptionReporter:38 - Could not execute native SQL query
java.sql.SQLException: Column 'id0_' not found.
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
    at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144)
    at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2813)
    at org.hibernate.type.IntegerType.get(IntegerType.java:18)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:62)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:53)
    at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:541)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:233)
    at org.hibernate.loader.Loader.doQuery(Loader.java:337)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:167)
    at org.hibernate.loader.Loader.doList(Loader.java:1201)
    at org.hibernate.loader.Loader.list(Loader.java:1186)
    at org.hibernate.loader.SQLLoader.list(SQLLoader.java:121)
    at org.hibernate.impl.SessionImpl.findBySQL(SessionImpl.java:2212)
    at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:85)
    at SelectProc.main(SelectProc.java:28)
org.hibernate.JDBCException: Could not execute native SQL query
    at org.hibernate.impl.SessionImpl.findBySQL(SessionImpl.java:2215)
    at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:85)
    at SelectProc.main(SelectProc.java:28)
Caused by: java.sql.SQLException: Column 'id0_' not found.
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
    at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144)
    at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2813)
    at org.hibernate.type.IntegerType.get(IntegerType.java:18)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:62)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:53)
    at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:541)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:233)
    at org.hibernate.loader.Loader.doQuery(Loader.java:337)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:167)
    at org.hibernate.loader.Loader.doList(Loader.java:1201)
    at org.hibernate.loader.Loader.list(Loader.java:1186)
    at org.hibernate.loader.SQLLoader.list(SQLLoader.java:121)
    at org.hibernate.impl.SessionImpl.findBySQL(SessionImpl.java:2212)
    ... 2 more

【问题讨论】:

【参考方案1】:

根据文档,该过程必须返回一个结果集,并且应该像这样调用:

 ? = call procedureName(<parameters>) 

因此请尝试以下方法:

<sql-query name="getRecordsSP" callable="true" >
  <return class="Example">
    <return-property name="user_id" column="user_id"></return-property>
    <return-property name="user_data" column="user_data"></return-property>
  </return>
   ? = call getRecords 
</sql-query>

参考文献

Hibernate 核心参考指南 16.2.2. Using stored procedures for querying

【讨论】:

? = call getRecords() 语法需要一个参数。存储过程不接受任何参数。 @ferronrsmith 然后去掉括号? 还是不行,太酷了,我换个方式写了,还是谢谢【参考方案2】:
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;



public class SelectPP 


    public static void main(String[] args) 

        Session session = null;
        //String query = "select example.id, example.data from Example example";
        CallableStatement callableStatement = null;
        ResultSet resultSet = null;

        try

            SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
            session = sessionFactory.openSession();

            System.out.println("selecting records");
    //      Query q = session.getNamedQuery("getRecordsSP");
    //      Query q =  session.createSQLQuery("call getRecords","",Example.class);
    //      Query q = session.getNamedQuery("getRecordsSP");

            callableStatement = session.connection().prepareCall("call getRecords");
            callableStatement.execute();

            resultSet = callableStatement.getResultSet();

            while(resultSet.next())
                System.out.println(resultSet.getInt(1));
                System.out.println(resultSet.getString(2));
            

            //resultSet.

            System.out.print("Done");
            //List l = q.list();


        //  for(Iterator it = l.iterator() ;it.hasNext();)
        //      Object row [] = (Object []) it.next();

        //      Example row = (Example) it.next();
        //      System.out.println(row.getUser_id());
        //      System.out.println(row.getUser_data());
        //      System.out.println(row.length);
        //      System.out.println("ID " + row[0]);
        //  System.out.println("Data "+ row[1]);

        
        catch (Exception e) 
            e.printStackTrace();
        
        finally
            session.flush();
            session.close();
        
    

我基本上在不使用 hibernate getNamedQuery 的情况下重新设计了输入,但是 java.sql 类并且它起作用了!!!

【讨论】:

以上是关于在 Hibernate 中调用存储过程的主要内容,如果未能解决你的问题,请参考以下文章

在通用 DAO 中使用 Hibernate 调用存储过程的最佳方法是啥?

Hibernate 调用存储过程 该语句没有返回结果集

Hibernate JPA 存储过程调用?

不能用Hibernate调用PostgreSQL的11个存储过程

如何使用 Hibernate con Sql Server 2000 调用存储过程?

最近几天一直在搞Mybatis调用存储过程的问题,用<select>标签写的那种!然后用Java里写调用函数