সংযোগটি বন্ধ হয়ে যাওয়ার পরেও কি জেডিবিসি ফলাফল ও বিবৃতি আলাদাভাবে বন্ধ করতে হবে?


256

এটি ব্যবহারের পরে জেডিবিসির সমস্ত সংস্থান বন্ধ করা একটি ভাল অভ্যাস হিসাবে বলা হয়। তবে আমার যদি নিম্নলিখিত কোডগুলি থাকে তবে রেজাল্টসেট এবং বিবৃতিটি বন্ধ করা কি প্রয়োজনীয়?

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    try { if (rs != null) rs.close(); } catch (Exception e) {};
    try { if (stmt != null) stmt.close(); } catch (Exception e) {};
    try { if (conn != null) conn.close(); } catch (Exception e) {};
}

প্রশ্নটি হ'ল সংযোগটি বন্ধ হয়ে গেলে কাজটি হয় বা এটি যদি কিছু সংস্থান ব্যবহার করে।


উত্তর:


199

আপনি যা করেছেন তা নিখুঁত এবং খুব ভাল অনুশীলন।

আমি এর ভাল অনুশীলনটি বলার কারণ ... উদাহরণস্বরূপ, যদি কোনও কারণে আপনি "আদিম" ধরণের ডাটাবেস পুলিং ব্যবহার করে থাকেন এবং আপনি কল করেন connection.close()তবে সংযোগটি পুলটিতে ফিরে আসবে এবং ResultSet/ Statementকখনই বন্ধ হবে না এবং তারপরে আপনি বিভিন্ন নতুন সমস্যা চালানো হবে!

সুতরাং আপনি সবসময় connection.close()পরিষ্কার করার উপর নির্ভর করতে পারবেন না ।

আশা করি এটা কাজে লাগবে :)


4
... এবং স্পষ্টভাবে সবকিছু বন্ধ করার সবচেয়ে স্পষ্ট কারণ।
জিমি

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

3
@ রাল্ফ স্টিভেনস - আপনি এটির উপর নির্ভর করতে পারবেন না। আমার এমন পরিস্থিতি হয়েছিল যেখানে এমএসএসকিউএল জেডিবিসি ড্রাইভার মেমরি ফাঁস করেছিল কারণ রেজাল্টসেটটি আবর্জনা সংগ্রহের পরেও বন্ধ ছিল না।
পল

7
@ পল - আকর্ষণীয়। এটি আমার কাছে জেডিবিসি ড্রাইভারের অভাবের মতো মনে হচ্ছে।
পদক্ষেপবিদ

2
@tleb - এটি প্রত্যাশার মতো কাজ করবে। যদিও তত্ত্ব অনুসারে, ব্যতিক্রমগুলি "ব্যয়বহুল" তাই খুব ছোট পারফরম্যান্স নক হবে (যা আপনি ইতিমধ্যে চিহ্নিত করেছেন)
পল

124

জাভা 1.7 আমাদের জীবনকে আরও সহজ করে তোলে রিসোর্স-এ-বিবৃতি দিয়ে চেষ্টা করার জন্য ধন্যবাদ ।

try (Connection connection = dataSource.getConnection();
    Statement statement = connection.createStatement()) {
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do stuff with the result set.
    }
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do more stuff with the second result set.
    }
}

এই বাক্য গঠনটি বেশ সংক্ষিপ্ত এবং মার্জিত। এবং connectionপ্রকৃতপক্ষে বন্ধ হয়ে যাবে এমনকি যখন statementতৈরি করা যায়নি।


56
আপনাকে এর মতো বাসা বাঁধার দরকার নেই, আপনি সমস্ত কিছু একসাথে রিসোর্স দিয়ে করতে পারেন, কেবলমাত্র রিসোর্স ডিক্লেয়ারেশনকে আলাদা স্টেটমেন্ট হিসাবে পৃথক করুন (পৃথক ;)
মার্ক রোটভেল

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

