[数据库连接池二]Java数据库连接池--C3P0和JDNI.

前言:
上一篇文章中讲了DBCP的用法以及实现原理, 这一篇再来说下C3P0和JDNI的用法.

1.1、C3P0数据源

  C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。

  c3p0与dbcp区别

  1. dbcp没有自动回收空闲连接的功能
  2. c3p0有自动回收空闲连接功能

1.2、在应用程序中加入C3P0连接池

  1.导入相关jar包
       c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.2-pre1.jar
  2、在类目录下加入C3P0的配置文件:c3p0-config.xml

    c3p0-config.xml的配置信息如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml必须位于类路径下面
private static ComboPooledDataSource ds;
static{
    try {
        ds = new ComboPooledDataSource("MySQL");
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}
-->

<c3p0-config>
    <!--
    C3P0的缺省(默认)配置,
    如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
    -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
        <property name="user">root</property>
        <property name="password">XDP</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

    <!--
    C3P0的命名配置,
    如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
    -->
    <named-config name="MySQL">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
        <property name="user">root</property>
        <property name="password">XDP</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>

</c3p0-config>

如下图所示:

  

C3P0使用实例: C3P0Utils.java

 1 public class C3P0Utils {
 2     private static DataSource dataSource = new ComboPooledDataSource();
 3
 4     //从池中获取一个连接
 5     public static Connection getConnection() throws SQLException{
 6         return dataSource.getConnection();
 7     }
 8
 9     public static void closeAll(ResultSet rs,Statement stmt,Connection conn){
10         if(rs!=null){
11             try {
12                 rs.close();
13             } catch (SQLException e) {
14                 e.printStackTrace();
15             }
16         }
17
18         if(stmt!=null){
19             try {
20                 stmt.close();
21             } catch (SQLException e) {
22                 e.printStackTrace();
23             }
24         }
25
26         if(conn!=null){
27             try {
28                 conn.close();//关闭
29             } catch (SQLException e) {
30                 e.printStackTrace();
31             }
32         }
33     }
34 }

测试类:UserDaoImpl.java

 1 public class UserDaoImpl {
 2     @Test
 3     public void testInsert(){
 4         Connection conn = null;
 5         PreparedStatement ps = null;
 6         try {
 7             conn = C3P0Utils.getConnection();
 8             ps = conn.prepareStatement("");
 9             //...
10             System.out.println(conn.getClass().getName());
11         } catch (SQLException e) {
12             e.printStackTrace();
13         }finally{
14             C3P0Utils.closeAll(null, ps, conn);
15
16         }
17     }
18 }

可以看出只要将配置文件c3p0-config.xml放在classpath中,或classes目录中, 然后通过private static DataSource dataSource = new ComboPooledDataSource();就可以自动读取到,确实很方便易用.
到了这里我们来看一下这里的源码:

private static DataSource dataSource = new ComboPooledDataSource();

ComboPooledDataSource.java

 1  // not reassigned post-ctor; mutable elements protected by their own locks
 2     // when (very rarely) necessery, we sync this -> wcpds -> dmds
 3
 4     // note that serialization of these guys happens via out superclass
 5     // we just have to make sure they get properly reset on deserialization
 6     transient DriverManagerDataSource         dmds;
 7     transient WrapperConnectionPoolDataSource wcpds;
 8
 9     public ComboPooledDataSource()
10     { this( true ); }
11
12     public ComboPooledDataSource( boolean autoregister )
13     {
14         super( autoregister );
15
16         // System.err.println("...Initializing ComboPooledDataSource.");
17
18         dmds  = new DriverManagerDataSource();
19         wcpds = new WrapperConnectionPoolDataSource();
20
21         wcpds.setNestedDataSource( dmds );
22
23         try
24         { this.setConnectionPoolDataSource( wcpds ); }
25         catch (PropertyVetoException e)
26         {
27             logger.log(MLevel.WARNING, "Hunh??? This can‘t happen. We haven‘t set up any listeners to veto the property change yet!", e);
28             throw new RuntimeException("Hunh??? This can‘t happen. We haven‘t set up any listeners to veto the property change yet! " + e);
29         }
30
31         // set things up in case there are future changes to our ConnectionPoolDataSource
32         //
33         setUpPropertyEvents();
34     }

具体更多细节 还请大家看下源码了, 这里我就不继续往后扩展了. 源码下载地址: http://nchc.dl.sourceforge.net/sourceforge/c3p0/c3p0-0.9.1.2.src.zip


2.1 , JDNI

JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
  这 套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需 通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。

  Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,通过查看Tomcat文档,我们知道使用如下的方式配置tomcat服务器的数据源:

1 <Context>
2   <Resource name="jdbc/datasource" auth="Container"
3             type="javax.sql.DataSource" username="root" password="123456"
4             driverClassName="com.mysql.jdbc.Driver"
5             url="jdbc:mysql://localhost:3306/datest"
6             maxActive="8" maxIdle="4"/>
7 </Context>

  服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序。我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:第一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的。第二种就是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可。

  对于上面的name="jdbc/datasource"数据源资源,在应用程序中可以用如下的代码去获取

1 Context initCtx = new InitialContext();
2 Context envCtx = (Context) initCtx.lookup("java:comp/env");
3 dataSource = (DataSource)envCtx.lookup("jdbc/datasource");

  此种配置下,数据库的驱动jar文件需放置在tomcat的lib下

  

2.2、配置Tomcat数据源

  1、在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件

  如下图所示:

  

  2、在context.xml文件配置tomcat服务器的数据源

 1 <Context>
 2    <Resource
 3        name="jdbc/datasource"
 4        auth="Container"
 5        type="javax.sql.DataSource"
 6        username="root"
 7        password="XDP"
 8        driverClassName="com.mysql.jdbc.Driver"
 9        url="jdbc:mysql://localhost:3306/jdbcstudy"
10        maxActive="8"
11        maxIdle="4"/>
12 </Context>

  3、将数据库的驱动jar文件需放置在tomcat的lib下

  

  4、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中获取JNDI容器中的数据源

 1 public class JdbcUtils_JNDI {
 2
 3     private static DataSource ds = null;
 4     //在静态代码块中创建数据库连接池
 5     static{
 6         try{
 7              //初始化JNDI
 8             Context initCtx = new InitialContext();
 9              //得到JNDI容器
10             Context envCtx = (Context) initCtx.lookup("java:comp/env");
11              //从JNDI容器中检索name为jdbc/datasource的数据源
12             ds = (DataSource)envCtx.lookup("jdbc/datasource");
13         }catch (Exception e) {
14             throw new ExceptionInInitializerError(e);
15         }
16     }
17
18     public static Connection getConnection() throws SQLException{
19         //从数据源中获取数据库连接
20         return ds.getConnection();
21     }
22
23
24     public static void release(Connection conn,Statement st,ResultSet rs){
25         if(rs!=null){
26             try{
27                 //关闭存储查询结果的ResultSet对象
28                 rs.close();
29             }catch (Exception e) {
30                 e.printStackTrace();
31             }
32             rs = null;
33         }
34         if(st!=null){
35             try{
36                 //关闭负责执行SQL命令的Statement对象
37                 st.close();
38             }catch (Exception e) {
39                 e.printStackTrace();
40             }
41         }
42
43         if(conn!=null){
44             try{
45                 //将Connection连接对象还给数据库连接池
46                 conn.close();
47             }catch (Exception e) {
48                 e.printStackTrace();
49             }
50         }
51     }
52 }

写一个Servlet测试JNDI数据源

 1 public class JNDITest extends HttpServlet {
 2
 3     public void doGet(HttpServletRequest request, HttpServletResponse response)
 4             throws ServletException, IOException {
 5         Connection conn = null;
 6         PreparedStatement st = null;
 7         ResultSet rs = null;
 8         try{
 9             //获取数据库连接
10             conn = JdbcUtils_JNDI.getConnection();
11             String sql = "insert into test1(name) values(?)";
12             st = conn.prepareStatement(sql);
13             st.setString(1, "gacl");
14             st.executeUpdate();
15             //获取数据库自动生成的主键
16             rs = st.getGeneratedKeys();
17             if(rs.next()){
18                 System.out.println(rs.getInt(1));
19             }
20         }catch (Exception e) {
21             e.printStackTrace();
22         }finally{
23             //释放资源
24             JdbcUtils_JNDI.release(conn, st, rs);
25         }
26     }
27
28     public void doPost(HttpServletRequest request, HttpServletResponse response)
29             throws ServletException, IOException {
30         doGet(request, response);
31     }
32
33 }
时间: 2024-10-05 00:16:43

[数据库连接池二]Java数据库连接池--C3P0和JDNI.的相关文章

java线程池笔记

java线程池是预先创建线程的一种技术,线程池在还没有线程到来之前创建一个数量的线程,放在空闲的队列中,然后对这些资源进行复用,减少频繁的创建和销毁对象, 1.jdk1.5以上提供了现成的线程池 2.java线程池的顶级接口是Executor,是一个执行线程的工具 3.线程池接口是ExecutorService

java虚拟机学习-触摸java常量池(13)

java虚拟机学习-深入理解JVM(1) java虚拟机学习-慢慢琢磨JVM(2) java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制 java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3) java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4) java虚拟机学习-JVM调优总结(5) java虚拟机学习-JVM调优总结(6) java虚拟机学习-JVM调优总结-基本垃圾回收算法(7) java虚拟机学习-JVM调优总结-垃圾回收面临的

