疯狂Java学习笔记(50)-----------JDBC

时间:2023-02-26 15:42:50

疯狂Java学习笔记(50)-----------JDBC

1、加载合适的JDBC驱动程序

Class.forName(Driver);

   MySQL驱动程序:com.mysql.jdbc.Driver

   Oracle驱动程序:oracle.jdbc.driver.OracleDriver

   SQLServer驱动程序:

   com.Microsoft.jdbc.sqlserver.SQLServerDriver

2、建立数据库连接

与MySQL数据库连接的方法:

Connection con=DriverManager.getConnection(“jdbc:mysql://主机IP或主机名:3306/数据库名”,用户名,密码);

java.sql.DriveManager  用来处理装载驱动程序并且为创建新的数据库连接提供支持;

–java.sql.Connection  用于完成对特定定数据库的连接;

–java.sql.Statement  用于对特定的数据库执行SQL语句;java.sql.Statement又包含了以下两个重要的子类型:

       java.sql.PreparedStatement  用于执行预编译的SQL语句;

       java.sql.CallableStatement  用于执行数据库中存储的过程的调用;

--java.sql.ResultSet  用于保存查询所得的结果集

3、创建Statement对象

Statement  st=con.createStatement();  //最后可以不关闭,但推荐关闭

利用Statement对象可以执行静态SQL语句,静态SQL语句可以是Select语句、Delete语句、Update语句和Insert语句。

执行SQL语句

Statement接口提供了三种执行SQL语句的方法:executeQuery()、executeUpdate() 和execute()。具体使用哪一个方法由SQL语句本身来决定。

方法 executeQuery 用于产生单个结果集的语句,例如 SELECT 语句等。

方法 executeUpdate 用于执行INSERT、UPDATE或DELETE 语句以及SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个 整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE 或DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

方法 execute 用于执行返回多个结果集、多个更新计数或二者组合的语句。一般不会需要该高级功能。

      ①JDBC在编译时并不对将要执行的SQL查询语句作任何检查,只是将其作为一个String类对象,直到驱动程序执行SQL查询语句时才知道其是否正确。对于错误的SQL查询语句,在执行时将会产生 SQLException。

      ②一个Statement对象在同一时间只能打开一个结果集,对第二个结果集的打开隐含着对第一个结果集的关闭。

      ③如果想对多个结果集同时操作,必须创建出多个Statement对象,在每个Statement对象上执行SQL查询语句以获得相应的结果集。

      ④如果不需要同时处理多个结果集,则可以在一个Statement对象上顺序执行多个SQL查询语句,对获得的结果集进行顺序操作。

str="insertinto customer values('wangyang',24,'beijing','wangyang@sina.com')";

int  recordNumber=st.executeUpdate(str);执行executeUpdate()方法返回该SQL语句涉及的记录数。

str="select* from mycustomer";   //查询表中记录

ResultSet rs=st.executeQuery(str); 由于SQL语句是select,用executeQuery()方法,返回一个结果集保存在ResultSet对象rs中。

4、分析ResultSet对象

① 执行完毕SQL语句后,将返回一个ResultSet类的对象,它包含所有的查询结果。但对ResultSet类的对象方式依赖于光标(Cursor)的 类型,而对每一行中的各个列,可以按任何顺序进行处理(当然,如果按从左到右的顺序对各列进行处理可以获得较高的执行效率);

ResultSet类中的Course方式主要有:

ResultSet.TYPE_FORWARD_ONLY(为缺省设置):光标只能前进不能后退,也就是只能从第一个一直移动到最后一个。

ResultSet.TYPE_SCROLL_SENSITIVE:允许光标前进或后退并感应到其它ResultSet的光标的移动情形。

ResultSet.TYPE_SCROLL_INSENSITIVE:允许光标前进或后退并不能感应到其它ResultSet的光标的移动情形。

ResultSet类中的数据是否允许修改主要有:

ResultSet.CONCUR_READ_ONLY(为缺省设置):表示数据只能只读,不能更改。

ResultSet.CONCUR_UPDATABLE:表示数据允许被修改。

可以在创建Statement或PreparedStatement对象时指定ResultSet的这两个特性。

Statement stmt=con.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);

PreparedStatement pstmt=con.PrepareStatement("insert into bookTable values (?,?,?)",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);

② ResultSet类的对象维持一个指向当前行的指针,利用ResultSet类的next()方法可以移动到下一行(在JDBC中,Java程序一次只 能看到一行数据),如果next()的返回值为false,则说明已到记录集的尾部。另外JDBC也没有类似ODBC 的书签功能的方法。

