天天看點

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

文章轉載多處:https://blog.csdn.net/weixin_34121282/article/details/93382694

文章目錄

  • 一、JDBC基礎
    • (一)ODBC到JDBC的發展曆程
      • 1.ODBC的結構模型
      • 2.JDBC的誕生
    • (二)JDBC技術概述
    • (三)JDBC技術及使用詳解
      • 1.何謂驅動?
      • 2.JDBC驅動程式的分類
  • 二、JDBC連接配接MySQL資料庫的基礎方式
    • (一)通過JDBC操作資料庫的基本步驟
      • 1.使用JDBC第一步:加載驅動
      • 2.使用JDBC第二步:建立連接配接
      • 3.使用JDBC第三步:建立執行對象
      • 4.使用JDBC第四步:執行SQL語句
      • 5.使用JDBC第五步:處理執行結果
      • 6.使用JDBC 第六步——釋放資源
    • (二)JDBC連接配接資料庫具體代碼示例
      • 1.确認資料庫是否存在
      • 2.連接配接并操作資料庫
  • 三、DBCP連接配接MySQL資料庫詳解
    • (一)DBCP2原理
    • (二)認識BasicDataSource類
      • 1.四個必須的set方法
      • 2.四個重要的拓展方法
      • 3.事務屬性配置
    • (三)讀取properties檔案建立BasicDataSource
      • 1.properties檔案格式
      • 2.用BasicDataSourceFactoy建立BasicDataSource資料庫連接配接池
    • (四) 在SpringIOC容器中建立BasicDataSource資料庫連接配接池
      • 1.配置xml核心配置檔案
      • 2.測試在IOC容器中BasicDataSource資料庫連接配接池
    • (五)建立BasicDataSource工具類來建立連接配接池
      • 1.建立DBCP連接配接池管理工具類
      • 2.在靜态工廠工具類中采取BasicDataSourceFactory來建立DBCP資料庫連接配接池
        • (1) 直接調用
        • (2) IOC容器中采取靜态工廠方式調用
      • 3.配置IOC 核心配置檔案xml
      • 4.分别從IOC容器和工具類中取得BasicDataSource資料庫連接配接池
  • 四、C3P0資料庫連接配接池詳解
    • (一)建立c3p0-config.xml檔案
    • (二)采取IOC容器建立C3P0資料庫連接配接池
      • 1.c3p0屬性檔案
      • 2.IOC容器配置檔案xml

一、JDBC基礎

  • DBC (Java DB Connection)—Java資料庫連接配接
  • JDBC是一種可用于執行SQL語句的JAVA API(ApplicationProgramming Interface應用程式設計接口)。它由一些Java語言編寫的類和界面組成。
  • JDBC為資料庫應用開發人員和資料庫前台工具開發人員提供了一種标準的應用程式設計接口,使開發人員可以用純JAVA語言編寫完整的資料庫應用程式。
  • JDBC代表JAVA資料庫連接配接。它是一個軟體層,允許開發者在JAVA中編寫用戶端/伺服器應用。

(一)ODBC到JDBC的發展曆程

ODBC是OpenDatabaseConnectivity的英文簡寫。它是一種用來在相關或不相關的資料庫管理系統(DBMS)中存取資料的,用C語言實作的,标準應用程式資料接口。通過ODBCAPI,應用程式可以存取儲存在多種不同資料庫管理系統(DBMS)中的資料,而不論每個DBMS使用了何種資料存儲格式和程式設計接口。

1.ODBC的結構模型

ODBC的結構包括四個主要部分:應用程式接口、驅動器管理器、資料庫驅動器和資料源。

應用程式接口:屏蔽不同的ODBC資料庫驅動器之間函數調用的差别,為使用者提供統一的SQL程式設計接口。

驅動器管理器:為應用程式裝載資料庫驅動器。

資料庫驅動器:實作ODBC的函數調用,提供對特定資料源的SQL請求。如果需要,資料庫驅動器将修改應用程式的請求,使得請求符合相關的DBMS所支援的文法。

