文章目录
数据库连接池
所谓的数据库连接池技术,就是用来分配,管理,释放数据库连接的。我们以前用 JDBC 操作数据库的时候,每次操作完都会将连接关闭。数据库连接是极其宝贵的资源,频繁的创建和销毁会极大地降低服务器的性能。因此,我们可以利用池化技术,重复利用数据库资源,避免没必要的开销
MyConnectionPool
package com.cskaoyan.ds;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class MyConnectionPool {
private int INIT_SIZE;
private int MAX_SIZE;
private int size; //当前有多少个连接
//queue用来存放空闲的连接
private Queue<Connection> queue = new ArrayBlockingQueue<>(MAX_SIZE);
private Properties info = new Properties();
public MyConnectionPool() {
try (Reader reader = new FileReader("pool.properties")) {
info.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
INIT_SIZE = Integer.parseInt(info.getProperty("INIT_SIZE"));
MAX_SIZE = Integer.parseInt(info.getProperty("MAX_SIZE"));
for (int i = 0; i < INIT_SIZE; i++) {
Connection conn = createConnection();
queue.offer(conn);
}
}
private Connection createConnection() {
String url = info.getProperty("url");
String user = info.getProperty("user");
String password = info.getProperty("password");
Connection conn = null;
try {
Connection connection = DriverManager.getConnection(url, user, password);
conn = new WorkConnection(connection);
size++;
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public Connection getConnection() {
if (!queue.isEmpty()) return queue.poll();
if (size < MAX_SIZE) return createConnection();
throw new RuntimeException("数据库连接数目已达到最大");
}
private class WorkConnection extends ConnectionWrapper {
//ConnectionWrapper其实就是继承connection后将close方法改成了抽象方法,为了接下来重写close方法
public WorkConnection(Connection conn) {
super(conn);
}
@Override
public void close() throws SQLException {
if (queue.size() < INIT_SIZE) {
queue.offer(this);
} else {
size--;
conn.close();
}
}
}
}
数据库连接池的优点
- 数据库连接得以重用,避免了频繁创建和销毁引起的大量性能开销,同时也增加了系统的稳定性。
- 数据库连接池在初始化过程中,往往就已经创建了若干个连接。因此可以提高系统的反应速度。、
- 如果有多个应用共用一个 DBMS,由于 DBMS 的连接是有限的,因此我们可以通过数据库连接池限制一个应用最大的连接数目,避免某一应用独占所有的连接。
- 在较为完善的数据库连接池中,可以设置占用超时,强制回收被占用的连接,从而避免了常规数据库连接操作中可能出现的资源泄露问题。
DbUtils
1.简介
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对 JDBC 的简单封装,学习成本极低,使用 dbutils 可以简化 jdbc 编码的工作量,同时也不会影响程序的性能。
使用 DBUtils 需要导入 commons-dbutils-1.7.jar。DBUtils 有三个核心的组件:
- QueryRunner:该类提供了 DML 和 DQL 的 API。
- ResultSetHandler:该接口定义如何封装结果集。
- DbUtils:一个简单的工具类,简化了关闭资源和事务处理,可以简化JDBC操作的模板代码
2.QueryRunner
2.1 构造方法
QueryRunner(); // 需要指定连接
QueryRunner(DataSource ds); //从数据源中获取连接
2.2 常用API
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object...params);
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh);
<T> T query(String sql, ResultSetHandler<T> rsh, Object... params);
<T> T query(String sql, ResultSetHandler<T> rsh);
int update(Connection conn, String sql, Object... params);
int update(Connection conn, String sql);
int update(String sql, Object... params);
int update(String sql);
int[] batch(Connection conn, String sql, Object[][] params)
int[] batch(String sql, Object[][] params)
2 ResultSetHandler
该接口用于处理 ResultSet,将查询返回的 ResultSet 按要求转换为另一种形式。该接口的定义如下
public interface ResultSetHandler<T> {
T handle(ResultSet rs) throws SQLException;
}
2.1 实现类
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
- BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
- MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
使用 BeanHandler 和 BeanListHandler 需要注意以下几点:
- 对应的 JavaBean 必须提供无参构造方法。
- JavaBean 的属性名应该和返回结果的字段名相同。
- JavaBean 中必须提供公共的 Setter 方法。
3 DbUtils
提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的
API
void close(Connection conn); //可以避免空指针异常
void close(ResultSet rs);
void close(Statement stmt);
void closeQuietly(Connection conn); //不需要判空, 处理异常
void closeQuietly(ResultSet rs);
void closeQuietly(Statement stmt);
void closeQuietly(Connection conn, Statement stmt, ResultSet rs);
void commitAndClose(Connection conn); // 提交事务并且关闭连接
void commitAndCloseQuietly(Connection conn);
boolean loadDriver(String driverClassName)