③ 利用ResultSet类的getXXX()方法可以获得某一列的结果,其中XXX代表JDBC中的Java数据类型,如 getInt()、getString()、getDate()等。访问时需要指定要检索的列(可以采用 int值作为列号(从1开始计数)或指定列(字段)名方式,但字段名不区别字母的大小写)。

示例:

while(rs.next()){

int id=rs.getInt("id");

String name=rs.getString("cName");

int age=rs.getInt("cAge");

String address=rs.getString("cAddress");

String email=rs.getString("cEmail");

System.out.println(id+" "+name+" "+age+" "+address+" "+email);

}

获得结果集中的结构信息:利用ResultSet类的getMetaData()方法来获得结果集中的一些结构信息(主要提供用来描述列的数量、列的名称、列的数据类型。利用ResulSetMetaData类中的方法)。

ResultsetMetaData  rsmd=rs.getMetaData();

rsmd.getColumnCount();   //返回结果集中的列数

rsmd.getColumnLabel(1); //返回第一列的列名(字段名)

例如:

Statement stmt=con.createStatement();

ResultSet rs=stmt.executeQuery("select * from TableName");

for(int i=1; i<=rs.getMetaData().getColumnCount(); i++) //跟踪显示各个列的名称

{ System.out.print(rs. getColumnName (i)+"\t");

}

while(rs.next())

{ //跟踪显示各个列的值

for(int j=1; j<=rs.getMetaData().getColumnCount(); j++)

{ System.out.print(rs.getObject(j)+"\t");

}

}

5、关闭连接

(注意关闭的顺序) 例:

rs.close();

st.close();

con.close()

6、JDBC的常用API

一、Connection接口:

       1.createStatement():创建数据库连接

       2.prepareStatement(Stringsql):创建预处理语句

       3.prepareCall(Stringsql):创建可调用语句

       4.getAutoCommit():获取自动提交的模式

       5.setAutoCommit():设置自动提交的模式

       6.commit():提交所执行的SQL语句

       7.rollback():回滚所执行的SQL语句

       8.getMetaData():获取一个DatabaseMetaData对象,该对象包含了有关数据库的基本信息

       9.close():关闭数据库连接

      10.isClose():判断数据库连接是否超时或被显示关闭

二、Statement接口:

       1.execute(Stringsql):执行SQL语句,如果返回值是结果集则为true,否则为false

       2.executeQuery(Stringsql):执行SQL语句,返回值为ResultSet

       3.executeUpdate(Stringsql):执行SQL语句,返回值为所影响的行数

       4.addBatch(Stringsql):向当前Statement对象的命令列表中添加新的批处理SQL语句

       5.clearBatch():清空当前Statement对象的命令列表

       6.executeBatch():执行当前Statement对象的批处理语句,返回值为每个语句所影响的函数数组

       7.getConnection():返回创建了该Statement对象的Connection对象

       8.getQueryTimeout():获取等待处理结果的时间

       9.setQueryTimeout():设置等待处理结果的时间

三、ResultSet接口:

       1.first()/beforeFirst():将游标移动到ResultSet中第一条记录(的前面)

       2.last()/afterLast():将游标移动到ResultSet中最后一条记录(的后面)

       3.absolute(intcolumn):将游标移动到相对于第一行的指定行,负数则为相对于最后一条记录

       4.relative(introws):将游标移动到相对于当前行的第几行,正为向下,负为向上

       5.next():将游标下移一行

       6.previous():将游标上移一行

       7.insertRow():向当前ResultSet和数据库中被插入行处插入一条记录

       8.deleteRow():将当前ResultSet中的当前行和数据库中对应的记录删除

       9.updateRow():用当前ResultSet中已更新的记录更新数据库中对应的记录

       10.cancelUpdate():取消当前对ResultSet和数据库中所做的操作

       11.findColumn(StringcolumnName):返回当前ResultSet中与指定列名对应的索引

       12.getRow():返回ResultSet中的当前行号

       13.refreshRow():更新当前ResultSet中的所有记录

       14.getMetaData():返回描述ResultSet的ResultSetMetaData对象

       15.isAfterLast():是否到了结尾

       16.isBeforeFirst(): 是否到了开头

       17.isFirst():是否第一条记录

       18.isLast(): 是否最后一条记录

       19.wasNull():检查列值是否为NULL值,如果列的类型为基本类型,且数据库中的值为0,那么

这项检查就很重要。由于数据库NULL也返回0,所以0值和数据库的NULL不能区分。如果列的类型为对象,可以简单地将返回值与null比较

        20.close():关闭当前ResultSet

