2011-09-29 3 views
22

Я пытаюсь определить, действительно ли я использую объединение JDBC-соединений. После некоторых исследований реализация кажется слишком простой. На самом деле проще, чем обычное соединение, поэтому я бы хотел проверить.Я использую JDBC Connection Pooling?

Вот мой класс подключения:

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

Предполагая, что это BasicDataSource от DBCP, то да, вы используете пул соединений. Однако вы воссоздаете еще один пул соединений при каждом приобретении соединения. Вы не объединяете соединения из одного пула. Вам необходимо создать пул соединений только один раз при запуске приложения и получить от него каждое соединение. Вы также не должны удерживать соединение в качестве переменной экземпляра. Вы также должны закрыть соединение, инструкцию и набор результатов, чтобы обеспечить надлежащее закрытие ресурсов, а также в случае исключений. Java 7's 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); 
} 

В реальной Java EE environement вы должны делегировать создание DataSource серверу контейнера/приложения и получать его от JNDI. В случае Tomcat см. Также, например, этот документ: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html

+0

Ничего себе, спасибо за переписывание. Идеальная помощь для кого-то нового, подобного мне. – ryandlf

+0

будет ли это решение быть потокобезопасным? Мне нужно вызвать connection.close(); – swapyonubuntu

+0

@swapyonubuntu: закрыть автоматически с помощью новой инструкции Java7 'try-with-resources' https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – BalusC

3

Не похоже, что он объединен. Вы должны хранить DataSource в DatabaseConnection вместо создания нового с каждым вызовом getConnection(). getConnection() должен возвращать datasource.getConnection().

2

Похоже, что использование DBCP. Если да, то да. Он уже объединен. И вот значение свойства пула по умолчанию для DBCP.

/** 
* 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. –