申明:本文对于连接资源关闭采用自定义的 JDBCUtils 工具:

package com.test.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public final class JDBCUtils {
private static String driver="com.mysql.jdbc.Driver";
private static String url="jdbc:mysql://localhost:3306/store28";
private static String user="root";
private static String password="root1234"; private JDBCUtils(){} static {
/**
* 驱动注册
*/
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
} } /**
* 获取 Connetion
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url, user, password);
} /**
* 释放资源
* @param conn
* @param st
* @param rs
*/
public static void colseResource(Connection conn,Statement st,ResultSet rs) {
closeResultSet(rs);
closeStatement(st);
closeConnection(conn);
} /**
* 释放连接 Connection
* @param conn
*/
public static void closeConnection(Connection conn) {
if(conn !=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//等待垃圾回收
conn = null;
} /**
* 释放语句执行者 Statement
* @param st
*/
public static void closeStatement(Statement st) {
if(st !=null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//等待垃圾回收
st = null;
} /**
* 释放结果集 ResultSet
* @param rs
*/
public static void closeResultSet(ResultSet rs) {
if(rs !=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//等待垃圾回收
rs = null;
}
}

一、连接池技术基本原理

  在程序初始化的时候创建一个 Connection 集合,便于快速增删,可以使用 LinkedList 集合来存储,

  当调用工具者获取一个 Connection 时,就从集合里移除一个 Connection 返回给调用者(期间,如果没有则创建一个连接池)

  当使用完 Connection 之后,使用 close() (Connection的 close() 方法) 将 Connection 资源归还(添加回)List 集合中,但是其中有一个问题,原始的 Connection 中的 close() 方法将资源关闭,因此需要想办法解决这个问题,可以使用如下技术:

  装饰者设计模式、适配器设计模式、基于接口的动态代理、基于子类的动态代理。 

二、使用 DBCP 技术实现连接池

  使用 properties 配置文件进行数据库连接配置(使用 eclipse 将 dbcp.properties 文件编写在 src 目录下):

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/store28
username=root
password=root1234

说明:以下是全配置信息

#连接基本设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/sys
username=root
password=root1234

#<!--扩展配置 了解-->
#初始化连接
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(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

编写 DBCPUtils 工具类:

package com.test.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class DBCPUtils {
private static DataSource dataSource; static {
try {
InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
Properties props = new Properties();
props.load(is);
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new ExceptionInInitializerError("数据源初始化失败!");
}
} public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("数据连接获取失败!");
}
} public static DataSource getDataSource() {
return dataSource;
}
}

测试:

package com.test.jdbcTest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.junit.Test; import com.test.utils.DBCPUtils;
import com.test.utils.JDBCUtils; public class DBCPDmeo {
@Test
public void test1() throws SQLException {
Connection conn = DBCPUtils.getConnection(); String sql = "select cid,cname from category";
PreparedStatement st = conn.prepareStatement(sql); ResultSet rs = st.executeQuery(); while(rs.next()) {
System.out.println(rs.getString("cid")+"..."+rs.getString("cname"));
}
JDBCUtils.colseResource(conn, st, rs);
} }

三、使用 C3P0 技术实现连接池

首先配置 c3p0-config.xml 文件(详见 c3p0 官网)

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="automaticTestTable">con_test</property>

<!-- 连接数据库配置信息 -->

<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/store28</property>
<property name="user">root</property>
<property name="password">root1234</property>

<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>

<user-overrides user="test-user">
<property name="maxPoolSize">10</property>
<property name="minPoolSize">1</property>
<property name="maxStatements">0</property>
</user-overrides>

</default-config>

<!-- This app is massive! -->
<named-config name="intergalactoApp">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>

<!-- intergalactoApp adopts a different approach to configuring statement
caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>

<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>
</c3p0-config>

C3P0Utils 工具:

package com.test.utils;

import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Utils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource(); public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("数据连接获取失败!");
}
} public static DataSource getDataSource() {
return dataSource;
}
}

测试:

package com.test.jdbcTest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.junit.Test; import com.test.utils.C3P0Utils;
import com.test.utils.JDBCUtils; public class C3p0Test {
@Test
public void test() throws SQLException {
Connection conn = C3P0Utils.getConnection(); String sql = "select cid,cname from category";
PreparedStatement st = conn.prepareStatement(sql); ResultSet rs = st.executeQuery(); while(rs.next()) {
System.out.println(rs.getString("cid")+"..."+rs.getString("cname"));
}
JDBCUtils.colseResource(conn, st, rs);
}
}