四、ResultSetMetaData接口:

       1.getColumnCount():返回ResultSet中列的数目

       2.getColumnName():返回列在数据库中的名称

       3.getColumnType():返回列的SQL类型

       4.isReadOnly():表示该数据项是否为只读值

       5.isNullable():表示该列是否可以存储NULL

实例:

//DBHelper.java

<span style="font-size:18px;">package com.haixu.jdbc;  
  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.sql.PreparedStatement;  
import java.sql.SQLException;  
  
public class DBHelper {  
    public static final String url = "jdbc:mysql://127.0.0.1/test";  
    public static final String name = "com.mysql.jdbc.Driver";  
    public static final String user = "root";  
    public static final String password = "root";  
  
    public Connection conn = null;  
    public PreparedStatement pst = null;  
  
    public DBHelper(String sql) {  
        try {  
            Class.forName(name);//指定连接类型  
            conn = DriverManager.getConnection(url, user, password);//获取连接  
            pst = conn.prepareStatement(sql);//准备执行语句  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    public void close() {  
        try {  
            this.conn.close();  
            this.pst.close();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
}  
</span>  
<span style="font-size:18px;">package com.haixu.jdbc;  
  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
public class Demo {  
  
    static String sql = null;  
    static DBHelper db1 = null;  
    static ResultSet ret = null;  
  
    public static void main(String[] args) {  
        sql = "select *from teacher";//SQL语句  
        db1 = new DBHelper(sql);//创建DBHelper对象  
  
        try {  
            ret = db1.pst.executeQuery();//执行语句,得到结果集  
            while (ret.next()) {  
                String uid = ret.getString(1);  
                String ufname = ret.getString(2);  
                String ulname = ret.getString(3);  
                String udate = ret.getString(4);  
                System.out.println(uid + "\t" + ufname + "\t" + ulname + "\t" + udate );  
            }//显示数据  
            ret.close();  
            db1.close();//关闭连接  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
  
}  
</span>  

在使用JDBC编程时需要连接数据库,导入JAR包是必须的,导入其它的jar包方法同样如此,导入的方法是 

打开eclipse

1.右击要导入jar包的项目,点properties 
2.左边选择java build path,右边选择libraries 
3.选择add External jars 
4.选择jar包的按照路径下的
确定后就行了。

Java连接MySQL的最新驱动包下载地址 

http://www.mysql.com/downloads/connector/j

有两种方法导入jar包,第一种是先把jar包放在项目的目录下,通过添加jar包,是使用相对地址的,这样把项目复制到其它电脑也可以用

第二种方法是导入外部的jar包,是绝对地址,如果项目要复制到其它电脑又要重新导入

第一种方法 ,建议使用

疯狂Java学习笔记(50)-----------JDBC

 第二种方法

疯狂Java学习笔记(50)-----------JDBC

添加之后就会出现以下

疯狂Java学习笔记(50)-----------JDBC

 

 

7.数据库连接池(connection pool)的工作原理

  1)、基本概念及原理
由上面的分析可以看出,问题的根源就在于对
数据库 连接资源的低效管理。我们知道, 
  对于共享资源,有一个很著名的 设计 模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
 
  2)、服务器自带的连接池
  JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。
  连接池关键问题分析
  (1)、并发问题
  为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为 Java 语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:
public synchronized Connection getConnection()
  (2)、多数据库服务器和多用户
  对于大型的企业级应用,常常需要同时连接不同的数据库(如连接 Oracle Sybase )。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址(<poolName.url>)﹑用户名(<poolName.user>)﹑密码(<poolName.password>)等信息。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。
  对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。
  3)、事务处理
  我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。
Java 语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。 
  4)、连接池的分配与释放
  连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。
  对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。
  5)、连接池的配置与维护
  连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。
  
 
 
如何确保连接池中的最小连接数呢?
 
有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。
连接池的实现 
  1、连接池模型
  本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConnetionPoolManager)和一个配置文件操作类(ParseDSConfig)。连接池类是对某一 数据库 所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。(5)当多数据库时,且数据库是动态增加的话,将会加到配置文件中。
  连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属性文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于 安全 性问题,需要不同的用户使用不同的名称和密码。
         2、连接池实现(经过本人改版,可以适用多数据库类型的应用以及一种数据库类型多个数据库且数据  库的数量可以动态增加的应用程序)
         1),DBConnectionPool.java   数据库连接池类
         2),DBConnectionManager .java   数据库管理类
         3),DSConfigBean .java                单个数据库连接信息Bean
         4),ParseDSConfig.java                操作多(这个'多'包括不同的数据库和同一种数据库有多个数据库)
                                                            数据 配置文件xml
         5),ds.config.xml                           数据库配置文件xml

 


