【问题标题】:How to call a Stored Procedure from Hibernate having both IN and OUT parameters如何从具有 IN 和 OUT 参数的 Hibernate 调用存储过程
【发布时间】:2013-12-03 10:57:27
【问题描述】:

我想从 Hibernate 调用一个存储过程,它返回一个输出值。这是我的存储过程。

create procedure myProcedure
(  
in in_Id int,  
out out_Id int  
)  
begin  
...  
END;

我正在尝试这个来调用我的程序

Query query = session.createSQLQuery(  
"CALL myProcedure(:in_Id)")  
.setParameter("in_id", 123);   
//Not sure how to register out parameters...??      
List result = query.list();

我尝试了一切,但没有运气。你能帮我吗? 如果我尝试上述方法,它会说:

PROCEDURE myProcedure 的参数数量不正确;预期 2,得到 1

我尝试添加类似的输出参数

myProcedure(:out_id:in_Id)

然后它说

并非所有命名参数都已设置:

不知道out参数怎么设置?是不是像下面这样?

.setParameter("out_id", ?);

任何帮助表示赞赏:)

【问题讨论】:

标签: java mysql database hibernate stored-procedures


【解决方案1】:

假设您有一个输出基本类型的简单存储过程:

CREATE PROCEDURE count_comments (
   IN postId INT, 
   OUT commentCount INT
) 
BEGIN
    SELECT COUNT(*) INTO commentCount 
    FROM post_comment  
    WHERE post_comment.post_id = postId; 
END

您可以使用 JPA StoredProcedureQuery 调用此存储过程:

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("count_comments")
    .registerStoredProcedureParameter(
        "postId", Long.class, ParameterMode.IN)
    .registerStoredProcedureParameter(
        "commentCount", Long.class, ParameterMode.OUT)
    .setParameter("postId", 1L);
 
query.execute();
 
Long commentCount = (Long) query
    .getOutputParameterValue("commentCount");

【讨论】:

  • 如果我想返回多种类型(如String、Int)怎么办?出现错误:org.hibernate.MappingException:没有 JDBC 类型的方言映射:-1
  • 这可能会有所帮助,但我使用的是 mysql 而不是 Oracle。
【解决方案2】:
@Override
public String generateVoucherNumber(ExpenseHeaderDTO expenseHeaderDTO) {

    Session session = sessionFactory.getCurrentSession();
    ProcedureCall query =  session.createStoredProcedureCall("voucher_number");
            query.registerParameter(
                "module", String.class, ParameterMode.IN).bindValue("EMPLOYEE_EXPENSE");
            query.registerParameter(
                "voucherNumber", String.class, ParameterMode.OUT);

    ProcedureOutputs procedureResult=query.getOutputs();
    String voucherNumber= (String) procedureResult.getOutputParameterValue("voucherNumber");
    return voucherNumber;
}

参考上面的例子

