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

Mau*_*uli 17 java oracle hibernate

我的问题非常类似于通过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();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不适用于Oracle.做这样的事情的推荐方法是什么?

有没有办法从我的语句中提取声明的变量?

Chs*_*y76 33

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
  }
});
Run Code Online (Sandbox Code Playgroud)


Vla*_*cea 9

我写了一篇关于从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();    
    
    Run Code Online (Sandbox Code Playgroud)
  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 ) );
        }
    } );            
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用本机Oracle查询:

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

  • 当我尝试第一个选项时,会出现以下异常。仅供参考:org.hibernate.MappingException:未知实体:java.lang.Integer (2认同)

Lad*_*ein 6

是的,您确实需要使用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
   }
});
Run Code Online (Sandbox Code Playgroud)

  • 哦.在这些情况下向某人投票是否也是普遍接受的礼仪? (11认同)

小智 5

备用代码:)

如果要直接结果,可以使用以下代码

 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
  }
});
Run Code Online (Sandbox Code Playgroud)

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