একটি প্রস্তুতিমূলক স্ট্যাটমেন্ট একাধিকবার পুনরায় ব্যবহার করা


99

কোনও পুল ছাড়াই একক সাধারণ সংযোগের সাথে প্রিপেইডস্টেটমেন্ট ব্যবহারের ক্ষেত্রে, আমি কি প্রতিটি ডিএমএল / এসকিউএল অপারেশনের জন্য প্রস্তুত বিবৃতিগুলির শক্তি ধরে রাখার জন্য একটি উদাহরণ তৈরি করতে পারি?

আমি বলতে চাইতেছি:

for (int i=0; i<1000; i++) {
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setObject(1, someValue);
    preparedStatement.executeQuery();
    preparedStatement.close();
}

পরিবর্তে:

PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i=0; i<1000; i++) {
    preparedStatement.clearParameters();
    preparedStatement.setObject(1, someValue);
    preparedStatement.executeQuery();
}
preparedStatement.close();

আমার প্রশ্নটি উত্থাপিত হয় যে আমি এই কোডটি একটি বহুবিধ পরিবেশে রাখতে চাই, আপনি কি আমাকে কিছু পরামর্শ দিতে পারেন? ধন্যবাদ


সুতরাং আপনার জিজ্ঞাসা, sqlলুপ সঙ্গে পরিবর্তন হয় না? যদি সেই ক্যোরিটি লুপের প্রতিটি পুনরাবৃত্তির জন্য পরিবর্তন না হয়, তবে আপনি কেন PreparedStatementপ্রতিটি পুনরাবৃত্তির জন্য একটি নতুন তৈরি করছেন (প্রথম কোড স্নিপেটে)? এটি করার কোনও কারণ আছে কি?
সাবির খান

জিজ্ঞাসা করুন যে যদি ক্যোয়ারী পরিবর্তন হয়, তবে এখনও দ্বিতীয় পদ্ধতির আরও ভাল? কোন অসুবিধা?
স্টাননার

উত্তর:


146

দ্বিতীয় উপায়টি একটি বাচ্চাটি আরও দক্ষ, তবে তাদের ব্যাচগুলিতে চালিত করার একটি আরও ভাল উপায়:

public void executeBatch(List<Entity> entities) throws SQLException { 
    try (
        Connection connection = dataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement(SQL);
    ) {
        for (Entity entity : entities) {
            statement.setObject(1, entity.getSomeProperty());
            // ...

            statement.addBatch();
        }

        statement.executeBatch();
    }
}

তবে আপনি জেডিবিসি ড্রাইভার প্রয়োগের উপর নির্ভরশীল যে আপনি একবারে কতগুলি ব্যাচ চালাতে পারবেন। আপনি উদাহরণস্বরূপ প্রতি 1000 ব্যাচ তাদের চালিয়ে দিতে চাইতে পারেন:

public void executeBatch(List<Entity> entities) throws SQLException { 
    try (
        Connection connection = dataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement(SQL);
    ) {
        int i = 0;

        for (Entity entity : entities) {
            statement.setObject(1, entity.getSomeProperty());
            // ...

            statement.addBatch();
            i++;

            if (i % 1000 == 0 || i == entities.size()) {
                statement.executeBatch(); // Execute every 1000 items.
            }
        }
    }
}

মাল্টিথ্রেডেড এনভায়রনমেন্টমেন্টগুলির হিসাবে, যদি আপনি একই পদ্ধতিতে ব্লকের অভ্যন্তরীণ সংক্ষিপ্ততম স্কোপটিতে সংযোগ এবং বিবৃতিটি জেডিবিসি আইডিয়োম অনুসারে -সংস্থান-সংস্থার বিবরণ ব্যবহার করে দেখিয়েছেন তবে এটি সম্পর্কে চিন্তা করার দরকার নেই in উপরে স্নিপেটস।

যদি এই ব্যাচগুলি লেনদেন হয়, তবে আপনি সংযোগটির স্বতঃসংশোধন বন্ধ করতে এবং সমস্ত ব্যাচ শেষ হয়ে গেলে কেবল লেনদেনের প্রতিশ্রুতিবদ্ধ করতে চান। অন্যথায় এটি কোনও নোংরা ডাটাবেসের ফলস্বরূপ হতে পারে যখন প্রথম ব্যাচের ব্যাচ সফল হয়েছিল এবং পরে না।

