数据库连接池,几种开源的数据库连接池

数据库连接池:什么是数据库连接池了?

        数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

在Java中开源的数据库连接池有以下几种 :

  • 1、C3P0:是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate [2]  一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
  • 2、Proxool:是一个Java SQL Driver驱动程序,提供了对选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中,完全可配置,快速、成熟、健壮。可以透明地为现存的JDBC驱动程序增加连接池功能。
  • 3、Jakarta DBCP:DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP可以直接的在应用程序中使用。
  • 4、DDConnectionBroker:是一个简单、轻量级的数据库连接池。
  • 5、DBPool:是一个高效、易配置的数据库连接池。它除了支持连接池应有的功能之外,还包括了一个对象池,使用户能够开发一个满足自己需求的数据库连接池。
  • 6、XAPool:是一个XA数据库连接池。它实现了javax.sql.XADataSource并提供了连接池工具。
  • 7、Primrose:是一个Java开发的数据库连接池。当前支持的容器包括Tomcat4&5、Resin3与JBoss3。它同样也有一个独立的版本,可以在应用程序中使用而不必运行在容器中。Primrose通过一个WEB接口来控制SQL处理的追踪、配置,以及动态池管理。在重负荷的情况下可进行连接请求队列处理。
  • 8、SmartPool:是一个连接池组件,它模仿应用服务器对象池的特性。SmartPool能够解决一些临界问题如连接泄漏(connection leaks)、连接阻塞、打开的JDBC对象(如Statements、PreparedStatements)等。SmartPool的特性包括: 支持多个pool,自动关闭相关联的JDBC对象,在所设定time-outs之后察觉连接泄漏,追踪连接使用情况,强制启用最近最少用到的连接,把SmartPool“包装”成现存的一个pool
  • 9、MiniConnectionPoolManager:是一个轻量级JDBC数据库连接池。它只需要Java1.5(或更高)并且没有依赖第三方包。
  • 10、BoneCP:是一个快速、开源的数据库连接池。帮用户管理数据连接,让应用程序能更快速地访问数据库。比C3P0/DBCP连接池速度快25倍。
  • 11、Druid:Druid不仅是一个数据库连接池,还包含一个ProxyDriver、一系列内置的JDBC组件库、一个SQL Parser。
  • 支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等。
  • Druid针对Oracle和MySql做了特别优化,比如:
  1. Oracle的PS Cache内存占用优化

  2. MySql的ping检测优化

  3. Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。
  4. 简单SQL语句用时10微秒以内,复杂SQL用时30微秒。
  5. 通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter,就是通过Druid的SQL Parser分析语义实现的

本篇文章主要来看下C3p0和DBCP:

  1. DBCP:
方式1:
BasicDataSource source = new BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl("jdbc:mysql:///day11");
source.setUsername("root");
source.setPassword("root");


 方式2:
Properties prop = new Properties();
prop.load(new FileReader("dbcp.properties"));
BasicDataSourceFactory factory = new BasicDataSourceFactory();
DataSource source = factory.createDataSource(prop);

配置文件中配置,JDBC.properties:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
  • C3P0数据源:
方式1:
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass("com.mysql.jdbc.Driver");
source.setJdbcUrl("jdbc:mysql:///day11");
source.setUser("root");
source.setPassword("root");

方式2:
ComboPooledDataSource source = new ComboPooledDataSource();


在类加载目录下名称为c3p0-config.xml的配置文件中配置:

<c3p0-config>
 <default-config>
   <property name="driverClass">com.mysql.jdbc.Driver</property>
   <property name="jdbcUrl">jdbc:mysql:///day11</property>
   <property name="user">root</property>
   <property name="password">root</property>
 </default-config>
</c3p0-config>

tomcat内置的数据源(DBCP):
1.如何为tomcat配置数据源

  • tomcat/conf/context.xml文件中配置<Context>配置在这个位置的信息将会被所有的web应用所共享
  • tomcat/conf/[engin]/[Host]/context.xml文件中可以配置<Context>标-签,这里配置的信息将会被这台虚拟主机中的所有web应用所共享
  • ~tomcat/conf/server.xml文件中的<Host>标签中配置<Context>标签,这是web应用的第一种配置方式,在这个标签中配置的信息将只对当前web应用起作用
  • ~tomcat/conf/[engin]/[Host]/自己创建一个.xml文件,在这个文件中使用<Context>标签配置一个web应用,这是web应用第二种配置方式,在这个<Context>标签中配置的信息将只会对当前web应用起作用
  • ~web应用还有第三种配置方式:将web应用直接放置到虚拟主机管理的目录.此时可以在web应用的META-INF文件夹下创建一个context.xml文件,在其中可以写<Context>标签进行配置,这种配置信息将只会对当前web应用起作用

