2011-09-29 12 views
22

मैं यह निर्धारित करने की कोशिश कर रहा हूं कि मैं वास्तव में जेडीबीसी कनेक्शन पूलिंग का उपयोग कर रहा हूं या नहीं। कुछ शोध करने के बाद, कार्यान्वयन लगभग बहुत आसान लगता है। वास्तव में नियमित कनेक्शन से आसान है इसलिए मैं सत्यापित करना चाहता हूं।क्या मैं जेडीबीसी कनेक्शन पूलिंग का उपयोग कर रहा हूं?

यहाँ मेरी कनेक्शन वर्ग है:

public class DatabaseConnection { 

Connection conn = null; 

public Connection getConnection() { 

    BasicDataSource bds = new BasicDataSource(); 
    bds.setDriverClassName("com.mysql.jdbc.Driver"); 
    bds.setUrl("jdbc:mysql://localhost:3306/data"); 
    bds.setUsername("USERNAME"); 
    bds.setPassword("PASSWORD"); 

    try{ 
     System.out.println("Attempting Database Connection"); 
     conn = bds.getConnection(); 
     System.out.println("Connected Successfully"); 
    }catch(SQLException e){ 
     System.out.println("Caught SQL Exception: " + e); 
    } 
    return conn; 
} 

public void closeConnection() throws SQLException { 
    conn.close(); 
} 

}

यह सच कनेक्शन पूलिंग है? मैं इतनी के रूप में एक और कक्षा में कनेक्शन का उपयोग कर रहा हूँ:

 //Check data against database. 
    DatabaseConnection dbConn = new DatabaseConnection(); 
    Connection conn; 
    ResultSet rs; 
    PreparedStatement prepStmt; 

    //Query database and check username/pass against table. 
    try{ 
     conn = dbConn.getConnection(); 
     String sql = "SELECT * FROM users WHERE username=? AND password=?"; 
     prepStmt = conn.prepareStatement(sql); 
     prepStmt.setString(1, user.getUsername()); 
     prepStmt.setString(2, user.getPassword()); 
     rs = prepStmt.executeQuery(); 

     if(rs.next()){ //Found Match. 
      do{ 
       out.println("UserName = " + rs.getObject("username") + " Password = " + rs.getObject("password")); 
       out.println("<br>"); 
      } while(rs.next()); 
     } else { 
      out.println("Sorry, you are not in my database."); //No Match. 
     } 

     dbConn.closeConnection(); //Close db connection. 

    }catch(SQLException e){ 
     System.out.println("Caught SQL Exception: " + e); 
    } 

उत्तर

45

मान लिया जाये कि यह BasicDataSourceDBCP, तो से हां, तो आप एक कनेक्शन पूल का उपयोग कर रहे है कि। हालांकि, आप प्रत्येक कनेक्शन अधिग्रहण पर एक और कनेक्शन पूल पुनर्निर्माण कर रहे हैं। आप वास्तव में एक ही पूल से कनेक्शन पूल नहीं कर रहे हैं। आपको एप्लिकेशन के स्टार्टअप पर केवल एक बार कनेक्शन पूल बनाना होगा और इससे प्रत्येक कनेक्शन प्राप्त करना होगा। आपको कनेक्शन आवृत्ति के रूप में कनेक्शन भी नहीं रखना चाहिए। अपवादों के मामले में संसाधनों को ठीक से बंद कर दिया गया है, यह सुनिश्चित करने के लिए आपको कनेक्शन, कथन और परिणाम भी बंद करना चाहिए। जावा 7 का try-with-resources statement इसमें सहायक है, try ब्लॉक समाप्त हो जाने पर यह संसाधनों को स्वतः बंद कर देगा।

public final class Database { 

    private static final BasicDataSource dataSource = new BasicDataSource(); 

    static { 
     dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
     dataSource.setUrl("jdbc:mysql://localhost:3306/data"); 
     dataSource.setUsername("USERNAME"); 
     dataSource.setPassword("PASSWORD"); 
    } 

    private Database() { 
     // 
    } 

    public static Connection getConnection() throws SQLException { 
     return dataSource.getConnection(); 
    } 

} 

(यह यदि आवश्यक हो तो pluggability सुधार करने के लिए एक सार कारखाने के रूप में पुनर्संशोधित जा सकता है) प्रयोग की जाने वाली

और

private static final String SQL_EXIST = "SELECT * FROM users WHERE username=? AND password=?"; 

