如何使用返回参数从Hibernate调用Oracle函数?

我的问题非常类似于通过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 } }); 

是的,您确实需要使用out参数。 如果你使用doWork()方法,你会做这样的事情:

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

替代代码:)

如果你想直接结果,你可以使用下面的代码

  int result = session.doReturningWork(new ReturningWork() { @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

我写了一篇关于从Hibernate调用Oracle存储过程和函数的各种方法的文章,所以总结一下,你有以下几种选择:

  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 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(:id, :transId) FROM DUAL") .setParameter("postId", 1) .setParameter("transId", 1) .getSingleResult(); 
 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 "); }