資料源:由使用者想要存取的資料以及與它相關的作業系統、DBMS和用于通路DBMS的網絡平台組成。

雖然ODBC驅動器管理器的主要目的是加載資料庫驅動器,以便ODBC函數調用,但是資料庫驅動器本身也執行ODBC函數調用,并與資料庫互相配合。是以當應用系統發出調用與資料源進行連接配接時,資料庫驅動器能管理通信協定。當建立起與資料源的連接配接時,資料庫驅動器便能處理應用系統向DBMS發出的請求,對分析或發自資料源的設計進行必要的翻譯,并将結果傳回給應用系統。

2.JDBC的誕生

自從Java語言于1995年5月正式公布以來,Java風靡全球。出現大量的用java語言編寫的程式,其中也包括資料庫應用程式。由于沒有一個Java語言的API,程式設計人員不得不在Java程式中加入C語言的ODBC函數調用。這就使很多Java的優秀特性無法充分發揮,比如平台無關性、面向對象特性等。随着越來越多的程式設計人員對Java語言的日益喜愛,越來越多的公司在Java程式開發上投入的精力日益增加,對java語言接口的通路資料庫的API的要求越來越強烈。也由于ODBC的有其不足之處,比如它并不容易使用,沒有面向對象的特性等等,SUN公司決定開發一Java語言為接口的資料庫應用程式開發接口。在JDK1.x版本中,JDBC隻是一個可選部件,到了JDK1.1公布時,SQL類包(也就是JDBCAPI)就成為Java語言的标準部件。

(二)JDBC技術概述

  1. JDBC是一種可用于執行SQL語句的JavaAPI(ApplicationProgrammingInterface,應用程式設計接口)。通過使用JDBC,開發人員可以很友善地将SQL語句傳送給幾乎任何一種資料庫。也就是說,開發人員可以不必寫一個程式通路Sybase,寫另一個程式通路Oracle,再寫一個程式通路Microsoft的SQLServer。用JDBC寫的程式能夠自動地将SQL語句傳送給相應的資料庫管理系統(DBMS)。不但如此,使用Java編寫的應用程式可以在任何支援Java的平台上運作,不必在不同的平台上編寫不同的應用。Java和JDBC的結合可以讓開發人員在開發資料庫應用時真正實作“WriteOnce,RunEverywhere!”
  2. Java具有健壯、安全、易用等特性,而且支援自動網上下載下傳,本質上是一種很好的資料庫應用的程式設計語言。它所需要的是Java應用如何同各種各樣的資料庫連接配接,JDBC正是實作這種連接配接的關鍵。
  3. JDBC擴充了Java的能力,如使用Java和JDBCAPI就可以公布一個Web頁,頁中帶有能通路遠端資料庫的Ap plet。或者企業可以通過JDBC讓全部的職工(他們可以使用不同的作業系統,如Windwos,Machintosh和UNIX)在In tranet上連接配接到幾個全球資料庫上,而這幾個全球資料庫可以是不相同的。随着越來越多的程式開發人員使用Java語言,對Java通路資料庫易操作性的需求越來越強烈。
  4. JDBC API定義了一組用于與資料庫通信的接口和類。這些接口和類位于java.sql包中。
  5. JDBC是用來(讓我們的程式)通過網絡來操作資料庫的,作用很重要;JDBC技術也是Java核心技術之一。凡是需要用網絡操作資料庫的程式,JDBC程式設計有問題,一切都是白搭。

(三)JDBC技術及使用詳解

從結構圖中可以看出,通過JDBC API 讓我們的Java應用程式可以利用JDBCDriver Manager[JDBC驅動管理],連接配接到JDBC驅動;展現在我們的工程中也就是要導入驅動jar包。

1.何謂驅動?

不同的資料庫廠商或者同一廠商的不同資料庫版本都會提供不同的驅動,任何應用程式都是通過這個驅動來操作特定廠商、特定版本的資料庫的。

2.JDBC驅動程式的分類

  • 第一類JDBC驅動程式是JDBC-ODBC橋再加上一個ODBC驅動程式。這類驅動一般不用現在的程式設計應用中。
  • 第二類JDBC驅動程式是部分JAVAAPI代碼的驅動程式,用于把JDBC調用轉換成主流資料庫API的本機調用。
  • 第三類JDBC驅動程式是面向資料庫中間件的純JAVA驅動程式,JDBC調用被轉換成一種中間件廠商的協定,中間件再把這些調用轉換到資料庫API。
  • 第四類JDBC驅動程式是直接面向資料庫的純JAVA驅動程式。

二、JDBC連接配接MySQL資料庫的基礎方式

(一)通過JDBC操作資料庫的基本步驟

  • 第1步:注冊驅動 (隻做一次)
  • 第2步:建立連接配接(Connection)
  • 第3步:建立執行SQL的語句(Statement)
  • 第4步:執行語句
  • 第5步:處理執行結果(ResultSet)
  • 第6步:釋放資源

1.使用JDBC第一步:加載驅動

注冊驅動有三種方式:

  • Class.forName(“com.mysql.jdbc.Driver”);推薦這種方式,不會對具體的驅動類産生依賴
  • DriverManager.registerDriver(com.mysql.jdbc.Driver);會對具體的驅動類産生依賴
  • System.setProperty(“jdbc.drivers”, “driver1:driver2”);雖然不會對具體的驅動類産生依賴;但注冊不太友善,是以很少使用

2.使用JDBC第二步:建立連接配接

通過Connection建立連接配接,Connection是一個接口類,其功能是與資料庫進行連接配接(會話)。

  • 建立Connection接口類對象:

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

  • URL的格式要求為:

    JDBC:子協定:子名稱//主機名:端口/資料庫名?屬性名=屬性值&

    如:"jdbc:mysql://localhost:3306/test“

  • user即為登入資料庫的使用者名,如root
  • password即為登入資料庫的密碼,為空就填””

3.使用JDBC第三步:建立執行對象

執行對象Statement負責執行SQL語句,由Connection對象産生。

Statement接口類還派生出兩個接口類PreparedStatement和CallableStatement,這兩個接口類對象為我們提供了更加強大的資料通路功能。

  • 建立Statement的文法為:

Statement st = conn.createStatement();

4.使用JDBC第四步:執行SQL語句

執行對象Statement提供兩個常用的方法來執行SQL語句。

  • executeQuery(Stringsql),該方法用于執行實作查詢功能的sql語句,傳回類型為ResultSet(結果集)。

如:ResultSet rs =st.executeQuery(sql);

  • executeUpdate(Stringsql),該方法用于執行實作增、删、改功能的sql語句,傳回類型為int,即受影響的行數。

如:int flag = st.executeUpdate(sql);

5.使用JDBC第五步:處理執行結果

ResultSet對象

ResultSet對象負責儲存Statement執行後所産生的查詢結果。

結果集ResultSet是通過遊标來操作的。

遊标就是一個可控制的、可以指向任意一條記錄的指針。有了這個指針我們就能輕易地指出我們要對結果集中的哪一條記錄進行修改、删除,或者要在哪一條記錄之前插入資料。一個結果集對象中隻包含一個遊标。

6.使用JDBC 第六步——釋放資源

Connection對象的close方法用于關閉連接配接,并釋放和連接配接相關的資源。

(二)JDBC連接配接資料庫具體代碼示例

1.确認資料庫是否存在

要查詢、增、删資料庫,首先得确認在mysql中是否存在資料庫及相應的表,可以通過cmd在mysql中進行确認

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

2.連接配接并操作資料庫

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解
// TODO: 2021/7/8 傳統的連接配接方式
    @Override
    public void connectionByJdbc() throws ClassNotFoundException, IOException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        InputStream resourceAsStream = JdbcConnectionImpl.class.getClassLoader().getResourceAsStream("jdbcproperties/jdbc.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        Connection connection = DriverManager.getConnection(url, user, password);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            System.out.println(resultSet.getString("name"));
            int salary = resultSet.getInt("salary");
            System.out.println(salary);
        }
    }
           

三、DBCP連接配接MySQL資料庫詳解

DBCP(DataBase Connection Pool)資料庫連接配接池,是java資料庫連接配接池的一種,由Apache開發,通過資料庫連接配接池,可以讓程式自動管理資料庫連接配接的釋放和斷開。

DBCP(DataBase connection pool),資料庫連接配接池。是 apache 上的一個 java 連接配接池項目,也是 tomcat 使用的連接配接池元件。單獨使用dbcp需要2個包:

  • commons-dbcp.jar

    ,
  • commons-pool.jar

由于建立資料庫連接配接是一個非常耗時耗資源的行為,是以通過連接配接池預先同資料庫建立一些連接配接,放在記憶體中,應用程式需要建立資料庫連接配接時直接到連接配接池中申請一個就行,用完後再放回去。

(一)DBCP2原理

DBCP2在初始化時會從資料庫擷取指定數量的連接配接,把這些連接配接存放到空閑連接配接隊列LinkedBlockingDeque裡面,這個隊列是雙向鍊路阻塞型隊列,先進先出,每次要使用連接配接時就從這個隊列擷取頭部結點,擷取連接配接時使用的鎖是ReentrantLock.擷取到連接配接時,該連接配接節點出隊列,更改狀态并且存放到一個ConcurrentHashMap中,辨別該連接配接已被使用,另外會有一個空閑連接配接檢測線程不斷去檢測ConcurrentHashMap中連接配接的狀态,如果連接配接已經關閉(不是資料庫連接配接關閉,而是連接配接在DBCP連接配接池中關閉),則把它從ConcurrentHashMap中删除,并且回收到LinkedBlockingDeque裡面。

  • 優點:

    配置簡單

  • 缺點:

    無論是空閑連接配接還是已使用的連接配接,都是存放加鎖的ConcurrentHashMap或LinkedBlockingDeque中,并發量低,性能不好,适用于小型系統。從資料庫擷取連接配接的過程中還加了synchronized同步鎖,如果網絡容易中斷的場景下,一旦與資料庫建立的網絡出現問題,容易導緻死鎖。

(二)認識BasicDataSource類

commons-dbcp.jar包中有一個類

BasicDataSource類

,該類有一個無參構造方法,可以執行個體化一個BasicDataSource對象,更重要的是這個是實作了

DataSource接口

,這樣更有利于規範化還更符合面向對象接口程式設計。該類當中有四個必須的set方法和四個重要的拓展方法

1.四個必須的set方法

參數 描述
setDriverClassName(String driverClassName) 設定驅動名
setUrl(String url) 設定url參數
setUsername(String username) 設定資料庫連接配接使用者名
setPassword(String password) 設定資料庫連接配接密碼

2.四個重要的拓展方法

參數 描述
setMaxActive(int maxActive) 最大活動連接配接:連接配接池在同一時間能夠配置設定的最大活動連接配接的數量, 如果設定為非正數則表示不限制.
setInitialSize(int initialSize) 初始化連接配接:連接配接池啟動時建立的初始化連接配接數量,1.2版本後支援
setMaxIdle(int maxIdle) 最大空閑連接配接:連接配接池中容許保持空閑狀态的最大連接配接數量,超過的空閑連接配接将被釋放,如果設定為負數表示不限制
setMinIdle(int minIdle) 最小空閑連接配接:連接配接池中容許保持空閑狀态的最小連接配接數量,低于這個數量将建立新的連接配接,如果設定為0則不建立
maxWaitMillis 最大等待時間:當沒有可用連接配接時,連接配接池等待連接配接被歸還的最大時間(以毫秒計數),超過時間則抛出異常

3.事務屬性配置

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

資料源連接配接健康狀況檢查

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

緩存語句

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

連接配接洩露回收

MySQL:JDBC基礎及連接配接資料庫的方式一、JDBC基礎二、JDBC連接配接MySQL資料庫的基礎方式三、DBCP連接配接MySQL資料庫詳解四、C3P0資料庫連接配接池詳解

(三)讀取properties檔案建立BasicDataSource

1.properties檔案格式

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?usessl=false&serverTimezone=UTC
username=root
password=123456
           

2.用BasicDataSourceFactoy建立BasicDataSource資料庫連接配接池

@Test
    public void test30() throws Exception {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("jdbcproperties/jdbc.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
        // TODO: 2021/7/8 設定建立資料庫連接配接池時初始的連接配接數量 
        dataSource.setInitialSize(10);
        // TODO: 2021/7/8 設定最小閑置連接配接數,如果閑置的連接配接數小于設定的值,則會自動建立連接配接 
        dataSource.setMinIdle(2);
        // TODO: 2021/7/8 設定最大閑置連接配接數量,如果閑置連接配接數量超過此值,則會釋放多餘的連接配接 
        dataSource.setMaxIdle(5);
        // TODO: 2021/7/8 設定最大活動連接配接數 
        dataSource.setMaxTotal(10);

        Connection connection = dataSource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id =1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            String salary = resultSet.getString("salary");
            System.out.println("Name:" + name + "Salary:" + salary);
        }
    }
           

(四) 在SpringIOC容器中建立BasicDataSource資料庫連接配接池

1.配置xml核心配置檔案

<!-- TODO:在IOC容器中建立一個BasicDataSource資料庫連接配接池,并将屬性資料裝配到Bean中,這裡的屬性與Properties後置處理器配合,解析Bean中
    的屬性,産生新的屬性名稱,并從屬性檔案中找到對應的屬性值,再次傳遞給BasicDataSource這個bean的屬性-->
    <bean id="datasource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.passowrd}"/>
    </bean>

    <!-- TODO:Properties後置處理器,主要用用是解析Bean中的屬性,從屬性檔案中讀取對應值,再次傳入到Bean中-->
    <!--    <context:property-placeholder location="classpath:dbcp.properties"/>-->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="classpath:dbcp.properties"/>
    </bean>
    
    <!-- TODO:Spring-jdbc中的資料空間,可将BasicDataSource的Bean封裝到其中,可以優化處理-->
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate" autowire="byType"/>
           

2.測試在IOC容器中BasicDataSource資料庫連接配接池

  • 2.1 第一種測試(基本測試,直接調用的是資料庫連接配接池)
@Test
    public void test22() throws SQLException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp.xml");
        BasicDataSource datasource = (BasicDataSource) ac.getBean("datasource");
        Connection connection = datasource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名為:" + name + ";薪資為:" + salary + ";");
        }
    }
           
  • 2.2 第二種測試,(調用的是spring-jdbc中的JdbcTemplate的Bean),他是将連接配接池的Bean注入其中,用他來管理并操作連接配接池查詢、增、删資料,比較友善
@Test
    public void test47() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) ac.getBean("jdbcTemplate");
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");

        for (Map<String, Object> map : maps) {
            String name = (String) map.get("name");
            Long salary = (Long) map.get("salary");
            System.out.println(name + "=" + salary);
        }
    }
           

(五)建立BasicDataSource工具類來建立連接配接池

1.建立DBCP連接配接池管理工具類

public class BasicDataSourceUtil {

    private static BasicDataSource thisbasicDataSource;

    public BasicDataSource createDataSource() throws IOException {
        BasicDataSource basicDataSource = new BasicDataSource();
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("dbcp2.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String driverClassName = properties.getProperty("driverClassName");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        basicDataSource.setDriverClassName(driverClassName);
        basicDataSource.setUrl(url);
        basicDataSource.setUsername(username);
        basicDataSource.setPassword(password);
        thisbasicDataSource = basicDataSource;
        return basicDataSource;
    }

    // TODO: 2021/7/9 傳回一個dbcp資料為連接配接池,一般不會采取這樣的做法,不安全
    public static BasicDataSource getBaiseDataResouce(){
        return thisbasicDataSource;
    }

    // TODO: 2021/7/9 傳回一個連接配接
    public static Connection getConnection() throws SQLException {
        return thisbasicDataSource.getConnection();
    }
}
           

在上面的代碼中,是通過讀取proeperties檔案中對應的屬性值,然後傳遞給DBCP資料庫連接配接池對象,我們也可以通過BasicDataSourceFactory工廠,隻接加載屬性檔案對象,這樣更快速便捷,隻是對Properties檔案的格式有一定的要求。要求屬性檔案中的屬性名必須和BasicDataSource中的屬性名一緻,具體部分屬性如下:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&useSSL=false
username=root
password=123456

maxTotal:100
initialSize:10
maxWait:60000
minIdle:10
maxIdle:15

logAbandoned:true
removeAbandoned:true
removeAbandonedTimeout:10
timeBetweenEvictionRunsMillis:10000
numTestsPerEvictionRun:10
minEvictableIdleTimeMillis:10000
validationQuery:SELECT 1 FROM DUAL

#\u6821\u9A8C\u94FE\u63A5
testWhileIdle:true
testOnBorrow:true
           

2.在靜态工廠工具類中采取BasicDataSourceFactory來建立DBCP資料庫連接配接池

在前一小節中,我們采取的是讀取屬性檔案的屬性值後,再單獨将每個屬性值傳遞給BasicDataSource資料庫連接配接池對象,這樣的效率比較慢,在這裡,我們可以采取BasicDataSourceFactiory類加載屬性對象,來建立一個DBCP資料庫連接配接池。

public class BasicDataSourcePropertiesUtil {

    private static BasicDataSource staticdataSource;
    private static JdbcTemplate staticjdbcTemplate;

    public static BasicDataSource createBasicDataSource(String xmlName) throws Exception {
        InputStream resource AsStream = BasicDataSource.class.getClassLoader().getResourceAsStream(xmlName);
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        staticdataSource = dataSource;
        staticjdbcTemplate = jdbcTemplate;
        return dataSource;
    }

    public static Connection getConnection() throws SQLException {
        return staticdataSource.getConnection();
    }

    public static List<Map<String, Object>> getConnectionQuery(String strQuery) {
        List<Map<String, Object>> maps = staticjdbcTemplate.queryForList(strQuery);
        return maps;
    }
}
           

針對上的工具類建立的資料庫連接配接池,可通直接調用,也可以通過IOC容器,采取靜态工廠的方法來建立.

(1) 直接調用

@Test
    public void test112() throws Exception {
        BasicDataSource basicDataSource = BasicDataSourcePropertiesUtil.createBasicDataSource("dbcp4.properties");
        List<Map<String, Object>> connectionQuery = BasicDataSourcePropertiesUtil.getConnectionQuery("select * from customer");
        for (Map<String, Object> stringObjectMap : connectionQuery) {
            String name = (String) stringObjectMap.get("name");
            Integer salary = (Integer) stringObjectMap.get("salary");
            System.out.println(name + "=" + salary + ";");
        }
    }
           

(2) IOC容器中采取靜态工廠方式調用

  • 首先得建立IOC容器的xml核心配置檔案
<bean class="util.BasicDataSourcePropertiesUtil" factory-method="createBasicDataSource" id="dataSource">
        <constructor-arg name="xmlName" value="dbcp4.properties"/>
    </bean>
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
           
  • 建立IOC容器,并從IOC容器中得到DBCP資料庫連接配接池,或者得到JdbcTemplate對象(用于封裝DBCP資料庫連接配接池對象BasicDataSource,提供了操作資料庫方法)
@Test
    public void test124() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp4.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) ac.getBean("jdbcTemplate");
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");
        for (Map<String, Object> map : maps) {
            String name = (String) map.get("name");
            Integer salary = (Integer) map.get("salary");
            System.out.println(name + "=" + salary + ";");
        }
    }
           

3.配置IOC 核心配置檔案xml

核心 檔案的配置實作了現以下兩個功能:

  • 在IOC容器中建立了工具類的一個Bean,做為執行個體工廠類Bean
  • 調用執行個體工廠類bean中的方法,在IOC中建立一個BasicDataSource連接配接池Bean,同時将這個Bean的引用傳遞到工具類中
<!-- TODO:建立一個BasicDataSource工具類執行個體 -->
    <bean id="datasourceutil" class="util.BasicDataSourceUtil"/>
    <!-- TODO:執行個體工廠類,通過一個方法return 一個BasicDataSource對象,同時在這個執行個體工廠方法中,将這個資料庫連接配接池的Bean的引用傳遞給工具類的BasicDataSource的引用 -->
    <bean id="datasource" factory-bean="datasourceutil" factory-method="createDataSource" destroy-method="close"/>

           

4.分别從IOC容器和工具類中取得BasicDataSource資料庫連接配接池

  • 從IOC中取得連接配接池
// TODO: 2021/7/9 這個是從IOC容器中取得到的資料為連接配接池
    @Test
    public void test44() throws SQLException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp2.xml");
        BasicDataSource datasource = (BasicDataSource) ac.getBean("datasource");
        Connection newconnection = datasource.getConnection();
        Statement statement = newconnection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名為:" + name + ";薪資為:" + salary + ";");
        }
        resultSet.close();
        statement.close();
        newconnection.close();
    }
           
  • 從工具類中取得連接配接池
// TODO: 2021/7/9 調用工具類的做法 ,從工具類中得到資料庫連接配接池
    @Test
    public void test63() throws SQLException {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("dbcp2.xml");
        Connection connection = BasicDataSourceUtil.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名為:" + name + ";薪資為:" + salary + ";");
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
           

四、C3P0資料庫連接配接池詳解

C3P0,它實作了資料源和JNDI綁定,支援JDBC3規範和JDBC2的标準擴充。目前使用它的開源項目有Hibernate,Spring等,這個被推薦使用.他的配置相對簡單,可以直接通過加載檔案就可以配置成功!

(一)建立c3p0-config.xml檔案

這是一個c3p0資料庫連接配接池的配置檔案,他可以預設狀态,也可以指定配置名稱配置.這樣的話,c3p0資料庫連接配接池在建立中,可以指定不同的名,加載一個c3p0-config.xml檔案,建立不同的資料庫連接配接池!

  • xml連接配接池配置檔案
<?xml version="1.0" encoding="UTF-8"?>

<!-- TODO: 此檔案必須命名為: c3p0-confing.xml-->
<c3p0-config>
    <!-- TODO:此處為給此檔案命名為:jdbcConfig,在建立c3p0資料庫連接配接池時,可以通過此名來加載引xml檔案 -->
    <named-config name="jdbcConfig">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 當連接配接數量用盡時,可定期的增量數 -->
        <property name="acquireIncrement">10</property>
        <!-- 資料庫初始化時,需要初始化連接配接池中連接配接的數量 -->
        <property name="initialPoolSize">100</property>
        <!-- 連接配接池的最小連接配接數 -->
        <property name="minPoolSize">10</property>
        <!-- 連接配接池的最大連接配接數 -->
        <property name="maxPoolSize">200</property>
        <!-- 連接配接池中 Statement 的最大個數 -->
        <property name="maxStatements">20</property>
        <!-- 連接配接池中每個連接配接可以同時使用的 Statement 的個數 -->
        <property name="maxStatementsPerConnection">5</property>
    </named-config>

    <named-config name="abcd">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 當連接配接數量用盡時,可定期的增量數 -->
        <property name="acquireIncrement">10</property>
        <!-- 資料庫初始化時,需要初始化連接配接池中連接配接的數量 -->
        <property name="initialPoolSize">100</property>
        <!-- 連接配接池的最小連接配接數 -->
        <property name="minPoolSize">10</property>
        <!-- 連接配接池的最大連接配接數 -->
        <property name="maxPoolSize">200</property>
        <!-- 連接配接池中 Statement 的最大個數 -->
        <property name="maxStatements">20</property>
        <!-- 連接配接池中每個連接配接可以同時使用的 Statement 的個數 -->
        <property name="maxStatementsPerConnection">5</property>
    </named-config>
    
    <default-config>
        <!-- TODO:這個地方可以寫預設的c3p0資料庫連接配接池配置檔案 -->
    </default-config>

</c3p0-config>
           
  • 直接建立連接配接池
public class CmoboPoolUtil {

    private static ComboPooledDataSource dataSource;

    public static ComboPooledDataSource createComboPoolDataSource(String c3p0config) {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(c3p0config);
        dataSource = comboPooledDataSource;
        return comboPooledDataSource;
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}
           
  • 在IOC容器中以靜态工廠的方式建立連接配接池
?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="datasource" class="util.CmoboPoolUtil" factory-method="createComboPoolDataSource" destroy-method="close">
        <constructor-arg name="c3p0config" value="jdbcConfig"/>
    </bean>
    <bean class="org.springframework.jdbc.core.JdbcTemplate" name="jdbcTemplate">
        <property name="dataSource" ref="datasource"/>
    </bean>

    <bean id="abcd" class="util.CmoboPoolUtil" factory-method="createComboPoolDataSource" destroy-method="close">
        <constructor-arg name="c3p0config" value="abcd"/>
    </bean>
    <bean id="springjdbc" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="abcd"/>
    </bean>


</beans>
           

(二)采取IOC容器建立C3P0資料庫連接配接池

在IOC容器中,可以直接建立一個C3p0的資料庫連接配接池的Bean,并設定配置屬性,配置屬性可以建立一個配置屬性properties檔案,在IOC容器中上,通過properties後置處理器解析c3p0資料庫連接配接池Bean的屬性,通過解析的名字,從屬性檔案中得到對應的屬性值,并得新給c3p0資料庫連接配接池中的屬性指派,在這個地方,properties後置處理器的主要功能有:

  • 解析IOC Bean中的屬性
  • 加載propertids屬性檔案
  • 通過解析後的字元找到相應的屬性值,并重新指派給Bean中的屬性.

1.c3p0屬性檔案

driverClass=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/newdb?useSSL=false&serverTimezone=UTC
user=root
password=123456
acquireIncrement=10
initialPoolSize=100
minPoolSize=10
maxPoolSize=200
maxStatements=20
maxStatementsPerConnection=5
           

2.IOC容器配置檔案xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- TODO:在IOC容器中建立c3p0資料庫連接配接池 -->
    <bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>

        <property name="acquireIncrement" value="${acquireIncrement}"/>
        <property name="initialPoolSize" value="${initialPoolSize}"/>
        <property name="minPoolSize" value="${minPoolSize}"/>
        <property name="maxPoolSize" value="${maxPoolSize}"/>
        <property name="maxStatements" value="${maxStatements}"/>
        <property name="maxStatementsPerConnection" value="${maxStatementsPerConnection}"/>
    </bean>
    <!-- TODO:IOC後置處理器,解析Bean中的屬性,從指定的屬性檔案中讀取對應的屬性值,重新注入到Bean中 -->
    <!--    <context:property-placeholder location="classpath:c3p0.properties"/>-->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="classpath:c3p0.properties"/>
    </bean>
    <!-- TODO:建立一個Srping-jdbc包裝類,用于封裝c3po資料庫連接配接池,可以對資料庫連接配接池進行操作 -->
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate" autowire="byType"/>

</beans>

           

繼續閱讀