DBCP代码实现:

 


//创建数据源


public static DataSource setupDataSource(String connectURI) {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName(org.gjt.mm.mysql.Driver);
    ds.setUsername("username");
    ds.setPassword("password");
    ds.setUrl(connectURI);
    return ds;    
}

//关闭数据源
public static void shutdownDataSource(DataSource ds) throws SQLException {
    BasicDataSource bds = (BasicDataSource)ds;
    bds.close();
}

//数据源的使用

DataSource dataSource = getDataSource();
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  
  try {
   conn = dataSource.getConnection();
   pstmt = conn.prepareStatement("select * from users");
   rs = pstmt.executeQuery();
   while(rs.next()) {
    System.out.println(rs.getInt("id"));
   }
  } catch(Exception e) {
   e.printStackTrace();
  } finally {
   try {
    rs.close();
    pstmt.close();
    conn.close();
   } catch(Exception ex) {
    ex.printStackTrace();
   }
  } 




在Tomcat中配置数据库连接池:

我们使用Tomcat中lib文件夹下的tomcat-dbcp.jar。
1. 修改server.xml文件在<Service>中写入以下代码:
< Context path="/WebProject" docBase="WebProject" reloadable="true" crossContext="true">
     
     <Resource auth="Container" name="jdbc/CompanyDB" type="javax.sql.DataSource" 
      factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"  
     driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"      
     url="jdbc:sqlserver://localhost:1433;DataBaseName=Company"  
     username="sa"  
      password="root"  
      maxActive="100"  
      maxIdle="30"  
      maxWait="10000"   
     removeAbandoned=“true”
      removeAbandonedTimeOut="10"  
      logAbandoned="true"/> 
    </Context>


path:工程路径。
docBase:工程名字。
name:JNDI的名字。
type:数据源的类。
factory:指定生成的DataReource的factory类名;默认DBCP工厂类。
driverClassName:数据库驱动名。
url:数据库连接的URL。
username:数据库用户名。
password:数据库密码。
maxActive:最大连接数据库数,设为0表示没有限制。
maxIdle:最大等待数量,设为0表示没有限制。
maxWait:最大等待秒数,单位为ms。
removeAbandoned:是否自我中断,默认为false。
removeAbandonedTimeOut:几秒后会自我中断,removeAbandoned必须为true。
logAbandoned:是否记录中断事件,默认为false。



2. 修改web.xml文件,增加一个标签,输入以下代码:
<resource-ref>
     <description>Company Connection</description>
     <res-ref-name>jdbc/CompanyDB</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
< /resource-ref>

res-ref-name:指定JNDI的名字。
res-type:指定资源类名。
res-auth:指定资源的Manager。

3. 代码中使用JNDI代码进行获取:
Context ctx = new InitalContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CompanyDB");
Connection conn = ds.getConnection();


注意:java:comp/env/ 是java中JNDI固定写法。 


注意:如果该配置出现错误,采用另一种方式进行配置

在tomcat中的server.xml不进行配置,而在context.xml中进行设置
代码如下:
<Resource name="jdbc/CompanyDB" type="javax.sql.DataSource" password="root" 
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" maxIdle="2" maxWait="5000" username="sa" url="jdbc:sqlserver://localhost:1433;DataBaseName=Company" maxActive="100"/>


web.xml的设置同上一个配置一样。


 数据库连接池 : C3P0、DBCP

1、数据库连接池技术的优点:

•资源重用:
     由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
•更快的系统反应速度:
     数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
•新的资源分配手段:
     对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。
•统一的连接管理,避免数据库连接泄露:
     在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
 
1)两种开源的数据库连接池:
•  JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,
    该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现:
    – DBCP 数据库连接池
    – C3P0 数据库连接池
•  DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池
A:DBCP 数据源 :
•  DBCP 是 Apache 软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统:Common-pool. 如需使用该连接池实现,应在系统中增加如下两个 jar 文件:
Commons-dbcp.jar:连接池的实现。
Commons-pool.jar:连接池实现的依赖库。
•   Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
DBCP 数据源使用范例:
•  数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
•  当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但上面的代码并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。


