हालांकि यह सच है कि, कई मामलों में, एक मूल SQL कथन कई डेटाबेस परिवर्तनों या प्रश्नों के लिए काम पूरा कर देगा, यह अक्सर एक सर्वोत्तम अभ्यास होता है PreparedStatements
. का उपयोग करके आपको प्रदान किए गए लचीलेपन और लाभों का उपयोग करने के लिए ।
एक मानक JDBC स्टेटमेंट और एक PreparedStatement
. के बीच प्राथमिक अंतर लाभ . द्वारा सर्वोत्तम रूप से परिभाषित किया गया है कि एक PreparedStatement
आपको और आपके आवेदन को प्रदान करता है। नीचे हम PreparedStatements
. के तीन मुख्य लाभों की जांच करेंगे नियमित JDBC/SQL स्टेटमेंट पर।
एसक्यूएल इंजेक्शन रोकथाम
PreparedStatement
. का उपयोग करने का पहला लाभ क्या आप .setXYZ()
. की भीड़ का लाभ उठा सकते हैं? विधियाँ, जैसे कि .setString()
, जो आपके कोड को हमेशा खतरनाक SQL injection
को रोकने के लिए SQL कथन में पारित उद्धरणों जैसे विशेष वर्णों से स्वचालित रूप से बचने की अनुमति देता है हमला।
उदाहरण के लिए, एक मानक SQL कथन में, कथन के साथ सीधे इनलाइन मान सम्मिलित करना विशिष्ट हो सकता है, जैसे:
statement = "INSERT INTO books (title, primary_author, published_date) VALUES ('" + book.getTitle() + "', '" + book.getPrimaryAuthor() + "', '" + new Timestamp(book.getPublishedDate().getTime()) + "'";
यह आपको सम्मिलित मूल्यों से उद्धरणों और अन्य विशेष वर्णों से बचकर SQL इंजेक्शन को रोकने के लिए अपना स्वयं का कोड निष्पादित करने के लिए मजबूर करेगा।
इसके विपरीत, एक PreparedStatement
.setXYZ()
. का उपयोग करके निम्नानुसार लागू किया जा सकता है विधि निष्पादन के दौरान स्वचालित वर्ण से बचने के साथ मान सम्मिलित करने के तरीके:
ps = connection.prepareStatement("INSERT INTO books (title, primary_author, published_date) VALUES (?, ?, ?)");
ps.setString(1, book.getTitle());
ps.setString(2, book.getPrimaryAuthor());
ps.setTimestamp(3, new Timestamp(book.getPublishedDate().getTime()));
ps.executeUpdate();
पूर्व-संकलन
PreparedStatement
. का एक अन्य लाभ यह है कि SQL स्वयं pre-compiled
है एक बार और फिर सिस्टम द्वारा मेमोरी में बनाए रखा जाता है, बजाय इसके कि हर बार स्टेटमेंट को संकलित किया जाए। यह तेजी से निष्पादन की अनुमति देता है, खासकर जब एक PreparedStatement
batches
. के संयोजन में प्रयोग किया जाता है , जो आपको एक श्रृंखला . निष्पादित करने की अनुमति देता है (या batches
) एक ही डेटाबेस कनेक्शन के दौरान एक ही बार में SQL स्टेटमेंट्स का।
उदाहरण के लिए, यहां हमारे पास एक फ़ंक्शन है जो List
. को स्वीकार करता है किताबों की। प्रत्येक book
. के लिए सूची में, हम एक INSERT
execute निष्पादित करना चाहते हैं स्टेटमेंट, लेकिन हम उन सभी को PreparedStatements
. के एक बैच में जोड़ने जा रहे हैं और उन सभी को एक झटके में निष्पादित करें:
public void createBooks(List<Entity> books) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement ps = connection.prepareStatement("INSERT INTO books (title, primary_author, published_date) VALUES (?, ?, ?)");
) {
for (Entity book : books) {
ps.setString(1, book.getTitle());
ps.setString(2, book.getPrimaryAuthor());
ps.setTimestamp(3, new Timestamp(book.getPublishedDate().getTime()));
ps.addBatch();
}
ps.executeBatch();
}
}
एसक्यूएल स्टेटमेंट में असामान्य डेटा प्रकारों को सम्मिलित करना
PreparedStatement
. का अंतिम लाभ हम एसक्यूएल स्टेटमेंट में असामान्य डेटा प्रकारों को सम्मिलित करने की क्षमता को कवर करेंगे, जैसे कि Timestamp
, InputStream
, और भी बहुत कुछ।
उदाहरण के लिए, हम एक PreparedStatement
. का उपयोग कर सकते हैं .setBinaryStream()
. का उपयोग करके हमारे बुक रिकॉर्ड में एक कवर फ़ोटो जोड़ने के लिए विधि:
ps = connection.prepareStatement("INSERT INTO books (cover_photo) VALUES (?)");
ps.setBinaryStream(1, book.getPhoto());
ps.executeUpdate();