public void executeBatch(List<Entity> entities) throws SQLException { 
    try (Connection connection = dataSource.getConnection()) {
        connection.setAutoCommit(false);

        try (PreparedStatement statement = connection.prepareStatement(SQL)) {
            // ...

            try {
                connection.commit();
            } catch (SQLException e) {
                connection.rollback();
                throw e;
            }
        }
    }
}

inside the same method block- আপনার অর্থ হ'ল প্রতিটি থ্রেডের নিজস্ব স্ট্যাক থাকবে এবং এই সংযোগ এবং বিবৃতিগুলি একপাশ থেকে এবং অন্য ডেটা উত্স থেকে স্ট্যাকের মধ্যে রয়েছে এবং এক্সিকিউটিউঙ্কেশনের প্রতিটি নতুন কলকে (== প্রতিটি থ্রেড) সংযোগের পৃথক উদাহরণ দেবে। আমি কি আপনাকে ঠিক বুঝতে পারি? "
পাভেল_কে

আমি প্রথম পদ্ধতিটি করছি তবে এসকিউএল প্রোফাইলারে পর্যবেক্ষণ করার সময় আমি একের চেয়ে বার বার একাধিক প্রস্তুত বিবৃতি দেখতে পাচ্ছি। এটি কেন একাধিক বক্তব্য দেখাচ্ছে তা আমি বুঝতে পারি না। সহায়তা প্রয়োজন।
দুর্বৃত্ত ছেলের

আপনার উত্তরটি ভাল দেওয়া হয়েছে যদি ক্যোয়ারী লুপে পরিবর্তিত না হয় তবে .. যদি ক্যোয়ারী যেমন আমার ক্ষেত্রে যেখানে ক্যোয়ারী পরিবর্তন করা হয়েছে সেভাবে পরিবর্তন হচ্ছে তবে .. আমি এখনও ধরে নিই যে দ্বিতীয় পন্থাটি আরও ভাল। দয়া করে বৈধতা দিন
স্টাননার

13

আপনার কোডের লুপটি কেবল একটি অতি-সরল উদাহরণ, তাই না?

এটি তৈরি করা ভাল PreparedStatementএকবারে এবং লুপটিতে বারবার ব্যবহার করা ভাল।

এমন পরিস্থিতিতে যেখানে এটি সম্ভব নয় (কারণ এটি প্রোগ্রামটির প্রবাহকে আরও জটিল করে তোলে), এটি এখনও ব্যবহার করা উপকারী PreparedStatement , আপনি এটি একবারে ব্যবহার করলেও, কারণ কাজের সার্ভার-সাইড (এসকিউএল বিশ্লেষণ এবং সম্পাদনকে ক্যাশে করছে) পরিকল্পনা), এখনও হ্রাস করা হবে।

আপনি জাভা PreparedStatementসাইডটি পুনরায় ব্যবহার করতে চান এমন পরিস্থিতি মোকাবেলার জন্য কিছু জেডিবিসি ড্রাইভারের (যেমন ওরাকল) ক্যাশিং বৈশিষ্ট্য রয়েছে: আপনি যদি একটি তৈরি করেনPreparedStatement একই সংযোগে একই এসকিউএল জন্য , তবে এটি আপনাকে একই (ক্যাশেড) দেবে ) দৃষ্টান্ত.

মাল্টি-থ্রেডিং সম্পর্কে: আমি মনে করি না যে কোনওভাবেই জেডিবিসি সংযোগগুলি একাধিক থ্রেডে ভাগ করা যায় (অর্থাত্ একাধিক থ্রেড দ্বারা একই সাথে ব্যবহৃত হয়)। প্রতিটি থ্রেডের পুল থেকে তার নিজস্ব সংযোগ পাওয়া উচিত, এটি ব্যবহার করা উচিত এবং এটি আবার পুলটিতে ফেরা উচিত।


4
আসলে সংযোগটির একচেটিয়া থ্রেড রয়েছে এবং এতে প্রতিটি বিবৃতি কার্যকর করা হয়, তবে আমি সেই থ্রেডে প্রস্তুত বিবৃতিগুলির একটি উন্মুক্ত স্ট্যাকের মাধ্যমে অ্যাক্সেস করি। সুতরাং অন্যান্য সমবর্তী থ্রেডগুলি প্রাথমিকভাবে সমস্ত প্রস্তুত বিবৃতি তৈরির জন্য প্রয়োজনীয় প্যারামগুলি পাস করে তবে তারা একযোগে প্যারামগুলি সংশোধন করতে পারে
স্টিল প্লুম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.