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

后端 未结 5 1600
你的背包
你的背包 2020-11-29 05:47

My question is very much like Getting the return value of a PL/SQL function via Hibernate

I have a function which does some modifications internally and it returns a

相关标签:
5条回答
  • 2020-11-29 05:50

    Alternative code :)

    if you want to direct result you can use below code

     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

    0 讨论(0)
  • 2020-11-29 05:56

    Hibernate Session provides a doWork() method that gives you direct access to java.sql.Connection. You can then create and use java.sql.CallableStatement to execute your function:

    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
      }
    });
    
    0 讨论(0)
  • 2020-11-29 06:10
    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 ");
    }
    
    0 讨论(0)
  • 2020-11-29 06:16

    I wrote an article about various ways of calling Oracle stored procedures and functions from Hibernate so, to summarize it, you have the following options:

    1. With a @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. With 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. With a native Oracle query:

      Integer result = (Integer) entityManager.createNativeQuery(
          "SELECT MYSCHEMA.MYFUNC(:postId, :transId) FROM DUAL")
          .setParameter("postId", 1)
          .setParameter("transId", 1)
          .getSingleResult();
      
    0 讨论(0)
  • 2020-11-29 06:16

    Yes, you do need to use an out parameter. If you use the doWork() method, you'd do something like this:

    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
       }
    });
    
    0 讨论(0)
提交回复
热议问题