তুমি কেন এমন কিছু করবে না? চেষ্টা করুন (ওপেন কানেকশন) {চেষ্টা করুন (একাধিক বিবৃতি এবং ফলাফলসেট) {বিশেষত যখন পরবর্তী প্রশ্নের ফলাফলগুলি পূর্ববর্তীগুলির সাথে গণনা করতে পারে।
ড্যানিয়েল হাজডুক

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

রাসসিও, আপনি ক্যাচ ব্লকে যা কিছু করতে পারেন তা করতে পারেন
রাউল সালিনাস-মন্টেইগুডো

73

জাভাডোকস থেকে :

যখন কোনও Statementঅবজেক্টটি বন্ধ থাকে, তার বর্তমান ResultSetঅবজেক্টটি যদি উপস্থিত থাকে তবে এটি বন্ধ হয়ে যায়।

তবে জাভাদোকগুলি অন্তর্নিহিত বন্ধ করার সময় Statementএবং ResultSetএটি বন্ধ রয়েছে কিনা সে সম্পর্কে খুব বেশি স্পষ্ট নয় Connection। তারা কেবল জানিয়ে দেয় যে কোনও সংযোগ বন্ধ করে দেওয়া:

এই Connectionঅবজেক্টের ডাটাবেস এবং জেডিবিসি সংস্থানগুলি স্বয়ংক্রিয়ভাবে প্রকাশ হওয়ার অপেক্ষা না করে অবিলম্বে প্রকাশ করে।

আমার মতে, সবসময় স্পষ্টভাবে ঘনিষ্ঠ ResultSets, Statementsএবং Connectionsআপনি তাদের সঙ্গে বাস্তবায়ন যেমন শেষ হয়ে যখন closeডাটাবেসের ড্রাইভার মধ্যে পরিবর্তিত হতে পারে।

আপনি নিজেকে যেমন পদ্ধতি ব্যবহার করে বয়লার-প্লেট কোড অনেক সঞ্চয় করতে পারেন closeQuietlyমধ্যে DBUtils অ্যাপাচি থেকে।


1
কুকুরবাবু ধন্যবাদ। মুল বক্তব্যটি হ'ল আপনি সংযোগ.ক্লোজ বাস্তবায়নের উপর নির্ভর করতে পারবেন না, তাই না?
জিমি

1
আমার মত n00bs জন্য পার্শ্ব নোট - stackoverflow.com/questions/3992199/
ডেভিড ব্লেইন

39

আমি এখন জাভা দিয়ে ওরাকল ব্যবহার করছি। এখানে আমার দৃষ্টিভঙ্গি:

আপনার বন্ধ করা উচিত ResultSetএবং Statementস্পষ্টতই বলা উচিত কারণ সংযোগ বন্ধ করার পরেও কার্সারগুলি খোলা রাখার ক্ষেত্রে ওরাকল এর আগে সমস্যা ছিল। যদি আপনি ResultSet(কার্সার) বন্ধ না করেন তবে এটি সর্বাধিক উন্মুক্ত কার্সারকে ছাড়িয়ে যাওয়ার মতো একটি ত্রুটি ফেলে দেবে ।

আমি মনে করি আপনি ব্যবহার করেন এমন অন্যান্য ডাটাবেসের সাথেও আপনি একই সমস্যার মুখোমুখি হতে পারেন।

এখানে টিউটোরিয়ালটি ক্লোজ রেজাল্টসেট সমাপ্ত হলে :

সমাপ্ত হলে রেজাল্টসেট বন্ধ করুন

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

ResultSet.close();


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

আপনি যদি সংযোগটি বন্ধ করেন তবে এটি সমস্ত ফলাফল সেট উত্তরগুলিও বন্ধ করে দেবে তবে সংযোগের আগে আপনার রেজাল্টটি বন্ধ করা উচিত

এবং কেন আমি সংযোগের আগে ফলাফল সেট বন্ধ করব? আপনি বলতে চাইছেন ওরাকল ড্রাইভার সমস্যার কারণে?
জিমি

1
এখানে আরো সাধারণ শোধন :) হয় stackoverflow.com/questions/103938/...

তত্ত্ব মধ্যে, আপনি যদি বিবৃতি বন্ধ আপনি না আছে resultsets বন্ধ করতে, কিন্তু এটা সম্ভবত ভাল অভ্যাস।
রজারডপ্যাক

8

আপনি যদি আরও কমপ্যাক্ট কোড চান তবে আমি অ্যাপাচি কমন্স DbUtils ব্যবহার করার পরামর্শ দিচ্ছি । এক্ষেত্রে:

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(stmt);
    DbUtils.closeQuietly(conn);
}

3
আমি যদি এই কোডটি আরএসসি ক্লোজ (), স্টেমিটক্লোজ (), কানক্লোজ () এর পরিবর্তে ব্যবহার করি তবে কী হবে
মুসালে

3

জেডিবিসির সাথে সম্পর্কিত সংস্থানগুলি বন্ধ করার জন্য সঠিক এবং নিরাপদ পদ্ধতি (এটি জেডিবিসি রিসোর্সগুলি যথাযথভাবে বন্ধ করার পদ্ধতি থেকে নেওয়া হয়েছে - প্রতিবার )

Connection connection = dataSource.getConnection();
try {
    Statement statement = connection.createStatement();

    try {
        ResultSet resultSet = statement.executeQuery("some query");

        try {
            // Do stuff with the result set.
        } finally {
            resultSet.close();
        }
    } finally {
        statement.close();
    }
} finally {
    connection.close();
}

3

Connectionপোলযোগ্য হয় কি না তা বিবেচ্য নয়। এমনকি পুলে ফেরার আগে পোল্যাবল সংযোগটি পরিষ্কার করতে হবে।

"ক্লিন" এর অর্থ সাধারণত ফলাফল ফলাফলগুলি বন্ধ করা এবং কোনও বিচারাধীন লেনদেনকে ফিরিয়ে নেওয়া কিন্তু সংযোগটি বন্ধ না করা। অন্যথায় পুলিং এর জ্ঞান হারিয়ে ফেলে।


