2009-11-09 6 views
14

मेरा प्रश्न Getting the return value of a PL/SQL function via Hibernateरिटर्न पैरामीटर के साथ हाइबरनेट से ओरेकल फ़ंक्शन को कैसे कॉल करें?

मेरे पास एक ऐसा फ़ंक्शन है जो आंतरिक रूप से कुछ संशोधन करता है और यह एक मूल्य देता है।

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 के साथ काम नहीं करता है:

मूल विचार इस तरह कुछ करने के लिए किया गया था। ऐसा कुछ करने का अनुशंसित तरीका क्या है?

क्या मेरे कथन के भीतर से घोषित चर निकालने का कोई तरीका है?

उत्तर

29

हाइबरनेट सत्र 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 
    } 
}); 
+0

क्या आप एक उदाहरण प्रदान करना चाहते हैं? मैं थोड़ा सा खो गया हूं कि समारोह से परिणाम कैसे प्राप्त करें। क्या मुझे आउट पैरामीटर का उपयोग करने की ज़रूरत है? – Mauli

+0

मैंने ऊपर एक उदाहरण प्रदान किया है। आपके फ़ंक्शन/संग्रहीत प्रक्रिया के आधार पर आपको अन्य readyocation फॉर्म को 'readyCall()' के बजाय उपयोग करने की आवश्यकता हो सकती है - CallableStatement दस्तावेज़ दोनों का वर्णन करता है। – ChssPly76

+1

@ ChssPly76: मैं कभी भी 'डूवर्क (..)' के बारे में कभी नहीं जानता था, जो कि हाइबरनेट के '@ नामांकित नेटवर्क्चर' से काफी बेहतर है, जिसके लिए पहले पैरामीटर (आउट पैरामीटर) के रूप में एक रिफ्रसर को वापस करने के लिए स्पोक/फ़ंक्शन की आवश्यकता होती है। –

6

हाँ, आप एक बाहर पैरामीटर का उपयोग करने की आवश्यकता है। आप 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 
    } 
}); 
+1

@ ChssPly76, मैंने इसे एक ही समय में लिखा था, और मैंने इसे पोस्ट करने के बाद, आपका पहले से ही वहां था। न ही यह एक सटीक प्रति है, हालांकि निश्चित रूप से यह काफी समान है, क्योंकि समस्या से शुरू करना बहुत आसान है। यदि आप अपना डाउन वोट हटा देते हैं तो यह अच्छा होगा। – Ladlestein

+1

एसओ पर आम तौर पर स्वीकार्य शिष्टाचार आपके उत्तर को हटाना है यदि आप देखते हैं कि एक और ऐसा पहले से ही है जब तक कि वे दोनों एक ही समय में सचमुच लिखे गए थे। इस मामले में मेरा और तुम्हारा बीच 16 मिनट का अंतर है। यदि आप इसे अभी हटा देते हैं, तो अगली प्रतिनिधि recalc के दौरान डाउन-वोट के कारण खो गया प्रतिनिधि आपके खाते में बहाल कर दिया जाएगा (वे आमतौर पर हर 6 से 8 सप्ताह में किए जाते हैं)। डाउन-वोट को रद्द नहीं किया जा सकता है (यह बहुत पुराना है) जब तक आपका उत्तर संपादित नहीं किया जाता है। – ChssPly76

+11

ओह। क्या यह आमतौर पर उन मामलों में किसी को वोट देने के लिए शिष्टाचार भी स्वीकार किया जाता है? – Ladlestein

1
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 "); 
} 
+2

'कनेक्शन()' विधि को 'हाइबरनेट 3.3.2GA + ' – Stephan

+1

में बहिष्कृत किया गया है, यहां तक ​​कि' कनेक्शन()' बहिष्कृत है। उन संस्करणों में आप जिस तरह से पहुंच सकते हैं। – takacsot

4

वैकल्पिक कोड :)

अगर आप निर्देशित करने के लिए परिणाम आप कोड नीचे का उपयोग कर सकते हैं

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

4

मैं an article about various ways of calling Oracle stored procedures and functions from Hibernate तो लिखा था, यह संक्षेप में प्रस्तुत करने के लिए, आप निम्नलिखित विकल्प हैं:

  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. एक साथ देशी ओरेकल क्वेरी:

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

जब मैं पहला विकल्प आज़माता हूं, तो यह निम्न अपवाद के साथ परिणाम देता है। बस FYI: org.hibernate.MappingException: अज्ञात इकाई: java.lang.Integer – akaya

+0

आप मेरी पुस्तक, उच्च-प्रदर्शन जावा पर्सिस्टेंस, गिटहब रिपोजिटरी और [परीक्षण स्वयं को चला सकते हैं] (https://github.com/vladmihalcea/ उच्च प्रदर्शन-जावा-हठ/ब्लॉब/8a2447eddda1b03371197db75c1ddecd32a8654e/कोर/src/परीक्षण/जावा/com/vladmihalcea/पुस्तक/hpjp/हाइबरनेट/एसपी/OracleStoredProcedureTest.java # L209)। मैंने इसे हाइबरनेट 5.2.11 के साथ चलाया है और यह एक आकर्षण की तरह काम करता है। –

संबंधित मुद्दे

 संबंधित मुद्दे