web-dev-qa-db-fra.com

Suis-je en utilisant le pool de connexions JDBC?

J'essaie de déterminer si j'utilise réellement le pool de connexions JDBC. Après avoir fait quelques recherches, la mise en œuvre semble presque trop facile. Plus simple qu'une connexion régulière en fait, donc je voudrais vérifier.

Voici ma classe de connexion:

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

}

S'agit-il d'un véritable pool de connexions? J'utilise la connexion dans une autre classe comme suit:

        //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);
    }
31
ryandlf

En supposant que c'est le BasicDataSource est de DBCP , alors oui, vous utilisez un pool de connexions. Cependant, vous recréez un autre pool de connexions à chaque acquisition de connexion. Vous ne regroupez pas vraiment les connexions à partir du même pool. Vous devez créer le pool de connexions une seule fois au démarrage de l'application et en obtenir chaque connexion. Vous ne devez pas non plus conserver la connexion en tant que variable d'instance. Vous devez également fermer la connexion, l'instruction et l'ensemble de résultats pour vous assurer que les ressources sont correctement fermées, également en cas d'exceptions. Java 7's try-with-resources statement est utile dans ce cas, il fermera automatiquement les ressources lorsque le bloc try sera terminé.

Voici une réécriture mineure:

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

}

(cela peut si nécessaire être refactorisé comme une usine abstraite pour améliorer la connectivité)

et

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

qui doit être utilisé comme suit:

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

Dans un environnement réel Java EE, vous devez cependant déléguer la création du DataSource au conteneur/serveur d'applications et l'obtenir auprès de JNDI. Dans le cas de Tomcat, voir aussi par exemple ce document: http://Tomcat.Apache.org/Tomcat-6.0-doc/jndi-resources-howto.html

55
BalusC

Il ne semble pas que ce soit mis en commun. Vous devez stocker le DataSource dans DatabaseConnection au lieu d'en créer un nouveau avec chaque appel getConnection (). getConnection () doit renvoyer datasource.getConnection ().

3
andy

Ressemble à une utilisation DBCP. Si oui, alors oui. C'est déjà mis en commun. Et voici la valeur de propriété de pool par défaut du 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;
2
phyerbarte

Dans le prolongement de la solution de BalusC, voici une implémentation que je peux utiliser dans une application qui nécessite plus d'une connexion, ou dans une bibliothèque commune qui ne connaîtrait pas les propriétés de connexion à l'avance ...

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

    }

}
1
Todd W. Powers