配置的方式:在META-INF下创建一个context.xml
 

<Resource name="mySource"
   auth="Container"
   type="javax.sql.DataSource"
   username="root"
   password="root"
   driverClassName="com.mysql.jdbc.Driver"
   url="jdbc:mysql:///day11"
   maxActive="8"
   maxIdle="4"/>

2.数据源是配置好了,那么如何在程序中获取这个数据源
想要访问jndi就必须在Servlet中才能执行下列代码:在init的方法中执行以下操作:
 

Context initCtx = new InitialContext();
Context jndi = (Context) initCtx.lookup("java:comp/env");
DataSource source = jndi.lookUp("mySource");
//代码如下:
@Override
public void init() throws ServletException {
try{
//通过穿件这个容器
Context initCtx = new InitialContext();
//通过容器中的java:comp/env去找jndi
Context jndi = (Context) initCtx.lookup("java:comp/env");
//jndi去找配置的数据源;
DataSource source = (DataSource) jndi.lookup("mySource");
//通过找到的数据源获取连接
Connection conn = source.getConnection();
//获取连接后开是执行sql语句;
PreparedStatement ps = conn.prepareStatement("select * from account");
ResultSet rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);
}
rs.close();
ps.close();
conn.close();

}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

元数据的操作:
c3p0的基础来操作:
1.先配置c3p0的数据文件

<?xml version="1.0" encoding="utf-8"?>
<c3p0-config>
 <default-config>
   <property name="driverClass">com.mysql.jdbc.Driver</property>
   <property name="jdbcUrl">jdbc:mysql:///blob?generateSimpleParameterMetadata=true</property>
   <property name="user">root</property>
   <property name="password">123</property>
 </default-config>
</c3p0-config>


2.通过Databasematadata获取

public class DataBaseMeataDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
//存储数据源接口池。
ComboPooledDataSource source = new ComboPooledDataSource();
try{
conn = source.getConnection();
//--获取当前数据库的元数据
DatabaseMetaData metaData = conn.getMetaData();
//----获取数据库连接时使用的URL
String url = metaData.getURL();
System.out.println(url);
//----获取数据库的用户名
String username = metaData.getUserName();
System.out.println(username);
//----获取驱动的名称
String driverName = metaData.getDriverName();
System.out.println(driverName);
//----获取数据库中指定表的主键信息
rs = metaData.getPrimaryKeys(null, null, "account");
while(rs.next()){
short cseq = rs.getShort("KEY_SEQ");
String cname = rs.getString("COLUMN_NAME");
System.out.println(cseq+":"+cname);
}
//----获取表
rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
while(rs.next()){
String tabName = rs.getString("TABLE_NAME");
System.out.println(tabName);
}

}catch (Exception e) {
e.printStackTrace();
}finally{
DbUtils.closeQuietly(conn, ps, rs);
}
}
}


3.//获取参数源数据;
//通过c3p0的配置config信息,然后用ComboPooledDataSource source = new ComboPooledDataSource();
//来获取连接
•获得代表PreparedStatement元数据的ParameterMetaData对象。

public class PMMetaDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try{
conn = source.getConnection();
ps = conn.prepareStatement("select * from account where name=? and money=?");
//--获取参数元数据
ParameterMetaData metaData = ps.getParameterMetaData();
//----参数的个数
int count = metaData.getParameterCount();
System.out.println(count);
//----获取参数的类型
String type = metaData.getParameterTypeName(1);
System.out.println(type);
String type2 = metaData.getParameterTypeName(2);
System.out.println(type2);

}catch (Exception e) {
e.printStackTrace();
}finally{
DbUtils.closeQuietly(conn, ps, rs);
}
}
}


4.结果集元数据

ResultSet. getMetaData()
获得代表ResultSet对象元数据的ResultSetMetaData对象
public class RSMetaDataDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = new ComboPooledDataSource();
try{
conn = source.getConnection();
ps = conn.prepareStatement("select * from account");
rs = ps.executeQuery();
//--获取结果集元数据
ResultSetMetaData metaData = rs.getMetaData();
//----获取结果集中的列数
int cc = metaData.getColumnCount();
//System.out.println(cc);
//----获取结果集中指定列的名称
//String cn = metaData.getColumnName(2);
//System.out.println(cn);
//----获取结果集中指定列的类型的名称
//String ct = metaData.getColumnTypeName(3);
//System.out.println(ct);

System.out.println("-------------------------------------------------------");
for(int i = 1;i<=cc;i++){
String cn = metaData.getColumnName(i);
String ct = metaData.getColumnTypeName(i);
System.out.print(cn+":"+ct+"\t\t");
}
System.out.println();
System.out.println("-------------------------------------------------------");
while(rs.next()){
for(int i =1 ;i<=cc;i++){
Object obj = rs.getObject(i);
System.out.print(obj+"\t\t\t");
}
System.out.println();
}

System.out.println("-------------------------------------------------------");

}catch (Exception e) {
e.printStackTrace();
}finally{
DbUtils.closeQuietly(conn, ps, rs);
}
}
}