public boolean exist(User user) throws SQLException { 
    boolean exist = false; 

    try (
     Connection connection = Database.getConnection(); 
     PreparedStatement statement = connection.prepareStatement(SQL_EXIST); 
    ) { 
     statement.setString(1, user.getUsername()); 
     statement.setString(2, user.getPassword()); 

     try (ResultSet resultSet = preparedStatement.executeQuery()) { 
      exist = resultSet.next(); 
     } 
    }  

    return exist; 
} 

है जो:

यहाँ एक छोटी सी पुनर्लेखन है निम्नानुसार है:

try { 
    if (!userDAO.exist(username, password)) { 
     request.setAttribute("message", "Unknown login. Try again."); 
     request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); 
    } else { 
     request.getSession().setAttribute("user", username); 
     response.sendRedirect("userhome"); 
    } 
} catch (SQLException e) { 
    throw new ServletException("DB error", e); 
} 

वास्तविक जावा ईई वातावरण में आपको कंटेनर/एप्लिकेशन सर्वर पर DataSource के निर्माण का प्रतिनिधि होना चाहिए और इसे जेएनडीआई से प्राप्त करना चाहिए। टॉमकैट के मामले में, उदाहरण के लिए यह दस्तावेज़ भी देखें: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html

+0

वाह, फिर भी लिखने के लिए धन्यवाद। मेरे जैसे नए व्यक्ति के लिए बिल्कुल सही मदद। – ryandlf

+0

क्या यह समाधान थ्रेडसेफ होगा? क्या मुझे कनेक्शन.क्लोज़() को कॉल करने की आवश्यकता है; – swapyonubuntu

+0

@swapyonubuntu: स्वचालित रूप से नए जावा 7 'प्रयास-संसाधनों' कथन के साथ बंद किया जाता है https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – BalusC

3

ऐसा लगता है कि यह पूल नहीं है। आपको प्रत्येक getConnection() कॉल के साथ एक नया निर्माण करने के बजाय डेटाबेस कनेक्शन में डेटासोर्स स्टोर करना चाहिए। getConnection() को datasource.getConnection() वापस करना चाहिए।

2

एक डीबीसीपी उपयोग की तरह दिखता है। यदि हां, तो हाँ। यह पहले से ही पूल किया गया है। और यहां डीबीसीपी का डिफ़ॉल्ट पूल संपत्ति मूल्य है।

/** 
* The default cap on the number of "sleeping" instances in the pool. 
* @see #getMaxIdle 
* @see #setMaxIdle 
*/ 
public static final int DEFAULT_MAX_IDLE = 8; 
/** 
* The default minimum number of "sleeping" instances in the pool 
* before before the evictor thread (if active) spawns new objects. 
* @see #getMinIdle 
* @see #setMinIdle 
*/ 
public static final int DEFAULT_MIN_IDLE = 0; 
/** 
* The default cap on the total number of active instances from the pool. 
* @see #getMaxActive 
*/ 
public static final int DEFAULT_MAX_ACTIVE = 8; 
1

के रूप में एक BalusC के समाधान के लिए ऊपर का पालन करें, नीचे एक कार्यान्वयन है कि मैं एक आवेदन है कि एक से अधिक कनेक्शन की आवश्यकता है, या एक आम पुस्तकालय में पहले से कनेक्शन गुण पता नहीं होता है कि भीतर इस्तेमाल किया जा सकता है ..

import org.apache.commons.dbcp.BasicDataSource; 

import java.sql.Connection; 
import java.sql.SQLException; 
import java.util.concurrent.ConcurrentHashMap; 

public final class Database { 

    private static final ConcurrentHashMap<String, BasicDataSource> dataSources = new ConcurrentHashMap(); 

    private Database() { 
     // 
    } 

    public static Connection getConnection(String connectionString, String username, String password) throws SQLException { 

     BasicDataSource dataSource; 

     if (dataSources.containsKey(connectionString)) { 
      dataSource = dataSources.get(connectionString); 
     } else { 
      dataSource = new BasicDataSource(); 
      dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
      dataSource.setUrl(connectionString); 
      dataSource.setUsername(username); 
      dataSource.setPassword(password); 
      dataSources.put(connectionString, dataSource); 
     } 

     return dataSource.getConnection(); 

    } 

} 
+0

यह समाधान हमेशा काम नहीं करता है। यह ConcurrentHashMap का उपयोग करने के बावजूद दौड़ की स्थिति के अधीन है। –

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