我正在尝试确定我是否实际使用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);
}
答案 0 :(得分:53)
假设BasicDataSource
来自DBCP,那么是的,您正在使用连接池。但是,您要在每个连接获取上重新创建另一个连接池。您实际上并不是从同一个池中汇集连接。您只需在应用程序启动时创建一次连接池,并从中获取每个连接。您也不应该将连接保存为实例变量。您还应关闭连接,语句和结果集,以确保在异常情况下正确关闭资源。 Java 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();
}
}
(如果有必要,可以将其重构为抽象工厂以提高可插拔性)
和
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
答案 1 :(得分:3)
看起来好像没有合并。您应该将DataSource存储在DatabaseConnection中,而不是在每次getConnection()调用时创建一个新的。 getConnection()应该返回datasource.getConnection()。
答案 2 :(得分: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;
答案 3 :(得分: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();
}
}