2

না আপনাকে কানেকশনটি ছাড়া কিছুই বন্ধ করতে হবে না। প্রতি জেডিবিসি স্পেস যে কোনও উচ্চতর অবজেক্টটি বন্ধ করলে স্বয়ংক্রিয়ভাবে নিম্ন বস্তু বন্ধ হবে। বন্ধ করা সংযোগ তৈরি করা যে Connectionকোনও বন্ধ করে দেবে Statement। যে কোনওটি বন্ধ করা Statementতার ResultSetদ্বারা নির্মিত সমস্তগুলি বন্ধ করে দেবে StatementConnectionপোলযোগ্য হয় কি না তা বিবেচ্য নয়। এমনকি পুলে ফেরার আগে পোল্যাবল সংযোগটি পরিষ্কার করতে হবে।

অবশ্যই Connectionপ্রচুর বিবৃতি তৈরির ক্ষেত্রে আপনার দীর্ঘ নেস্ট লুপ থাকতে পারে , তবে সেগুলি বন্ধ করা উপযুক্ত। ResultSetযদিও আমি প্রায় কখনও বন্ধ করি না , বন্ধ করার সময় Statementবা Connectionএগুলি বন্ধ করার সময় অতিরিক্ত মনে হয় ।


1

পুনরায় ব্যবহারযোগ্য ওয়ান লাইনার তৈরি করার জন্য আমি নিম্নলিখিত পদ্ধতিটি তৈরি করেছি:

public void oneMethodToCloseThemAll(ResultSet resultSet, Statement statement, Connection connection) {
    if (resultSet != null) {
        try {
            if (!resultSet.isClosed()) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (statement != null) {
        try {
            if (!statement.isClosed()) {
                statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    if (connection != null) {
        try {
            if (!connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

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

finally {
    oneMethodToCloseThemAll(resultSet, preStatement, sqlConnection);
}

-1

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


3
না, এর একমাত্র অর্থ এই যে closeসংস্থান-সংস্থার একটি বিবৃতি শেষ করার আহ্বান জানানো হয়েছে। দেখুন docs.oracle.com/javase/tutorial/essential/exceptions/... এবং docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
জিমি

-1

কিছু সুবিধার ফাংশন:

public static void silentCloseResultSets(Statement st) {
    try {
        while (!(!st.getMoreResults() && (st.getUpdateCount() == -1))) {}
    } catch (SQLException ignore) {}
}
public static void silentCloseResultSets(Statement ...statements) {
    for (Statement st: statements) silentCloseResultSets(st);
}

এখানে কিছুই নেই যা কিছু বন্ধ করে দেয়। কেবলমাত্র একটি অর্থহীন লুপ যা সম্পূর্ণ প্রতিক্রিয়াটিকে অযৌক্তিকভাবে পড়বে, যদিও স্পষ্টভাবে এটি আর চাইছে না।
মারকুইস লার্নের

-1

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

try {
    //...   
    return resp;
} finally {
    if (rs != null && !rs.isClosed()) {
        try {
            rs.close();
        } catch (Exception e2) { 
            log.warn("Cannot close resultset: " + e2.getMessage());
        }
    }
    if (stmt != null && !stmt.isClosed()) {
        try {
            stmt.close();
        } catch (Exception e2) {
            log.warn("Cannot close statement " + e2.getMessage()); 
        }
    }
    if (con != null && !conn.isClosed()) {
        try {
            con.close();
        } catch (Exception e2) {
            log.warn("Cannot close connection: " + e2.getMessage());
        }
    }
}

তত্ত্বগতভাবে এটি 100% নিখুঁত নয় কারণ ঘনিষ্ঠ রাষ্ট্র এবং নিকটেই যাচাইয়ের মধ্যে রাষ্ট্রের পরিবর্তনের জন্য একটি ছোট্ট জায়গা রয়েছে। সবচেয়ে খারাপ ক্ষেত্রে আপনি দীর্ঘক্ষণ একটি সতর্কতা পাবেন। - তবে দীর্ঘমেয়াদী প্রশ্নের ক্ষেত্রে এটি রাষ্ট্র পরিবর্তনের সম্ভাবনার চেয়ে কম। আমরা উত্পাদনে এই নিদর্শনটি "অ্যাভারেজ" লোড (১৫০ জন সিমালানট্যান্স ব্যবহারকারী) দিয়ে ব্যবহার করছি এবং এটি নিয়ে আমাদের কোনও সমস্যা হয়নি - সুতরাং এই সতর্কতা বার্তাটি কখনও দেখবেন না।


আপনার isClosed()পরীক্ষাগুলির দরকার নেই , কারণ ইতিমধ্যে বন্ধ থাকা এগুলির কোনওটি বন্ধ করা কোনও অনিঃপত্তি। যা টাইমিং উইন্ডো সমস্যা দূর করে। যা স্থানীয় Connection, Statementএবং ResultSetভেরিয়েবলগুলি তৈরি করেও নির্মূল করা হবে ।
মারকুইস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.