[数据库连接池] Java数据库连接池--DBCP浅析.

前言对于数据库连接池, 想必大家都已经不再陌生, 这里仅仅设计Java中的两个常用数据库连接池: DBCP和C3P0(后续会更新). 一. 为何要使用数据库连接池假设网站一天有很大的访问量,数据库服务器就需要为每次连接创建一次数据库连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.拓机.数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正式针对这个问题提

【Java】java数据库连接池配置的几种方法

今天遇到了关于数据源连接池配置的问题,发现有很多种方式可以配置,现总结如下,希望对大家有所帮助:(已Mysql数据库为例) 一,Tomcat配置数据源: 方式一:在WebRoot下面建文件夹META-INF,里面建一个文件context.xml,内容如下: <Context>      <Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource" 

Java 数据库连接池—转载孤傲苍狼 http://www.cnblogs.com/xdp-gacl/p/4002804.html

一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.拓机.如下图所示: 二.使用数据库连接池优化程序性能 2.1.数据库连接池的基本概念 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性

java数据库连接池实现原理

一.为什么在连接数据库时要使用连接池 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.  一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下. 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并讲这些连接组成一个连接池(简单说:在一个"池"里放了好多半成品的数据库联接对象),由应用程序动态地对池中的连接进行申请.使用和释放.对于多于连接池中连接数的并发请求,应该在请求队列