【讨论】:

    【解决方案3】:
        just cal normal way but store response out param 
    in Object[] and we can also get multiple response value in Onject[]
    
        Object[] respnseCode = (Object[])session.createSQLQuery(
        "CALL myProcedure_only_in_parms (:in_Id)")
        .setParameter("in_id", 123);
        List result = query.list();
    
        sysout("out_Id"+respnseCode[0]);
    

    【讨论】:

      【解决方案4】:

      最简单的方法是将 out 参数作为返回参数的一部分返回 (仅当您有权访问存储过程时才相关)。
      开玩笑地添加一个像下面这样的存储过程

      create procedure myProcedure_only_in_parms (
         in in_Id int)
      begin
      call myProcedure(in_id,@out_Id) ;
      select @out_id
      END;
      

      完成后,通过以下方式将其与 Hibernet 一起使用非常简单

      Query query = session.createSQLQuery(
      "CALL myProcedure_only_in_parms (:in_Id)")
      .setParameter("in_id", 123);
      List result = query.list();
      

      结果包含out参数, 如果你想返回乘法参数,你可以通过做添加它 选择@parm1,@parm2,...,@parmn

      希望对你有帮助

      【讨论】:

        【解决方案5】:
        @PersistenceContext 
        private EntityManager entitymanager;
             @Override
                    public String function(int id, int emp_id, String letype, String days, Date fromdate, Date todate, String reason,
                            String backup, int user_id) {
        
                        //Session session = entitymanager.unwrap(Session.class);
        
                        StoredProcedureQuery  applyLeave = entitymanager.createStoredProcedureQuery("sp_apply_leave");
        
                        applyLeave.registerStoredProcedureParameter("p_id", Integer.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_emp_id", Integer.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_letype", String.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_days", String.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_fmdate", Date.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_todate", Date.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_reason", String.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_backper", String.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("p_user_id", Integer.class, ParameterMode.IN)
                                .registerStoredProcedureParameter("error_msg", String.class, ParameterMode.INOUT);
        
        
                        applyLeave.setParameter("p_id", id);
                        applyLeave.setParameter("p_emp_id" , emp_id);
                        applyLeave.setParameter("p_letype" , letype);
                        applyLeave.setParameter("p_days" , days);
                        applyLeave.setParameter("p_fmdate" , fromdate);
                        applyLeave.setParameter("p_todate" , todate);
                        applyLeave.setParameter("p_reason" , reason);
                        applyLeave.setParameter("p_backper" , backup);
                        applyLeave.setParameter("p_user_id" , user_id);
                        applyLeave.setParameter("error_msg", new String("error_msg"));
                        //applyLeave.executeUpdate();
        
                        String error_msg = (String) applyLeave.getOutputParameterValue("error_msg");
                        return error_msg;
        
                    }
        

        这里我有自动装配的实体管理器并在配置包中配置了休眠持久性

        【讨论】:

          【解决方案6】:

          示例:

                  Session session = em.unwrap(Session.class);
                  session.setHibernateFlushMode(FlushMode.MANUAL);
                  ProcedureCall query = session.createStoredProcedureCall("dbo.sp_getorderlistbyparam",BasicResult.class);
                  query.registerParameter("search_text",String.class, ParameterMode.IN).bindValue(searchText);
                  query.registerParameter("membership_nbr",String.class, 
                  query.registerParameter("is_debug",Integer.class, ParameterMode.IN).bindValue(0);
                  query.registerParameter("result_count",Integer.class, ParameterMode.OUT);
                  basicResults = (List<BasicResult>) query.getResultList();
                  ProcedureOutputs procedureOutputs = query.getOutputs();
                  parameterMap.put("totalOrderCnt" ,(Integer) procedureOutputs.getOutputParameterValue("result_count"));
          

          【讨论】:

          • 最好解释一下这些脚本的工作原理和方式。它将帮助未来的用户更好地理解。
          【解决方案7】:

          结果集 rs1=null;

               ArrayList<Lookup_master> list=new ArrayList<Lookup_master>();
          
               CallableStatement cStmt;
          
          
              try {
          
                  cStmt = hibernateConfiguration.dataSource().getConnection()
                              .prepareCall("{call SP_ADVSER_LOOKUPMASTER(?,?,?,?,?,?,?)}");
          
                  cStmt.setString(1,lookup_master.getLookup_code());
                  cStmt.setString(2,lookup_master.getLookup_type());
                  cStmt.setString(3,lookup_master.getLookup_name());
                  cStmt.setString(4,lookup_master.getMeaning());
                  cStmt.setString(5,request.getParameter("start_date"));
                  cStmt.setString(6,request.getParameter("end_date"));
          
                  cStmt.registerOutParameter(7, OracleTypes.CURSOR);
                  cStmt.executeQuery();
          
          
                  rs1 = (ResultSet) cStmt.getObject(7);
          
          
                  while (rs1.next()) {
          
                      Lookup_master lookup_master1=new Lookup_master();
          
                      lookup_master1.setLookup_id(rs1.getInt(1));
                      lookup_master1.setLookup_code(rs1.getString(2));
                      lookup_master1.setLookup_type(rs1.getString(3));
                      lookup_master1.setLookup_name(rs1.getString(4));
                      lookup_master1.setMeaning(rs1.getString(5));
                      lookup_master1.setStart_date(rs1.getDate(6));
                      lookup_master1.setEnd_date(rs1.getDate(7));
          
                       list.add(lookup_master1);
                      System.out.println(lookup_master1.getLookup_id());
          
                  }
          
          
          
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          
               return  list;
           }
          

          【讨论】:

          • cStmt = hibernateConfiguration.dataSource().getConnection() .prepareCall("{call SP_ADVSER_LOOKUPMASTER(?,?,?,?,?,?,?)}");
          猜你喜欢
          • 2015-01-07
          • 1970-01-01
          • 2011-07-29
          • 2012-04-18
          • 2020-09-22
          • 2018-09-19
          • 1970-01-01
          • 2021-05-18
          • 1970-01-01
          相关资源
          最近更新 更多