文章目录
数据库连接池
为什么要用数据库连接池?
用户每次请求都需要向数据库获取连接,而数据库创建连接需要耗费较大的资源。
所以可以设置一个连接池,在程序启动时就初始化一批连接,在程序中共享,需要连接时从连接池获取,用完之后再还给连接池,这样就大大减少了连接的创建和销毁次数,提高程序的效率。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
特点
- 资源重用:
使得数据库连接得以重用,避免频繁创建、释放连接引起的大量性能开销。- 提高系统反应速度:
在初始化工程中,就已经创建了若干数据库连接放在连接池中,业务请求进来直接利用现有的可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。- 新的资源分配手段:
对于多应用共享同一数据库的系统而言,可以在应用层通过数据库连接池配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。- 统一管理、避免数据库连接泄露:
在较为晚上的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
常用的数据库连接池
Druid(德鲁伊)
阿里提供的。
开源。
集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池。还加入了日志监控,可以监控DB池连接和SQL执行情况。
速度不确定是否有BoneCP快。
属性配置参数:
配置 | 说明及默认值 |
---|---|
name | 如果存在多个数据源,监控的时候可以通过名字来区分开。 如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.identityHashCode(this) |
url | 连接数据库的url。mysql : jdbc:mysql://IP:3306/druid2 oracle : jdbc:oracle:thin:@IP:ocnauto |
username | 连接数据库的用户名 |
password | 连接数据库的密码。 |
driverClassName | 根据url自动识别。不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下) |
initialSize | 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时;默认值0 |
maxActive | 最大连接池数量;默认8 |
maxIdle | 已经不再使用,配置了也没效果 |
minIdle | 最小连接池数量 |
maxWait | 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 |
poolPreparedStatements | 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭;默认false |
maxOpenPreparedStatements | 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100;默认-1 |
validationQuery | 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。 |
testOnBorrow | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。;默认true |
testOnReturn | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能;默认false |
testWhileIdle | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
timeBetweenEvictionRunsMillis | 有两个含义: 1)Destroy线程会检测连接的间隔时间2)testWhileIdle的判断依据,详细看testWhileIdle属性的说明 |
numTestsPerEvictionRun | 不再使用,一个DruidDataSource只支持一个EvictionRun |
connectionInitSqls | 物理连接初始化的时候执行的sql |
exceptionSorter | 根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接 |
filters | 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall |
proxyFilters | 类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系 |
实例:
package com.atguigu.druid;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class TestDruid {
public static void main(String[] args) throws Exception {
Properties pro = new Properties(); pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
src下的配置文件为:【druid.properties】
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=20
maxWait=1000
filters=wall
C3P0 (速度较慢,稳定性还可以)
开源。
需要将c3p0的jar包:c3p0-0.9.1.2.jar 拷贝到lib目录下。
在src下创建一个C3p0的配置文件(C3p0提供了默认的配置文件:c3p0.properties 或者 c3p0-config.xml)
创建连接池:ComboPooledDataSource pool = new ComboPooledDataSource();
c3p0.properties 的配置内容:
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///mydb1
c3p0.user=root
c3p0.password=root
c3p0-config.xml的配置内容:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 获取连接的4个基本信息 -->
<property name="user">root</property>
<property name="password">abc123</property>
<property name="jdbcUrl">jdbc:mysql:///test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 涉及到数据库连接池的管理的相关属性的设置 -->
<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">10</property>
<!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
<property name="maxStatements">20</property>
<!-- 每个连接同时可以使用的 Statement 对象的个数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
工具类:
package cn.tedu.utils;
import java.sql.*;
public class JDBCUtils {
//获取MySQL数据库连接
public static Connection getConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:mysql:///mydb1","root","root");
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//获取Oracle数据库连接
public static Connection getConnection(){
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl","root","root");
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//释放资源
public static void close(Connection conn,Statement stat,ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
rs = null;
}
}
if(stat != null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
stat = null;
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
conn = null;
}
}
}
}
使用:
package cn.tedu.c3p0;
import cn.tedu.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class C3p0Demo1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
//创建连接池
ComboPooledDataSource pool = new ComboPooledDataSource("helloc3p0");
//从连接池获取连接
conn = pool.getConnection();
ps = conn.prepareStatement("delete from exam where id=?");
ps.setInt(1,2);
ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.close(conn,ps,rs);
}
}
}
DBCP(速度比C3P0快,存在bug)
apache家提供的。
开源。
tomcat自带DBCP数据库连接池。
系统中实现该连接池可以加入下面两个jar包:
- Commons-dbcp.jar:连接池的实现
- Commons-pool.jar:连接池实现的依赖库
属性配置参照表:
属性 | 说明及默认值 |
---|---|
initialSize | 连接池启动时创建的初始化连接数量;默认0 |
maxActive | 连接池中可同时连接的最大连接数;默认8 |
maxIdle | 连接池中最大空闲的连接数,超过的空闲连接被释放,若设置负数表示不限制;默认8 |
minIdle | 连接池中最小空闲连接数,低于这个数量会被创建新的连接。该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都需要消耗资源。不能太大;默认0 |
maxWait | 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置 -1 表示无限等待;默认无限制。 |
poolPreparedStatements | 开启池的Statement是否prepared;默认false |
maxOpenPreparedStatements | 开启池的prepared后的同时最大连接数;默认无限制 |
minEvictableIdleTimeMillis | 连接池中连接在时间段内一直空闲,被逐出连接池的时间; |
removeAbandonedTimeout | 超过时间限制,回收没有用的(废弃)连接;默认300 |
removeAbandoned | 超过removeAbandonedTimeout时间后,是否进行没用连接(废弃)的回收;默认false |
方式一:
public static Connection getConnection3() throws Exception {
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl("jdbc:mysql:///test");
source.setUsername("root");
source.setPassword("abc123");
//
source.setInitialSize(10);
Connection conn = source.getConnection();
return conn;
}
方式二:
//使用dbcp数据库连接池的配置文件方式,获取数据库的连接:推荐
private static DataSource source = null;
static{
try {
Properties pros = new Properties();
InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");
pros.load(is);
//根据提供的BasicDataSourceFactory创建对应的DataSource对象
source = BasicDataSourceFactory.createDataSource(pros);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection4() throws Exception {
Connection conn = source.getConnection();
return conn;
}
src下的配置文件为:【dbcp.properties】
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=abc123
initialSize=10
#...
Proxool (可监控连接池转台,性能较c3p0差点)
是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
BoneCP
是一个开源组织提供的数据库连接池,速度快
参考:
参考:
https://www.cnblogs.com/superxuezhazha/p/12433124.html
https://blog.csdn.net/m0_46556472/article/details/107943651