JDBC笔记 08:数据库连接池

it2024-06-25  50

1. 为什么需要数据库连接池

需要的时候就加载一个连接这种方式,会消耗大量的资源和时间,数据库的资源并没有得到很好的重复利用。对于每一次数据库连接,使用完后都得断开。如果出现异常而未能关闭,会导致数据库系统中的内存泄露,最终将导致重启数据库。不能控制被创建的连接对象数,系统资源分配没有限制,如果连接过多,也可能导致内存泄漏,服务器崩溃。

2. 数据库连接池技术


2.1 基本思想

为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。

2.2 功能

数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

2.3 优点:

资源重用 由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。更快的系统反应速度 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均 已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销, 从而减少了系统的响应时间新的资源分配手段 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库 连接数的限制,避免某一应用独占所有的数据库资源统一的连接管理,避免数据库连接泄漏 在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据 库连接操作中可能出现的资源泄露

3. 多种开源的数据库连接池

JDBC的数据库连接池使用 javax.sql.DataSource 来表示,DataSource只是一个接口,该接口通常由服务器提供实现,也有一些开源组织提供实现:

DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因 自身存在BUG,Hibernate3已不再提供支持C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一 点BoneCP 是一个开源组织提供的数据库连接池,速度快Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是 速度不确定是否有BoneCP快DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分DataSource用来取代 DriverManager 来获取 Connection,获取速度快,同时可以大幅度提高数据库访问速度注意: 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个 数据源即可。当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数 据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。

3.1 C3P0数据库连接池

使用数据库连接池获取连接

public class JDBCUtils { //参数值是配置文件中named-config标签的name属性值 private static ComboPooledDataSource dataSource = new ComboPooledDataSource("helloc3p0"); //获取数据库的连接 public static Connection getConnection() throws Exception { Connection connection = dataSource.getConnection(); return connection; } }

c3p0-config 配置文件(需要放在类路径下)

<?xml version="1.0" encoding="UTF-8" ?> <c3p0-config> <named-config name="helloc3p0"> <!--提供获取连接的四个基本信息--> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="user">root</property> <property name="password">root</property> <!--进行数据库连接池管理的基本信息--> <!--当数据库连接池中连接数不够时,一次性向数据库服务器申请的连接数--> <property name="acquireIncrement">5</property> <!-- 数据库连接池初始化时的连接数 --> <property name="initialPoolSize">10</property> <!-- 数据库连接池初维护的最少连接数 --> <property name="minPoolSize">10</property> <!-- 数据库连接池初维护的最多连接数 --> <property name="maxPoolSize">100</property> <!-- 数据库连接池初维护的最多statement数 --> <property name="maxStatements">50</property> <!-- 数据库连接池初维护的每个连接可以使用的最多statement数 --> <property name="maxStatementsPerConnection">2</property> </named-config> </c3p0-config>

配置文件的属性名时约定好的,不允许修改,可以按照set方法的提示书写

3.2 DBCP数据库连接池

使用数据库连接池获取连接

public class JDBCUtils { private static DataSource dataSource; static { try { //获取配置文件 ClassLoader loader = ClassLoader.getSystemClassLoader(); InputStream in = loader.getResourceAsStream("dbcp.properties"); Properties properties = new Properties(); properties.load(in); //获取数据库连接池 dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //获取数据库的连接 public static Connection getConnection() throws Exception { Connection connection = dataSource.getConnection(); return connection; } }

3.3 Druid数据库连接池

使用数据库连接池获取连接

public class JDBCUtils { private static DataSource dataSource; static { try { //获取配置文件 ClassLoader loader = ClassLoader.getSystemClassLoader(); InputStream in = loader.getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(in); //获取数据库连接池 dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //获取数据库的连接 public static Connection getConnection() throws Exception { Connection connection = dataSource.getConnection(); return connection; } }

常用参数

配置默认值说明name配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过 名字来区分开来。如果没有配置,将会生成一个名字,格式 是:”DataSource-” + System.identityHashCode(this)url连接数据库的urlusername连接数据库的用户名password连接数据库的密码。如果不希望密码直接写在配置文件中,可以使用 ConfigFilter。driverClassName根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动 识别dbType,然后选择相应的driverClassName(建议配置下)initialSize0初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者 第一次getConnection时maxActive8最大连接池数量maxWait获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启 用公平锁,并发效率会有所下降,如果需要可以通过配置 useUnfairLock属性为true使用非公平锁。poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游 标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。maxOpenPreparedStatements-1要启用PSCache,必须配置大于0,当大于0时, poolPreparedStatements自动触发修改为true。在Druid中,不会存 在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一 些,比如说100validationQuery用来检测连接是否有效的sql,要求是一个查询语句。如果 validationQuery为null,testOnBorrow、testOnReturn、 testWhileIdle都不会其作用。testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,做了这个配置会 降低性能。testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会 降低性能testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。申请连接的时候检 测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行 validationQuery检测连接是否有效。timeBetweenEvictionRunsMillis有两个含义: 1)Destroy线程会检测连接的间隔时间2)testWhileIdle的 判断依据,详细看testWhileIdle属性的说明numTestsPerEvictionRun不再使用,一个DruidDataSource只支持一个EvictionRunminEvictableIdleTimeMillisconnectionInitSqls物理连接初始化的时候执行的sqlexceptionSorter根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接filters属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wallproxyFilters类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非 替换关系
最新回复(0)