簡體   English   中英

如何使用返回參數從 Hibernate 調用 Oracle 函數?

[英]How to call an Oracle function from Hibernate with a return parameter?

我的問題很像通過 Hibernate 獲取 PL/SQL 函數的返回值

我有一個函數在內部進行一些修改並返回一個值。

最初的想法是做這樣的事情:

protected Integer checkXXX(Long id, Long transId)
        throws Exception {
    final String sql = "SELECT MYSCHEMA.MYFUNC(" + id + ", "
            + transId + ") FROM DUAL";
    final BigDecimal nr = (BigDecimal) this.getHibernateTemplate()
            .getSessionFactory().getCurrentSession().createSQLQuery(sql)
            .uniqueResult();
    return nr.intValue();
}

不幸的是,這不適用於 Oracle。 做這樣的事情的推薦方法是什么?

有沒有辦法從我的語句中提取聲明的變量?

Hibernate Session 提供了一個doWork()方法,讓您可以直接訪問java.sql.Connection 然后您可以創建並使用java.sql.CallableStatement來執行您的函數:

session.doWork(new Work() {
  public void execute(Connection connection) throws SQLException {
    CallableStatement call = connection.prepareCall("{ ? = call MYSCHEMA.MYFUNC(?,?) }");
    call.registerOutParameter( 1, Types.INTEGER ); // or whatever it is
    call.setLong(2, id);
    call.setLong(3, transId);
    call.execute();
    int result = call.getInt(1); // propagate this back to enclosing class
  }
});

您有以下選擇:

  1. 使用@NamedNativeQuery

     @org.hibernate.annotations.NamedNativeQuery( name = "fn_my_func", query = "{ ? = call MYSCHEMA.MYFUNC(?, ?) }", callable = true, resultClass = Integer.class ) Integer result = (Integer) entityManager.createNamedQuery("fn_my_func") .setParameter(1, 1) .setParameter(2, 1) .getSingleResult();
  2. 使用 JDBC API:

     Session session = entityManager.unwrap( Session.class ); final AtomicReference<Integer> result = new AtomicReference<>(); session.doWork( connection -> { try (CallableStatement function = connection .prepareCall( "{ ? = call MYSCHEMA.MYFUNC(?, ?) }" ) ) { function.registerOutParameter( 1, Types.INTEGER ); function.setInt( 2, 1 ); function.setInt( 3, 1 ); function.execute(); result.set( function.getInt( 1 ) ); } } );
  3. 使用本機 Oracle 查詢:

     Integer result = (Integer) entityManager.createNativeQuery( "SELECT MYSCHEMA.MYFUNC(:postId, :transId) FROM DUAL") .setParameter("postId", 1) .setParameter("transId", 1) .getSingleResult();

是的,您確實需要使用 out 參數。 如果你使用 doWork() 方法,你會做這樣的事情:

session.doWork(new Work() {
   public void execute(Connection conn) {
      CallableStatement stmt = conn.prepareCall("? = call <some function name>(?)");
      stmt.registerOutParameter(1, OracleTypes.INTEGER);
      stmt.setInt(2, <some value>);
      stmt.execute();
      Integer outputValue = stmt.getInt(1);
      // And then you'd do something with this outputValue
   }
});

替代代碼:)

如果你想直接結果,你可以使用下面的代碼

 int result = session.doReturningWork(new ReturningWork<Integer>() {
  @Override
   public Integer  execute(Connection connection) throws SQLException {
    CallableStatement call = connection.prepareCall("{ ? = call MYSCHEMA.MYFUNC(?,?) }");
    call.registerOutParameter( 1, Types.INTEGER ); // or whatever it is
    call.setLong(2, id);
    call.setLong(3, transId);
    call.execute();
    return call.getInt(1); // propagate this back to enclosing class
  }
});

http://keyurj.blogspot.com.tr/2012/12/dowork-in-hibernate.html

public static void getThroHibConnTest() throws Exception {
    logger.debug("UsersActiion.getThroHibConnTest() | BEG ");
    Transaction tx = null;
    Connection conn = null;
    CallableStatement cs = null;
    Session session = HibernateUtil.getInstance().getCurrentSession();
    try {
        tx = session.beginTransaction();
        conn = session.connection();

        System.out.println("Connection = "+conn);
        if (cs == null)
        {
            cs = 
                conn.prepareCall("{ ?=call P_TEST.FN_GETSUM(?,?) }");
        }
        cs.clearParameters();
        cs.registerOutParameter(1,OracleTypes.INTEGER);
        cs.setInt(2,1);
        cs.setInt(3,2);
        cs.execute();
        int retInt=cs.getInt(1);
        tx.commit();            
    }catch (Exception ex) {  
        logger.error("UsersActiion.getThroHibConnTest() | ERROR | " , ex);  
        if (tx != null && tx.isActive()) {
            try {
                // Second try catch as the rollback could fail as well
                tx.rollback();
            } catch (HibernateException e1) {
                logger.debug("Error rolling back transaction");
            }
            // throw again the first exception
            throw ex;
        }
    }finally{
        try {
            if (cs != null) {
                cs.close();
                cs = null;
            }
            if(conn!=null)conn.close();

        } catch (Exception ex){;}
    }
    logger.debug("UsersActiion.getThroHibConnTest() | END ");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM