1. 程式人生 > >JDBC 資料庫連線池(DBCP、C3P0) 詳解

JDBC 資料庫連線池(DBCP、C3P0) 詳解

前言

  這段時間狀態有一點浮躁,希望自己靜下心來。還有特別多的東西還沒有學懂。需要學習的東西非常的多,加油!

一、JDBC複習

  Java Data Base Connectivity,java資料庫連線,在需要儲存一些資料,或者拿到一些資料的時候,就需要往資料庫裡存取資料。那麼java如何連線資料庫呢?需要哪些步驟?

1.1、註冊驅動

  1)什麼是驅動

     驅動就是JDBC實現類,通俗點講,就是能夠連線到資料庫功能的東西就是驅動,由於市面上有很多資料庫,Oracle、MySql等等,所以java就有一個連線資料庫的實現規

    範介面,定義一系列的連線資料庫介面(java.sql.Driver介面),但是不提供實現,而每個資料庫廠家來提供這些介面的具體實現

,這樣一來,不管使用的是什麼資料庫,我

    們開發者寫的程式碼都是相同的,就不必因為資料庫的不同,而寫法不同,唯一的不同就是資料庫驅動不一樣,使用mysql,那麼就必須使用mysql的驅動,使用Oracle就必

    須使用oracle的驅動實現類。

    看下面mysql連線資料的原理圖,看看驅動是在哪裡,起什麼作用?

    

  2)DriverManager,一個工具類,是用於操作管理JDBC實現類的

複製程式碼
 原始寫法:DriverManager.register(new Driver());  //因為使用的是MySql,所以在導包時就需要匯入com.mysql.jdbc.Driver
 現在寫法:Class.forName("com.mysql.jdbc.Driver");  //不用導包,會執行com.mysql.jdbc.Driver類中的靜態程式碼塊,其靜態程式碼塊的內容為    static {       try {                  java.sql.DriverManager.registerDriver(new Driver());                  } catch (SQLException E) {                     
throw new RuntimeException("Can't register driver!");          }          }  
複製程式碼

  分析: 

   會發現第二種載入驅動的方法的底層其實就是第一種載入驅動。為什麼要這樣呢?原因很簡單, 第一種是硬程式設計,直接將資料庫驅動給寫死了,無法擴充套件,如果使用第一

   種,那麼連線的資料庫只能是mysql,因為導包導的是mysql的驅動包,如果換成Oracle,就會報錯,需要在程式碼中將Oracle的驅動包匯入,這樣很麻煩,而第二種寫法就不

   一樣了,第二種是使用的字串方法註冊驅動的,我們只需要將該字串提取到一個配置檔案中,以後想換成oracle資料庫,只需要將該字串換成oracle驅動的類全名即可

   ,而不需要到程式碼中去修改什麼東西。

1.2、獲取連線

  使用DriverManage來獲得連線,因為DriverManager是驅動實現類的管理者

  Connection conn = DriverManager.getConnection(url,user,password);

    url:確定資料庫伺服器的位置,埠號,資料庫名

      jdbc:mysql://localhost:3306/db 

    user:登入名稱,預設root

    password:密碼,預設root   

  這裡只是說mysql,別的資料庫,url格式就不同了。

    MySQL    jdbc:mysql://localhost:3306/db    預設埠是3306,粗體為連線時使用的資料庫名

    Oracle     jdbc:oracle:thin:@localhost:1521:db  預設埠號1521

    DB2      jdbc:db2://localhost:6789/db      預設埠號6789

    SQLServer  jdbc:microsoft:sqlserver://localhost:1433;databaseName=db  預設埠號1433

    SQLServer 2005  jdbc:sqlserver://localhost:1433;databaseName=db  預設埠號1433

1.3、獲取執行sql物件,PreparedStatement物件 

  通過Connection物件獲取Statement或者PraparedStament物件(使用它)處理sql

  1)Statement

    Statement st = conn.createStatement();  //獲取sql語句執行物件

    st.excuteUpdate(sql);  //執行增刪改語句

    st.excuteQuery(sql);  //執行查詢語句      

    sql語句必須是完整的。

  2)PraparedStatment

    sql語句可以不是完整的,可以將引數用?替代,然後在預編譯後加入未知引數

    PraparedStatment ps = conn.prapareStatement(sql);  //獲取sql語句執行物件praparedStatment

    賦值

      ps.setInt(Index,value);  ps.setString(index,value);  //可以設定很多中型別,index從1開始,代表sql語句中的第幾個未知引數,

      ps.excuteUpdate();  //執行增刪改語句

      ps.excuteQuery(sql);  //執行查詢語句

  這兩個的區別,常使用的是PraparedStatment物件,因為它可以預編譯,效率高,可以設定引數等等優點。

1.4、獲取結果集物件

  int count = ps.excuteUpdate();   //執行增刪改的sql語句時,返回一個int型別的整數,代表資料庫表影響的行數,

  Result result = ps.excuteQuery();  //執行查詢sql語句時,返回一個結果集物件,該物件裝著所有查詢到的資料資訊,一行一行的儲存資料庫表資訊。

1.5、處理結果集

  對查詢到的Result結果進行處理,拿到所有資料,並封裝成物件。

複製程式碼
        while(rs.next()){

          獲取行資料的第一種方式
          rs.getString(index);//index代表第幾列,從1開始

          獲取行資料的第二中方式
          rs.getString(string);  //string:代表欄位名稱。

        }
複製程式碼

  

  總結:java的JDBC就分為5步,4個屬性

    屬性:driver、url、user、password

    五步:

      註冊驅動、獲取連線、獲取執行sql語句物件、獲取結果集物件、處理結果。

二、JDBC的CURD操作

  建立(Create)、更新(Update)、讀取(Retrieve)和刪除(Delete)操作

  查詢所有(讀取Retrieve)

2.1、查詢所有記錄讀取(Retrieve)

 findAll()

2.2、增加操作(建立Create)  

 save()

2.3、更新操作 (Update)

 update()

2.4、刪除操作(delete)

 delete()

  也可以用我前面寫的JDBC連線的工具類去連線!

三、資料庫連線池

  在上面,我們在進行CRUD時,一直重複性的寫一些程式碼,比如最開始的註冊驅動,獲取連線程式碼,一直重複寫,通過編寫一個獲取連線的工具類後,解決了這個問題,但是又

  會出現新的問題,每進行一次操作,就會獲取一個連線,用完之後,就銷燬,就這樣一直新建連線,銷燬連線,新建,銷燬,連線Connection 建立與銷燬 比較耗時的。所以應

  該要想辦法解決這個問題?

  解決方法:

    連線池就是為了解決這個問題而出現的一個方法,為了提高效能,開發連線池,連線池中一直保持有n個連線,供呼叫者使用,呼叫者用完返還給連線池,繼續給別的呼叫

    者使,比如連線池中一開始就有10個連線,當有5個使用者拿走了5個連線後,池中還剩5個,當第6個使用者在去池中拿連線而前面5個連線還沒歸還時,連線池就會新建一個

    連線給第六個使用者,讓池中一直能夠儲存最少5個連線,而當這樣新建了很多連線後,使用者歸還連接回來時,會比原先連線池中的10個連線更多,連線池就會設定一個池中

    最大空閒的連接數,如果超過了這個數,就會將超過的連線給釋放掉,連線池就是這樣工作的。

3.1、連線池概述

  資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個釋放空閒時間超過最大空閒時間的資料庫連線來避

  免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項技術能明顯提高對資料庫操作的效能。

3.2、比較應用程式直接獲取連線和使用連線池

  1)應用程式直接獲取連線

    

    缺點:使用者每次請求都需要向資料庫獲得連結,而資料庫建立連線通常需要消耗相對較大的資源,建立時間也較長。

          假設網站一天10萬訪問量,資料庫伺服器就需要建立10萬次連線,極大的浪費資料庫的資源,並且極易造成資料庫伺服器記憶體溢位、宕機。

  2)使用連線池連線

     

    目的:解決建立資料庫連線耗費資源和時間很多的問題,提高效能。

四、常用的資料庫連線池  

  現在很多WEB伺服器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的實現,即連線池的實現。通常我們把DataSource的實現,按其英文含義稱之為資料來源,

  資料來源中都包含了資料庫連線池的實現。
  也有一些開源組織提供了資料來源的獨立實現:
    DBCP 資料庫連線池 
    C3P0 資料庫連線池
  實際應用時不需要編寫連線資料庫程式碼,直接從資料來源獲得資料庫的連線。程式設計師程式設計時也應儘量使用這些資料來源的實現,以提升程式的資料庫訪問效能。

  DBCP、C3P0、tomcat內建連線池(JNDI)是我們開發中會用到的。

4.1、DBCP連線池

  1)概述

    DBCP 是 Apache 軟體基金組織下的開源連線池實現,使用DBCP資料來源,應用程式應在系統中增加如下兩個 jar 檔案:
      Commons-dbcp.jar:連線池的實現
      Commons-pool.jar:連線池實現的依賴庫
    Tomcat 的連線池正是採用該連線池來實現的。該資料庫連線池既可以與應用伺服器整合使用,也可由應用程式獨立使用。

  1)獲取連線的兩種方式

    兩種方式獲得連線,使用配置檔案,不使用配置檔案

    1.1)不使用配置檔案,自己手動設定引數

       第一:導包

      

      第二:測試例子

 TestDBCP

    1.2)使用配置檔案,引數寫入配置檔案中即可,也就是通過配置檔案來配置驅動、使用者名稱、密碼、等資訊  

      第一:導包

      和上面的一樣的

      第二:匯入配置檔案dbcpconfig.properties

 dbcpconfig.properties

      第三:獲取連線,測試例子

複製程式碼
package com.zyh.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class TestDBCPPro {

    public static void main(String[] args) {
        Connection conn = TestDBCPPro.getConnection();
        try {
            String sql = "select id,name,price from book";
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                String id = rs.getString(1);
                String name = rs.getString(2);
                double price = rs.getDouble(3);
                System.out.println("id="+id+",name="+name+",price="+price);
                System.out.println("-------------------------");
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    public static Connection getConnection(){
         //通過類載入器獲取指定配置檔案的輸入流,TestDBCPPro是一個類名
        InputStream in = TestDBCPPro.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
        Properties properties = new Properties();
        try {
                properties.load(in);
                //載入配置檔案,獲得配置資訊
                DataSource ds = BasicDataSourceFactory.createDataSource(properties);
                Connection conn = ds.getConnection();
                return conn;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    

}
複製程式碼

    1.3)編寫一個數據源工具類

複製程式碼
package com.zyh.util;


import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.imageio.stream.FileImageInputStream;
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCPUtils {
    private static DataSource ds = null;
    static{
        Properties prop = new Properties();
        try {
            prop.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));//根據DBCPUtil的classes的路徑,載入配置檔案
            ds = BasicDataSourceFactory.createDataSource(prop);//得到一個數據源 
        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化錯誤,請檢查配置檔案");
        }
    }
    
    public static Connection getConnection(){
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException("伺服器忙。。。");
        }
    }
    
    public static void release(Connection conn,Statement stmt,ResultSet rs){
        //關閉資源
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    rs = null;
                }
                if(stmt!=null){
                    try {
                        stmt.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    stmt = null;
                }
                if(conn!=null){
                    try {
                        conn.close();//關閉
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    conn = null;
                }
    }
    
}
複製程式碼

4.2、C3P0

  1)導包

  

  2)從配置資訊中獲取  配置檔案必須為xml(c3p0-config.xml)

複製程式碼
<c3p0-config>
    <!-- 預設配置,如果沒有指定則使用這個配置 -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/book</property>
        <property name="user">root</property>
        <property name="password">654321</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> 
    <!-- 命名的配置 -->
    <named-config name="jxpx">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/myums</property>
        <property name="user">root</property>
        <property name="password">root</property>
    <!-- 如果池中資料連線不夠時一次增長多少個 -->
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">20</property>
        <property name="minPoolSize">10</property>
        <property name="maxPoolSize">40</property>
        <property name="maxStatements">0</property>
        <property name="maxStatementsPerConnection">5</property>
    </named-config>
</c3p0-config>
複製程式碼   

    從配置檔案中看,需要注意一個地方,一個是default-config,一個是name-config,兩者都區別在於建立核心類物件時,如果將name-config作為引數傳進去,

    那麼將會呼叫name-config下的配置資訊,否則將呼叫default-config下的配置資訊,

    兩種方式使用c3p0,加引數,使用named-config 的配置資訊不加引數,自動載入配置資訊,載入的是default-config中的資訊。

複製程式碼
        //1 c3p0...jar 將自動載入配置檔案。規定:WEB-INF/classes (src)  c3p0-config.xml,也就是將配置檔案放在src下就會自動載入。
         //ComboPooledDataSource dataSource = new ComboPooledDataSource(); //自動從配置檔案 <default-config>
         ComboPooledDataSource dataSource = new ComboPooledDataSource(); //手動指定配置檔案 <named-config name="jxpx">
         Connection conn = dataSource.getConnection();
         System.out.println(conn);
複製程式碼

  3)編寫一個數據源工具類

  這個工具類的xml是:

 c3p0-config.xml

  工具類

 C3P0Util

4.3、用JavaWeb伺服器管理資料來源:Tomcat

  開發JavaWeb應用,必須使用一個JavaWeb伺服器,JavaWeb伺服器都內建資料來源
  Tomcat:(DBCP)
  資料來源只需要配置伺服器即可
  配置資料來源的步驟:
    1)拷貝資料庫連線的jar到tomcatlib目錄下
    2)配置資料來源XML檔案
      a)如果把配置資訊寫在tomcat下的conf目錄的context.xml中,那麼所有應用都能使用此資料來源。
      b)如果是在當前應用的META-INF中建立context.xml, 編寫資料來源,那麼只有當前應用可以使用。

 context.xml

  在servlet中進行測試:

  Context initCtx = new InitialContext();
  Context envCtx = (Context) initCtx.lookup("java:comp/env");  //path
  dataSource = (DataSource)envCtx.lookup("jdbc/datasource");   //context.xml中resource的name

  注意:此種配置下,驅動jar檔案需放置在tomcat的lib下  

  擴充套件:

    JNDI技術介紹:

      1)JNDI(Java Naming and Directory Interface),Java命名和目錄介面,它對應於J2SE中的javax.naming包。
      2)這套API的主要作用在於:

        它可以把Java物件放在一個容器中(JNDI容器),併為容器中的java物件取一個名稱,以後程式想獲得Java物件,只需通過名稱檢索即可
      3)其核心API為Context,它代表JNDI容器,其lookup方法為檢索容器中對應名稱的物件。

相關推薦

JDBC 資料庫連線DBCPC3P0

前言   這段時間狀態有一點浮躁,希望自己靜下心來。還有特別多的東西還沒有學懂。需要學習的東西非常的多,加油! 一、JDBC複習   Java Data Base Connectivity,java資料庫連線,在需要儲存一些資料,或者拿到一些資料的時候,就需要往

JDBC資料庫連線DBCPC3P0

前言   這段時間狀態有一點浮躁,希望自己靜下心來。還有特別多的東西還沒有學懂。需要學習的東西非常的多,加油! 一、JDBC複習   Java Data Base Connectivity,java資料庫連線,在需要儲存一些資料,或者拿到一些資料的時候,就需要往資料庫裡存取資料。那麼java如何連線資料

mysql筆記五——資料庫連線原理構建和java動態代理的使用

資料庫連線池 1、什麼是資料庫連線池?       資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項

JDBC4----------資料庫連線dbcp連線

1、JDBC:是提供用來執行SQL語句的java API.步驟如下:載入驅動程式、與資料庫建立連線、傳送SQL語句、處理結果。2、JTA:事務有提交和回滾兩個概念。提交:所有的操作步驟都被完整的執行後,稱為事務被提交。回滾:由於某一操作步驟執行失敗,導致所有步驟都沒有被提交,

常見連接相關dbcpc3p0

cef apach pri cdata created stream fileinput word put DBCP:(理解)   apache組織 使用步驟: 1.導入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.ja

Java個人總結——JDBC資料庫連線

三種常見的資料庫連線池 一、DBCP連線池 DBCP(DataBase connection pool),[資料庫連線池]。是 apache 上的一個 java 連線池專案,也是 tomcat 使用的連線池元件。單獨使用dbcp需要2個包:commons-dbcp.

爬蟲原理與會話保持cookiessession--python實現

一、爬蟲原理     我們知道網際網路是由大量計算機和網路構成的複雜系統,我們可以將其形象的比喻成一張蜘蛛網。網路的節點是計算機,計算機中儲存著大量的資料。爬蟲程式就是通過網路去採集指定計算機中資料的工具。一般來說,我們採集的資料大多是網頁上的資料,

順序表和連結串列的優缺點區別特點

順序表和連結串列由於儲存結構上的差異,導致它們具有不同的特點,適用於不同的場景。本節就來分析它們的特點,讓讀者明白 "在什麼樣的場景中使用哪種儲存結構" 更能有效解決問題。 通過系統地學習順序表和連結串列我們知道,雖然它們同屬於線性表,但資料的儲存結構有本質的不同: 順序表儲存資料,需預先申請一整塊足夠

Java——Web開發之開源的資料庫連線C3P0DBCP的使用

緊接上一篇資料庫連線池的學習,點連線直達~   資料庫連線池的簡單理解與使用 資料庫連線池DBCP程式碼連線與配置檔案: 1.先匯入使用的jar檔案,分別是dbcp.jar與pool.jar檔案 2.分別使用兩種方式實現,使用配置檔案(dbcpconfig.

JDBC資料庫連線連線資料庫資料庫操作DAO層設計通用更新及查詢方法

上篇文章主要介紹了通過資料庫連線池連線資料庫,然後設計了對資料庫通用更新和查詢方法,本篇文章主要通過例項介紹上篇文章定義的對資料庫操作的幾個方法的使用:     首先我們先在資料庫建立一個學生資訊表Student欄位如圖: 建立好表將配置檔案的資訊改好然後需要建立一

JDBC資料庫連線連線資料庫資料庫操作DAO層設計通用更新及查詢方法

該篇文章介紹了資料庫連線池獲取資料庫連線以及資料庫操作的基本使用,然後主要提供了java專案案例中dao層的一種設計,利用反射的原理定義了通用的查詢方法可以對應所有的表和例項。文章中的每段程式碼都提供了詳細的註釋及邏輯步驟 首先匯入資料庫連線的所需要的jar包:    

[課本10.1.4]JDBC資料庫連線- C3P0資料來源--通過構造方法建立資料來源物件--通過配置檔案建立資料來源物件[推薦]

JDBC- C3P0資料來源 1 /*重點提醒*/ 2 連線資料庫的較低的jar包版本會與較高版本的mysql版本有衝突; 3 通過把mysql 8.0的版本降到5.5, jar包仍使用較高的 mysql-connector-java-5.1.7-bin.jar, 完美解決衝突.  

常用資料庫連線dbpc,c3p0,Druid

1. 引言 1.1 定義 資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。 資料庫連線池負責分配、管理和釋放資料庫連線,它允許應

JDBC-資料庫連線

JDBC資料庫連線池的必要性 一、在使用開發基於資料庫的web程式時,傳統的模式基本是按一下步驟: 1)在主程式(如servlet/beans)中建立資料庫連線 2)進行sql操作 3)斷開資料庫連線 二、這種模式開發,存在的問題: 1)普通的JDBC資料庫連線使用Drive

資料庫 連線緩衝定義原理

資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需要從緩衝池中取出一個了,使用完畢後再放回去。我們可以通過設定連線池最大數來防止系統無盡的與資料庫連線。更為重要的是我們可以通過連線池的管

使用資料庫連線C3P0管理資料來源出現的Too many connections問題

使用了Spring的HibernateDaoSupport管理資料DAO,如果在方法中使用了this.getSession()獲取session後,不在後面關閉session(session.close()),就會造成

配置資料庫連線資料來源--------java利用BasicDataSource

DataSource又稱為資料來源,該類的目的是為了防止使用資料庫時不必要操作帶來的資源浪費,使用資料庫時需要進行資料庫連線,才可以使用資料庫,使用資料庫後,又要斷開連結,用來釋放資源。連結資料庫和斷開資料庫連線浪費資源,而且在頻繁操作資料庫的時候,如果按照沒有資料來源的方式

IOC整合JDBC模板&連線17

整合Spring自帶連線池 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property

Spring Boot 整合 Mybatisdruid 資料庫連線 以及 分頁配置

MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映,目前很大一部分網際網路、軟體公司都在使用這套框架 下來來之後,我們主要關注幾個檔案 配置檔案:generator.properties 主要是資料庫的相關配置,以及檔案生成的根路徑 generator.jdbc.drive

JDBC-資料庫連線/操作

1.資料庫連線池的必要性 不使用資料庫連線池: 在使用開發基於資料庫的web程式時,傳統的模式基本是按以下步驟:   在主程式(如servlet、beans、DAO)中建立資料庫連線。 進行sql操作 斷開資料庫連線。 這種模式開發,存在的問題: 普通的JDBC