JDBC 连接池的两种方式——dbcp & c3p0的更多相关文章

  1. 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

    1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...

  2. 配置Java连接池的两种方式:tomcat方式以及spring方式

    1. tomcat方式:在context.xml配置连接池,然后在web.xml中写配置代码(也能够在server.xml文件里配置连接池).这两种方法的差别是:在tomcat6版本号及以上中cont ...

  3. ADB连接手机的两种方式(usb数据线连接和wifi连接)

    ADB(Android Debug Bridge)安卓测试桥,它是连接电脑开发端和安卓设备的桥梁,这个安卓设备可以是真实的安卓手机或者平板,也可以是虚拟的安卓模拟器,   这里介绍ADB连接手机的两种 ...

  4. 利用adb查看手机设备ip和连接手机的两种方式

    电脑安装adb(查看菜鸟adb教程) [cmd]->输入adb devices (设置了path,否则需要 ./路径/adb devices)如图: 查看ip两种方法(可能有更多,目前我还没看到 ...

  5. Go基础系列:Go实现工作池的两种方式

    worker pool简介 worker pool其实就是线程池thread pool.对于go来说,直接使用的是goroutine而非线程,不过这里仍然以线程来解释线程池. 在线程池模型中,有2个队 ...

  6. adb连接手机的两种方式

    adb连接手机进行调试有两种方式,一种使用USB线,一种使用无线WiFi. 第一种  使用USB线连接 1. 在手机上启用USB调试 2. CMD窗口输入adb devices,此时可以看到自己的设备 ...

  7. Android 应用开发 之通过AsyncTask与ThreadPool(线程池)两种方式异步加载大量数据的分析与对比--转载

     在加载大量数据的时候,经常会用到异步加载,所谓异步加载,就是把耗时的工作放到子线程里执行,当数据加载完毕的时候再到主线程进行UI刷新.在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一 ...

  8. Java连接Neo4j的两种方式

    1.Neo4j数据库的两种方式 Neo4j可以以两种方式运行: Java应用程序中的嵌入式数据库 通过REST的独立服务器 不管哪一种方式,这个选择不会影响查询和使用数据库的方式. 它是由应用程序的性 ...

  9. Spring框架中获取连接池的几种方式

    什么是数据库连接池? 数据库连接池是一种关键的有限的昂贵的资源,对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池就是用来解决这些问题而提出的. 数据库连接 ...

随机推荐

  1. 展开被 SpringBoot 玩的日子 《 四 》 Session 会话共享

    共享Session-spring-session-data-redis 分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一. Spring Session官方说 ...

  2. (转)Jquery获取上级、下级或者同级的元素

    下面介绍JQUERY的父,子,兄弟节点查找方法 jQuery.parent(expr) 找父亲节点,可以传入expr进行过滤,比如$("span").parent()或者$(&qu ...

  3. CTSC2018 被屠记

    占坑 day-1 Gery 和 lll 在火车上谈笑风生 day0 上午 Gery:"我要吊打全场" 下午 Gery 忘带杯子了. Gery:"我过两天碰杯了就可以喝到水 ...

  4. [CF1138B]Circus

    Description: 给你2个长度为n的01串 从中选出\(n/2\)个,使得选出的数中第一排1的个数等于未选出数中第二排1的个数 输出一种方案即可,没有输出-1 Hint: \(n \le 50 ...

  5. Ubuntu全盘备份与恢复,亲自总结,实测可靠

    https://blog.csdn.net/sinat_27554409/article/details/78227496 Ubuntu全盘备份与恢复,亲自总结,实测可靠 初学者在使用Ubuntu这类 ...

  6. 在IDEA中spring程序可以正常运行,但IDE报错Could not autowire.

    这个问题只会在使用xml文件配置bean时遇到,使用自动配置和java配置没有这种错误. 遇到这个问题首先要确定配置文件已经正确的放在了resources文件夹内,resources文件夹就是clas ...

  7. redis的过期策略都有哪些?

    1.面试题 redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现? 2.面试官心里分析 1)老师啊,我往redis里写的数据怎么没了? 之前有同学问过我,说我们生产环境的redi ...

  8. thinkphp5使用空模块

    今天想做一个功能,可以后台设置url是二级域名(也是指向同一个服务器)还是一级域名(域名/模块),网上找了找,TP3.2开始取消了空模块.所以只能自己修改框架源码了. ----------有点晚,明天 ...

  9. MySQL5.6启用sha256_password插件

    一.背景: 使用MySQL5.6过程中,发现默认的加密插件为mysql_native_password.而sha256_password的安全程度要比mysql_native_password高,尝试 ...

  10. Java GC相关知识

    Java堆的分类 分为两类:YoungGen和OldGen.其中,YoungGen分为三部分:eden,from survivor和to survivor,比例默认是:8:1:1 PermGen不属于 ...