/** 
     * 1. 加载 dbcp 的 properties 配置文件: 配置文件中的键需要来自 BasicDataSource 
     * 的属性. 
     * 2. 调用 BasicDataSourceFactory 的 createDataSource 方法创建 DataSource 
     * 实例 
     * 3. 从 DataSource 实例中获取数据库连接.  
     */  
    @Test  
    public void testDBCPWithDataSourceFactory() throws Exception{  
          
        Properties properties = new Properties();  
        InputStream inStream = JDBCTest.class.getClassLoader()  
                .getResourceAsStream("dbcp.properties");  
        properties.load(inStream);  
          
        DataSource dataSource =   
                BasicDataSourceFactory.createDataSource(properties);  
          
        System.out.println(dataSource.getConnection());   
          
//        BasicDataSource basicDataSource =   
//                (BasicDataSource) dataSource;  
//          
//        System.out.println(basicDataSource.getMaxWait());   
    }  
      
    /** 
     * 使用 DBCP 数据库连接池 
     * 1. 加入 jar 包(2 个jar 包). 依赖于 Commons Pool 
     * 2. 创建数据库连接池 
     * 3. 为数据源实例指定必须的属性 
     * 4. 从数据源中获取数据库连接 
     * @throws SQLException  
     */  
    @Test  
    public void testDBCP() throws SQLException{  
        final BasicDataSource dataSource = new BasicDataSource();  
          
        //2. 为数据源实例指定必须的属性  
        dataSource.setUsername("root");  
        dataSource.setPassword("1230");  
        dataSource.setUrl("jdbc:mysql:///atguigu");  
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");  
          
        //3. 指定数据源的一些可选的属性.  
        //1). 指定数据库连接池中初始化连接数的个数  
        dataSource.setInitialSize(5);  
          
        //2). 指定最大的连接数: 同一时刻可以同时向数据库申请的连接数  
        dataSource.setMaxActive(5);  
          
        //3). 指定小连接数: 在数据库连接池中保存的最少的空闲连接的数量   
        dataSource.setMinIdle(2);  
          
        //4).等待数据库连接池分配连接的最长时间. 单位为毫秒. 超出该时间将抛出异常.   
        dataSource.setMaxWait(1000 * 5);  
          
        //4. 从数据源中获取数据库连接  
        Connection connection = dataSource.getConnection();  
        System.out.println(connection.getClass());   
          
        connection = dataSource.getConnection();  
        System.out.println(connection.getClass());   
          
        connection = dataSource.getConnection();  
        System.out.println(connection.getClass());   
          
        connection = dataSource.getConnection();  
        System.out.println(connection.getClass());   
          
        Connection connection2 = dataSource.getConnection();  
        System.out.println(">" + connection2.getClass());   
          
        new Thread(){  
            public void run() {  
                Connection conn;  
                try {  
                    conn = dataSource.getConnection();  
                    System.out.println(conn.getClass());   
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
            };  
        }.start();  
          
        try {  
            Thread.sleep(5500);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
          
        connection2.close();  
    }  
username=root  
password=root  
driverClassName=com.mysql.jdbc.Driver  
url=jdbc:mysql:3306/test  
initialSize=10  
maxActive=50  
minIdle=5  
maxWait=5000  
  
dbcp.properties  
C3P0例子
/** 
     * 1. 创建 c3p0-config.xml 文件,  
     * 参考帮助文档中 Appendix B: Configuation Files 的内容 
     * 2. 创建 ComboPooledDataSource 实例; 
     * DataSource dataSource =  
     *            new ComboPooledDataSource("helloc3p0");   
     * 3. 从 DataSource 实例中获取数据库连接.  
     */  
    @Test  
    public void testC3poWithConfigFile() throws Exception{  
        DataSource dataSource =   
                new ComboPooledDataSource("helloc3p0");    
          
        System.out.println(dataSource.getConnection());   
          
        ComboPooledDataSource comboPooledDataSource =   
                (ComboPooledDataSource) dataSource;  
        System.out.println(comboPooledDataSource.getMaxStatements());   
    }  
      
    @Test  
    public void testC3P0() throws Exception{  
        ComboPooledDataSource cpds = new ComboPooledDataSource();  
        cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver              
        cpds.setJdbcUrl( "jdbc:mysql:///atguigu" );  
        cpds.setUser("root");                                    
        cpds.setPassword("1230");     
          
        System.out.println(cpds.getConnection());   
    }  
<?xml version="1.0" encoding="UTF-8"?>  
<c3p0-config>  
  
    <named-config name="helloc3p0">  
          
        <!-- 指定连接数据源的基本属性 -->  
        <property name="user">root</property>  
        <property name="password">1230</property>  
        <property name="driverClass">com.mysql.jdbc.Driver</property>  
        <property name="jdbcUrl">jdbc:mysql:///atguigu</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>  
  
c3p0-config.xml  
转载自:https://blog.csdn.net/u011225629/article/details/45938221