java数据库连接池性能对比

这个测试的目的是验证当前常用数据库连接池的性能. testcase Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.preparedStatement("select 1"); ResultSet rs = stmt.executeQuery(); while (rs.next()) { } rs.close(); stmt.close(); conn.close(); test c

为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用

HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池. 原文地址:http://blog.csdn.net/clementad/article/details/46928621 官网:https://github.com/brettwooldridge/HikariCP 为何要使用HiKariCP?这要先从BoneCP说起: 什么?不是有C3P0/DBCP这些成熟的数据库连接池吗?一直用的好好的,为什么又搞出一个BoneCP来?因为,传说中BoneCP在快速这个

JAVA 数据库连接池(伪代码,简单易读)

一.引言 近年来,随着 Internet/Intranet 建网技术的飞速发展和在世界范围内的迅速普及,电子商务的冲击波又一次在世界范围内掀起巨浪,各类商务网站吸引着大量用户的青睐,商务网站的访问量也就越来越大.这种批量.并发性的访问使得商务网站对用户的响应速度会明显变慢,甚至有可能使用户无法登陆网站.不堪重荷的商务网站管理公司,除了提高和优化网站服务器的整体性能外,目标也同时转向程序设计方面,数据库的连接性能优化方面已经成为重点.JAVA 语言的跨平台性.可移植性及安全性等特性,使其应用越来越