Использую ли я пул соединений JDBC?
Я пытаюсь определить, действительно ли я использую пул соединений 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);
}
4 ответа
Предполагая, что это 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();
}
}
(это может быть при необходимости реорганизовано как абстрактная фабрика для улучшения подключаемости)
а также
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 вы должны делегировать создание DataSource
к контейнеру / серверу приложений и получите его из JNDI. В случае Tomcat см. Также, например, этот документ: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html
Не похоже, что это объединено. Вам следует хранить DataSource в DatabaseConnection, а не создавать новый при каждом вызове getConnection(). getConnection() должен возвращать datasource.getConnection().
Похоже на использование 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;
В качестве продолжения решения 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();
}
}