Я использую JDBC Connection Pooling?

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

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

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);
    }

Ответы

Ответ 1

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

}

(при необходимости это можно реорганизовать как абстрактный factory, чтобы улучшить возможность подключения)

и

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

Ответ 2

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

Ответ 3

Похоже на использование 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;

Ответ 4

В качестве последующего решения для решения 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();

    }

}