2013-02-27 127 views
9

मेरी समझ के अनुसार जावा में प्रीपेडस्टेटमेंट का उपयोग हम इसे कई बार उपयोग कर सकते हैं। लेकिन मुझे वसंत जेडीबीसी के प्रीपेडस्टेटमेंट निर्माता का उपयोग करके कुछ भ्रम है।स्प्रिंग जेडीबीसी के प्रीपेडस्टेटमेंट निर्माता का उपयोग करने का उचित तरीका क्या है?

उदाहरण के लिए कोड को अपनाने पर विचार,

public class SpringTest { 

    JdbcTemplate jdbcTemplate; 
    PreparedStatementCreator preparedStatementCreator; 
    ResultSetExtractor<String> resultSetExtractor; 

    public SpringTest() throws SQLException { 

     jdbcTemplate = new JdbcTemplate(OracleUtil.getDataSource()); 

     preparedStatementCreator = new PreparedStatementCreator() { 
      String query = "select NAME from TABLE1 where ID=?"; 
      public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 
       return connection.prepareStatement(query); 
      } 
     }; 

     resultSetExtractor = new ResultSetExtractor<String>() { 
      public String extractData(ResultSet resultSet) throws SQLException, 
      DataAccessException { 
       if (resultSet.next()) { 
        return resultSet.getString(1); 
       } 
       return null; 
      } 
     }; 
    } 
    public String getNameFromId(int id){ 
     return jdbcTemplate.query(preparedStatementCreator, new Table1Setter(id), resultSetExtractor); 
    } 

    private static class Table1Setter implements PreparedStatementSetter{ 

     private int id; 
     public Table1Setter(int id) { 
      this.id =id; 
     } 
     @Override 
     public void setValues(PreparedStatement preparedStatement) throws SQLException { 
      preparedStatement.setInt(1, id); 
     } 
    } 
    public static void main(String[] args) { 
     try { 
      SpringTest springTest = new SpringTest(); 

      for(int i=0;i<10;i++){ 
       System.out.println(springTest.getNameFromId(i)); 
      } 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

इस कोड को जब मैं springTest.getNameFromId कहा जाता है के अनुसार (पूर्णांक आईडी) विधि है, यह नाम दिया आईडी से लौटता है, यहाँ मैं PreparedStatement और बनाने के लिए उपयोग किया है PreparedStatementCreator इनपुट पैरामीटर सेट करने के लिए तैयार स्टेटमेंटसेटर और मुझे परिणाम SetExtractor से परिणाम मिला। लेकिन प्रदर्शन बहुत धीमा है।

डिबगिंग और तैयार किए जाने के बाद प्रीपेडस्टेटमेंट निर्माता और जेडीबीसी टेम्पलेट के अंदर क्या होता है मुझे पता चला है कि प्रीपेर्डस्टेटमेंट निर्माता प्रत्येक तैयार नई तैयारी करता है ... !!!

प्रत्येक बार जब मैं कॉल विधि jdbcTemplate.query (readyStatementCreator, readyStatementSetter, resultSetExtractor) कहता हूं, यह नया तैयार स्टेमेंट बनाता है और यह धीमा प्रदर्शन करता है।

क्या प्रीपेयरस्टेटमेंट निर्माता का उपयोग करने का यह सही तरीका है? क्योंकि इस कोड में मैं प्रीपेयरस्टेटमेंट का पुन: उपयोग करने में असमर्थ हूं। और यदि प्रीपेडस्टेटमेंट निर्माता की पुन: प्रयोज्यता के लाभ के मुकाबले प्रीपेडस्टेटमेंट निर्माता का उपयोग करने का यह सही तरीका है?

उत्तर

2

तैयार वक्तव्य आमतौर पर अंतर्निहित कनेक्शन पूल द्वारा कैश किए जाते हैं, इसलिए आपको हर बार एक नया निर्माण करने की चिंता करने की आवश्यकता नहीं है या नहीं।

तो मुझे लगता है कि आपका वास्तव में उपयोग सही है।

JdbcTemplate यह क्रियान्वित करने के बाद बयान बंद कर देता है, तो आप वास्तव में एक ही तैयार बयान आप छद्म बयान कर सकता है पुन: उपयोग और केवल उदाहरण के रूप में बयान निर्माता

उदाहरण (परीक्षण नहीं के लिए में करीब विधि रोकना, करना चाहते हैं):

public abstract class ReusablePreparedStatementCreator implements PreparedStatementCreator { 

    private PreparedStatement statement; 

    public PreparedStatement createPreparedStatement(Connection conn) throws SQLException { 
     if (statement != null) 
      return statement; 

     PreparedStatement ps = doPreparedStatement(conn); 

     ProxyFactory pf = new ProxyFactory(ps); 
     MethodInterceptor closeMethodInterceptor = new MethodInterceptor() { 

      @Override 
      public Object invoke(MethodInvocation invocation) throws Throwable { 
       return null; // don't close statement 
      } 
     }; 

     NameMatchMethodPointcutAdvisor closeAdvisor = new NameMatchMethodPointcutAdvisor(); 
     closeAdvisor.setMappedName("close"); 
     closeAdvisor.setAdvice(closeMethodInterceptor); 
     pf.addAdvisor(closeAdvisor); 

     statement = (PreparedStatement) pf.getProxy(); 

     return statement;  
    } 

    public abstract PreparedStatement doPreparedStatement(Connection conn) throws SQLException; 

    public void close() { 
     try { 
      PreparedStatement ps = (PreparedStatement) ((Advised) statement).getTargetSource().getTarget(); 
      ps.close(); 
     } catch (Exception e) { 
      // handle exception 
     } 
    } 

} 
1

डिबगिंग के बाद और क्या PreparedStatementCreator और JdbcTemplate अंदर होता है मुझे पता है कि PreparedStatementCreator हर बार नया PreparedStatement बनाता मिला की जांच कर रहे ... !!!

मैं क्यों कि इतने चौंकाने वाला है, क्योंकि यह अपने खुद के कोड कि connection.prepareStatement(query); को फोन करके एक नया PreparedStatement हर बार बनाता है यकीन नहीं है। यदि आप एक ही पुन: उपयोग करना चाहते हैं, तो आपको एक नया निर्माण नहीं करना चाहिए।

+0

मैं भी साथ एक ही PreparedStatement लौटने, तो मैं त्रुटि "बंद कनेक्शन" हो गया, और करने की कोशिश की मैं एक ही कनेक्शन वस्तु का उपयोग करने की तुलना में मैं आप के बारे में बात कर रहे हैं त्रुटि "बंद वक्तव्य" –

+0

मिला की कोशिश की आपका नमूना उपरोक्त होगा, ऐसा इसलिए होगा क्योंकि आप उचित लेनदेन प्रबंधन कर रहे हैं। एक लेनदेन प्रगति पर है, सब कुछ एक ही कनेक्शन के खिलाफ निष्पादित होगा, और उसी कथन का पुन: उपयोग करना कोई समस्या नहीं होनी चाहिए। –

+0

क्षमा करें, ऊपर टाइपो ... इसे "आप * उचित लेनदेन प्रबंधन नहीं कर रहे हैं" बनाते हैं। –

3

आप प्रीपेर्डस्टेटमेंट निर्माता का उपयोग करने के सही रास्ते पर हैं।

  1. प्रत्येक नए लेन-देन में, आप नए ब्रांड PreparedStatement उदाहरण बनाना चाहिए, यह निश्चित रूप से सही है। PreparedStatementCreator मुख्य रूप से नहीं कह रही है कि आप नया उदाहरण प्रत्येक itme resue चाहिए कोड ब्लॉक रैप करने के लिए PreparedStatement बनाने के लिए डिज़ाइन किया गया है उदाहरण आसानी से।
  2. प्रीपेडस्टेटमेंट मुख्य रूप से टेम्पलेट और प्री-कंपाइल एसक्यूएल कथन डीबीएमएस भेजने के लिए डिज़ाइन किया गया है जो SQL निष्पादन के लिए कुछ पूर्व-संकलित समय को बचाएगा।

संक्षेप में, आपने जो किया वह सही है। तैयार किए गए स्टेटमेंटसे बेहतर प्रदर्शन होगा

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

  • कोई संबंधित समस्या नहीं^_^