apache-dbutils框架:
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
API介绍:

  • •org.apache.commons.dbutils.QueryRunner --- 核心
  • •org.apache.commons.dbutils.ResultSetHandler

•工具类DBUtils 

org.apache.commons.dbutils.DbUtils、
需要传递一个数据源然后获取连接;原理也是c3p0在实现的时候要配置c3p0文件:文件如下:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///blob
user=root
password=123
工具类
实现查询:

/**
* DbUtils方式实现查询
* @throws SQLException 
*/
public void find2() throws SQLException{
//需要传一个数据元进去
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Account>list = runner.query("select * from account where money>?"
, new ResultSetHandler<List<Account>>(){
public List<Account> handle(ResultSet rs) throws SQLException {
List<Account> list = new ArrayList<Account>();
while(rs.next()){
Account acc = new Account();
acc.setId(rs.getInt("id"));
acc.setName(rs.getString("name"));
acc.setMoney(rs.getDouble("money"));
list.add(acc);
}
return list;
}
}, 500);
System.out.println(list);
}
增删改
/**
* DBUtils方式实现增删改
* @throws SQLException 
*/


public void add2() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
runner.update("update account set money=? where name=?", 888,"a");
}




QueryRunner -- 两行代码搞定增删改查

(1)QueryRunner() --需要控制事务时,使用这组方法

  • int update(Connection conn, String sql) Execute an SQL INSERT, UPDATE, or DELETE query without replacement parameters.
  • int update(Connection conn, String sql, Object... params)  Execute an SQL INSERT, UPDATE, or DELETE query.
  • int update(Connection conn, String sql, Object param)  Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement parameter.
  • <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh) Execute an SQL SELECT query without any replacement parameters.
  • <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)  Execute an SQL SELECT query with replacement parameters.

(2)QueryRunner(DataSource ds) --不需要控制事务用这组方法

  • int update(String sql) Executes the given INSERT, UPDATE, or DELETE SQL statement without any replacement parameters.
  • int update(String sql, Object... params)  Executes the given INSERT, UPDATE, or DELETE SQL statement.
  • int update(String sql, Object param)  Executes the given INSERT, UPDATE, or DELETE SQL statement with a single replacement parameter.
  • <T> T query(String sql, ResultSetHandler<T> rsh) Executes the given SELECT SQL without any replacement parameters.
  • <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)  Executes the given SELECT SQL query and returns a result object.

3.ResultSetHandler 实现类

  • ArrayHandler:把结果集中的第一行数据转成对象数组。
  • ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
  • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
  • ColumnListHandler:将结果集中某一列的数据存放到List中。
  • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),再把这些map再存到一个map里,其key为指定的列。
  • ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询

ResultSetHandler类的演示:

public class RSHanlderDemo {
//ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询
//QueryRunner类使用可插入策略执行SQL查询以处理ResultSets。 这个类是线程安全的。
public void tes9() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Long count = (Long)runner.query("select count(*) from account",new ScalarHandler());
System.out.println(count);
}
//KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),再把这些map再存到一个map里,其key为指定的列。
public void tes8() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Map<Object, Map<String, Object>> map = runner.query("select * from account where money>?", new KeyedHandler("id"),500);
System.out.println(map);
}
//ColumnListHandler:将结果集中某一列的数据存放到List中。
public void tes7() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Object>list = runner.query("select * from account where money>?", new ColumnListHandler(3),500);
System.out.println(list);
}
//MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
public void tes6() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Map<String, Object>> list = runner.query("select * from account where money>?", new MapListHandler(),500);
System.out.println(list);
}
//MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
public void tes5() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Map<String, Object> map = runner.query("select * from account where money>?", new MapHandler(),500);
System.out.println(map);
}
//BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
public void tes4() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Account>list = runner.query("select * from account where money>?", new BeanListHandler<Account>(Account.class),500);
System.out.println(list);
}
//BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
public void tes3() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Account acc = runner.query("select * from account where money>?", new BeanHandler<Account>(Account.class),500);
System.out.println(acc);
}
//ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
public void tes2() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
List<Object[]> list = runner.query("select * from account where money>?", new ArrayListHandler(),500);
System.out.println(list);
}
//ArrayHandler:把结果集中的第一行数据转成对象数组。然后进行返回
public void test1() throws SQLException{
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
Object[] objs = runner.query("select * from account where money>?", new ArrayHandler(),500);
System.out.println(objs);
}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值