【JDBC-6】数据库连接池
类似于线程池,准备一些预先的资源,到使用的时候直接拿出。
之前我们在对数据库进行连接操作时,每次连接都需要连接
connection = JDBCUtils.getConnection();
操作完毕后还需要释放
JDBCUtils.release(connection,preparedStatement,resultSet);
这些操作是非常消耗系统资源的,因此就推出了数据库连接池的概念。类似于线程池,在事先定义好连接次数后,不用每次操作都要进行数据库的连接和释放
热门的开源数据源实现(拿来即用)
- DBCP
- C3P0
- Druid:阿里巴巴
用了这些数据库连接池后,在项目开发后就不需要编写连接数据库的代码
eg:
- 最小连接数:10
- 最大连接数:15 超过了最大连接数就需要等待
- 超时等待:100ms
编写连接池,要实现DateSource接口
数据库连接池使用步骤:
1.下载并导入dbcp、pool的jar包到lib文件夹下并设置为Library(IDEA版本高的话会自动解压)
2.写配置文件(固定写法)
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/studentcourse?useUnicode=true&
characterEncoding=utf8&useSSL=true&serverTimeZone=UTC
username=root
password=family52
#!-- 初始化连接 --
initialSize=10
#最大连接数量
maxActive=50
#!-- 最大空闲连接 --
maxIdle=20
#!-- 最小空闲连接 --
minIdle=5
#!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:user 与 password 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
参数解释:
driverClassName=com.mysql.cj.jdbc.Driver // 不多解释,这是基本的驱动加载
url=jdbc:mysql://localhost:3306/studentcourse?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimeZone=UTC // 驱动注册
username=root //要连接的数据库用户名
password=family520 // 要连接的数据库密码
defaultAutoCommit=true:// 设置是否自动提交,默认为true
defaultReadOnly=false: // 是否为只读 默认为false
defaultTransactionIsolation=3:// 设置数据库的事务隔离级别默认为1,READ_UNCOMMITTED,推荐设置为3
initialSize=10: // 初始化数据池拥有的连接数量
maxActive=20: /池中最多可容纳的活着的连接数量,当达到这个数量不在创建连接
maxIdle=20: // 最大空闲等待,也就是连接等待队列超过这个值会自动回收未使用的连接,直到达到20
minIdle=5: // 最小空闲等待 ,数据池中最少保持的连接
maxWait=10000 // 最大等待时间,超过这个时间等待队列中的连接就会失效
testOnBorrow=true //从池中取出连接时完成校验 ,验证不通过销毁这个connection,默认为true,
testOnReturn=false //放入池中时完成校验,默认我fasle
validationQuery=select 1 // 校验语句,必须是查询语句,至少查询一列,设置了它onBorrow才会生效
validationQueryTimeout=1 // 校验查询时长,如果超过,认为校验失败
testWhileIdle=false // 清除一个连接时是否需要校验
timeBetweenEvictionRunsMillis=1 // DBCP默认有个回收器Eviction,这个为设置他的回收时间周期
numTestsPerEvictionRun=3 // Eviction在运行时一次处理几个连接
poolPreparedStatements=true //是否缓存PreparedStatements
maxOpenPreparedStatements=1 // 缓存PreparedStatements的最大个数
3.编写工具类
private static DataSource dataSource = null;
static{
try{
// 通过类获取反射对象,然后获取反射对象的类加载器,调用类加载器调取资源
InputStream resourceAsStream = JdbcUtilsDbcp.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
// 创建数据源 工厂模式
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
// 2.从数据源中获取连接
return dataSource.getConnection();
}
// 释放资源
public static void release(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
if (resultSet != null){
resultSet.close();
}
if (statement != null){
statement.close();
}
if (connection != null){
connection.close();
}
}
4.实现代码
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JdbcUtilsDbcp.getConnection();
String sql = "update account set age = age + 2";
preparedStatement = connection.prepareStatement(sql);
int num = preparedStatement.executeUpdate();
if (num > 0){
System.out.println("插入成功!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
JdbcUtilsDbcp.release(connection,preparedStatement,null);
} catch (SQLException e) {
e.printStackTrace();
}
}
实际上数据库连接池改变的是就是个utils的工具类