दिलचस्प पोस्ट
जावास्क्रिप्ट में MSIE और addEventListener समस्या? <Canvas> स्केलिंग करते समय प्रक्षेपण अक्षम करें हैश '#' के बिना अंगुल्यजेएस रूटिंग क्यों नहीं config.time_zone` कुछ भी करने लगते हैं? पायथन आयात सीएसवी सूची में अनाम स्ट्रैक्ट्स / यूनियनों के साथ सी कोड कैसे संकलित करें? आप C # कंसोल एप्लिकेशन के लिए टाइमर कैसे जोड़ते हैं स्ट्रिंग नाम का उपयोग किए बिना संपदा-बदले गए ईवेंट को कैसे बढ़ाएं मैं एंड्रॉइड में रूट एक्सेस का अनुरोध कैसे करूं? एंड्रॉइड में टैब सूचक टेक्स्ट का रंग कैसे बदल सकता है? स्पैमबोट्स से वेबसाइटों पर ईमेल को बचाने के कुछ तरीके क्या हैं? क्या कोई विकिपीडिया एपीआई है? चरित्र तारों की सरणी में विभाजित स्ट्रिंग इंटेन्ट (फ़्रोयो) का उपयोग करके एंड्रॉइड कैलेंडर ऐप्लिकेशन लॉन्च कैसे करें XDocument से XML नोड कैसे प्राप्त करें

मैं एक एसक्यूएल को तैयार स्थिति में कैसे प्राप्त करूं?

मेरे पास निम्न विधि हस्ताक्षर के साथ एक सामान्य जावा विधि है:

private static ResultSet runSQLResultSet(String sql, Object... queryParams) 

यह एक कनेक्शन खोलता है, एसक्यूएल स्टेटमेंट का उपयोग करके PreparedStatement करता है और queryParams पैरामीटर चर लंबाई सरणी में पैरामीटर बनाता है, इसे चलाता है, ResultSet कैश करता है ( CachedRowSetImpl ), कनेक्शन को बंद करता है, और कैश्ड परिणाम सेट लौटाता है।

मेरे पास त्रुटियां लॉग करने वाले विधि में अपवाद हैंडलिंग है I मैं लॉग के हिस्से के रूप में SQL कथन लॉग इन करता हूं क्योंकि यह डीबगिंग के लिए बहुत उपयोगी है I मेरी समस्या यह है कि स्ट्रिंग वेरिएबल sql लॉग करना वास्तविक कथन के बजाय टेम्पलेट स्टेटमेंट को लॉग करता है? मैं निष्पादित किया गया वास्तविक वक्तव्य (या निष्पादित करने का प्रयास) लॉग करना चाहता हूं।

इसलिए … क्या वास्तविक एसक्यूएल स्टेटमेंट प्राप्त करने का कोई तरीका है जो कि PreparedStatement किए गए PreparedStatement द्वारा चलाया जाएगा? (इसे स्वयं के निर्माण के बिना । अगर मुझे PreparedStatement's एसक्यूएल एक्सेस करने का कोई रास्ता नहीं मिल रहा है, तो शायद मैं इसे अपने कब्जे के catch खुद बनाऊंगा।)

वेब के समाधान से एकत्रित समाधान "मैं एक एसक्यूएल को तैयार स्थिति में कैसे प्राप्त करूं?"

तैयार बयान का उपयोग करना, "SQL क्वेरी" नहीं है:

  • आपके पास एक बयान है, जिसमें प्लेसहोल्डर शामिल हैं
    • इसे डीबी सर्वर पर भेजा जाता है
    • और वहां तैयार
    • जिसका अर्थ है कि SQL कथन "विश्लेषण" है, पार्स किया जाता है, इसका प्रतिनिधित्व करने वाला कुछ डेटा-संरचना स्मृति में तैयार किया जाता है
  • और, फिर, आपके पास चर हैं
    • जो सर्वर को भेजे जाते हैं
    • और तैयार कथन निष्पादित होता है – उन डेटा पर काम करना

लेकिन वास्तविक वास्तविक एसक्यूएल क्वेरी का फिर से निर्माण नहीं है – न तो जावा की तरफ, न ही डेटाबेस की तरफ।

इसलिए, तैयार कथन के एसक्यूएल प्राप्त करने का कोई रास्ता नहीं है- क्योंकि ऐसा कोई एसक्यूएल नहीं है

डीबगिंग उद्देश्य के लिए, समाधान या तो हैं:

  • Ouput कथन का कोड, प्लेसहोल्डर और डेटा की सूची के साथ
  • या "हाथ से" कुछ एसक्यूएल क्वेरी "निर्माण" करने के लिए

यह कहीं भी जेडीबीसी एपीआई अनुबंध में निश्चित नहीं है, लेकिन अगर आप भाग्यशाली हैं, तो जेडीबीसी चालक सवाल में पूरे एसक्यूएल को सिर्फ PreparedStatement#toString() अर्थात

 System.out.println(preparedStatement); 

कम से कम MySQL 5.x और PostgreSQL 8.x JDBC ड्राइवरों का समर्थन करता है। हालांकि, अधिकांश अन्य जेडीबीसी ड्राइवर इसका समर्थन नहीं करते हैं। यदि आपके पास ऐसा कोई है, तो आपका सर्वश्रेष्ठ शर्त Log4jdbc या P6Spy का उपयोग कर रहा है

वैकल्पिक रूप से, आप एक जेनेरिक फ़ंक्शन भी लिख सकते हैं, जो एक Connection , एक एसक्यूएल स्ट्रिंग और कथन मान लेता है और एसक्यूएल स्ट्रिंग को PreparedStatement बाद PreparedStatement गई है। किकऑफ़ उदाहरण:

 public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < values.length; i++) { preparedStatement.setObject(i + 1, values[i]); } logger.debug(sql + " " + Arrays.asList(values)); return preparedStatement; } 

और इसे इस्तेमाल के रूप में

 try { connection = database.getConnection(); preparedStatement = prepareStatement(connection, SQL, values); resultSet = preparedStatement.executeQuery(); // ... 

एक अन्य विकल्प एक कस्टम PreparedStatement किए गए स्थान को लागू करना है जो निर्माण पर वास्तविक PreparedStatement किए गए स्थान को लपेटता है और सभी तरीकों को अध्यारोहित करता है ताकि वह वास्तविक PreparedStatement की गई setXXX() के तरीकों को कॉल करे और सभी सेट setXXX() तरीकों में मान एकत्र करें और "वास्तविक "जब भी executeXXX() तरीकों में से एक को एसक्यूएल स्ट्रिंग कहा जाता है (काफी काम है, लेकिन अधिकांश आईडीई डेकोरेटर पद्धतियों के लिए executeXXX() प्रदान करता है, एक्लिप्स करता है)। अंत में बस इसके बजाय इसका उपयोग करें यह भी मूल रूप से है कि क्या P6Spy और consorts पहले से ही हुड के तहत करते हैं।

यदि आप क्वेरी निष्पादित कर रहे हैं और ResultSet (आप इस परिदृश्य में कम से कम) की उम्मीद कर रहे हैं, तो आप बस इसी तरह से ResultSet 's getStatement() कॉल कर सकते हैं:

 ResultSet rs = pstmt.executeQuery(); String executedQuery = rs.getStatement().toString(); 

वेरिएबल executedQuery में उस कथन को शामिल किया जाएगा जिसका उपयोग ResultSet बनाने के लिए किया गया था।

अब, मुझे पता है कि यह सवाल काफी पुराना है, लेकिन मुझे उम्मीद है कि यह किसी को मददगार होगा ..

मैं जावा 8, जेडीबीसी ड्राइवर MySQL कनेक्टर वी। 5.1.31 के साथ उपयोग कर रहा हूं।

मुझे इस पद्धति का उपयोग करते हुए वास्तविक एसक्यूएल स्ट्रिंग मिल सकती है:

 // 1. make connection somehow, it's conn variable // 2. make prepered statement template PreparedStatement stmt = conn.prepareStatement( "INSERT INTO oc_manufacturer" + " SET" + " manufacturer_id = ?," + " name = ?," + " sort_order=0;" ); // 3. fill template stmt.setInt(1, 23); stmt.setString(2, 'Google'); // 4. print sql string System.out.println(((JDBC4PreparedStatement)stmt).asSql()); 

तो यह इस तरह smth देता है:

 INSERT INTO oc_manufacturer SET manufacturer_id = 23, name = 'Google', sort_order=0; 

यदि आप MySQL का उपयोग कर रहे हैं तो आप MySQL के क्वेरी लॉग का उपयोग कर क्वेरी लॉग कर सकते हैं । मुझे नहीं पता कि अन्य विक्रेताओं ने यह सुविधा प्रदान की है, लेकिन संभावना है कि वे क्या करते हैं

बस कार्य:

 public static String getSQL (Statement stmt){ String tempSQL = stmt.toString(); //please cut everything before sql from statement //javadb...: int i1 = tempSQL.indexOf(":")+2; tempSQL = tempSQL.substring(i1); return tempSQL; } 

तैयार स्थिति के लिए भी ठीक है।

मैं ओरालेस 11 जी का उपयोग कर रहा हूं और तैयार एसईसीएल को तैयार स्तर से प्राप्त करने के लिए प्रबंधन नहीं कर सकता। @ पास्कल मार्टिन के उत्तर को पढ़ने के बाद मैं समझता हूं कि क्यों

मैंने तैयार किए गए अवस्था का उपयोग करने के विचार को छोड़ दिया और एक सरल पाठ स्वरूपक का उपयोग किया जो मेरी ज़रूरतों को पूरा करता था यहां मेरा उदाहरण है:

 //I jump to the point after connexion has been made ... java.sql.Statement stmt = cnx.createStatement(); String sqlTemplate = "SELECT * FROM Users WHERE Id IN ({0})"; String sqlInParam = "21,34,3434,32"; //some random ids String sqlFinalSql = java.text.MesssageFormat(sqlTemplate,sqlInParam); System.out.println("SQL : " + sqlFinalSql); rsRes = stmt.executeQuery(sqlFinalSql); 

आप समझ सकते हैं कि एसक्यूएल इनपाराम को एक (के लिए, जबकि) लूप में गतिशील रूप से बनाया जा सकता है, मैंने एसक्यूएल क्वेरी के लिए एक स्ट्रिंग टेम्पलेट फॉर्मेटर के रूप में सेवा देने के लिए MessageFormat क्लास का इस्तेमाल करने की बात समझने के लिए सरल बना दिया है।

मैंने PrepareStatement से SQL को मुद्रित करने के लिए निम्न कोड लागू किया है

 public void printSqlStatement(PreparedStatement preparedStatement, String sql) throws SQLException{ String[] sqlArrya= new String[preparedStatement.getParameterMetaData().getParameterCount()]; try { Pattern pattern = Pattern.compile("\\?"); Matcher matcher = pattern.matcher(sql); StringBuffer sb = new StringBuffer(); int indx = 1; // Parameter begin with index 1 while (matcher.find()) { matcher.appendReplacement(sb,String.valueOf(sqlArrya[indx])); } matcher.appendTail(sb); System.out.println("Executing Query [" + sb.toString() + "] with Database[" + "] ..."); } catch (Exception ex) { System.out.println("Executing Query [" + sql + "] with Database[" + "] ..."); } } 

एसक्यूएल तैयार किए गए स्टॉमेंन्टों को तर्कों की सूची के साथ कनवर्ट करने के लिए कोड स्निपेट। इससे मेरा काम बनता है

  /** * * formatQuery Utility function which will convert SQL * * @param sql * @param arguments * @return */ public static String formatQuery(final String sql, Object... arguments) { if (arguments != null && arguments.length <= 0) { return sql; } String query = sql; int count = 0; while (query.matches("(.*)\\?(.*)")) { query = query.replaceFirst("\\?", "{" + count + "}"); count++; } String formatedString = java.text.MessageFormat.format(query, arguments); return formatedString; } 

मैंने अपने एसक्यूएल से तैयार किए गए स्टाटेमेंट से तैयार किए गए स्टाटेमेंट.स्टोस्टिंग () का उपयोग कर लिया है मेरे मामले में स्ट्रिंग () स्ट्रिंग को इस तरह से रिटर्न करता है:

 org.hsqldb.jdbc.JDBCPreparedStatement@7098b907[sql=[INSERT INTO TABLE_NAME(COLUMN_NAME, COLUMN_NAME, COLUMN_NAME) VALUES(?, ?, ?)], parameters=[[value], [value], [value]]] 

अब मैंने एक विधि (जावा 8) बनाई है, जो क्वेरी और मान दोनों को निकालने और उन्हें मानचित्र में डाल करने के लिए regex का उपयोग कर रहा है:

 private Map<String, String> extractSql(PreparedStatement preparedStatement) { Map<String, String> extractedParameters = new HashMap<>(); Pattern pattern = Pattern.compile(".*\\[sql=\\[(.*)],\\sparameters=\\[(.*)]].*"); Matcher matcher = pattern.matcher(preparedStatement.toString()); while (matcher.find()) { extractedParameters.put("query", matcher.group(1)); extractedParameters.put("values", Stream.of(matcher.group(2).split(",")) .map(line -> line.replaceAll("(\\[|])", "")) .collect(Collectors.joining(", "))); } return extractedParameters; } 

यह विधि उस स्थान को देता है जहां हमारे पास महत्वपूर्ण-मूल्य जोड़े हैं:

 "query" -> "INSERT INTO TABLE_NAME(COLUMN_NAME, COLUMN_NAME, COLUMN_NAME) VALUES(?, ?, ?)" "values" -> "value, value, value" 

अब – यदि आप मूल्यों को सूची के रूप में चाहते हैं तो आप केवल इसका उपयोग कर सकते हैं:

 List<String> values = Stream.of(yourExtractedParametersMap.get("values").split(",")) .collect(Collectors.toList()); 

यदि आपके तैयार किए गए स्टेटस .स्ट्रेसिंग () मेरे मामले की तुलना में अलग है, तो यह केवल "समायोजन" रीजेक्स की बात है।

ऐसा करने के लिए आपको एक जेडीबीसी कनेक्शन और / या ड्राइवर की जरूरत है जो कम स्तर पर एसक्यूएल को लॉगिंग का समर्थन करता है।

Log4jdbc पर एक नज़र डालें