開(kāi)源數(shù)據(jù)庫(kù)連接池的使用

上篇博客剛剛說(shuō)完如何去自定義一個(gè)數(shù)據(jù)庫(kù)連接池斑举,當(dāng)然糊肤,這個(gè)自定義的數(shù)據(jù)庫(kù)連接池是十分簡(jiǎn)易的,憑借自己的能力也無(wú)法寫出優(yōu)秀的連接池啰扛。但是嚎京,不用擔(dān)心,我們可以使用開(kāi)源的數(shù)據(jù)庫(kù)連接池侠讯,開(kāi)源的優(yōu)勢(shì)體現(xiàn)于此挖藏。

在Java中有三種開(kāi)源數(shù)據(jù)庫(kù)連接池提供了數(shù)據(jù)源的獨(dú)立實(shí)現(xiàn):

  • DBCP 數(shù)據(jù)庫(kù)連接池
  • C3P0 數(shù)據(jù)庫(kù)連接池
  • Apache Tomcat內(nèi)置的連接池(apache dbcp)
1、DBCP數(shù)據(jù)庫(kù)連接池

DBCP是Apache軟件基金組織下的開(kāi)源連接池實(shí)現(xiàn)厢漩,使用DBCP數(shù)據(jù)源膜眠,應(yīng)用程序應(yīng)在系統(tǒng)中增加如下兩個(gè)jar文件:

  • commons-dbcp.jar
  • commons-pool.jar

今天的jar包資源我也放在了網(wǎng)盤上。鏈接:https://pan.baidu.com/s/1-Rj4TQLI_5DGLdfb45N62g
提取碼:ba3a
復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤手機(jī)App溜嗜,操作更方便哦
jar包準(zhǔn)備好了宵膨,那么我們來(lái)使用一下。
新建一個(gè)Java項(xiàng)目炸宵。
然后新建測(cè)試類DBCPTest辟躏,編寫測(cè)試代碼

@Test
public void demo1(){
    //首先使用BasicDataSource創(chuàng)建連接池
    BasicDataSource basicDataSource = new BasicDataSource();
    try {
        //從連接池中獲取連接
        Connection connection = basicDataSource.getConnection();
        String sql = "select * from account";
        PreparedStatement stmt = connection.prepareStatement(sql);
        ResultSet set = stmt.executeQuery();
        while(set.next()){
            System.out.println(set.getString("name"));
        }
        //釋放資源
        JDBCUtils.release(stmt, connection);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

現(xiàn)在運(yùn)行測(cè)試代碼,能查詢出表數(shù)據(jù)嗎土全?
很顯然捎琐,連數(shù)據(jù)庫(kù)參數(shù)都沒(méi)給会涎,這段測(cè)試代碼肯定會(huì)報(bào)錯(cuò)。
那現(xiàn)在就來(lái)設(shè)置一下參數(shù)瑞凑,修改測(cè)試代碼

@Test
public void demo1(){
    //首先使用BasicDataSource創(chuàng)建連接池
    BasicDataSource basicDataSource = new BasicDataSource();
    //創(chuàng)建連接需要四個(gè)參數(shù)
    basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
    basicDataSource.setUrl("jdbc:mysql:///test");
    basicDataSource.setUsername("root");
    basicDataSource.setPassword("123456");
    try {
        //從連接池中獲取連接
        Connection connection = basicDataSource.getConnection();
        String sql = "select * from account";
        PreparedStatement stmt = connection.prepareStatement(sql);
        ResultSet set = stmt.executeQuery();
        while(set.next()){
            System.out.println(set.getString("name"));
        }
        //釋放資源
        JDBCUtils.release(stmt, connection);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

現(xiàn)在運(yùn)行測(cè)試代碼


在這里插入圖片描述

成功查詢到表數(shù)據(jù)末秃。但是這樣寫具有局限性,應(yīng)該把數(shù)據(jù)庫(kù)參數(shù)寫成配置文件籽御,以適應(yīng)靈活多變的用戶需求练慕。
在src目錄下新建配置文件dbcp.properties

driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql:///test
username = root
password =123456

編寫測(cè)試代碼

@Test
public void demo2() throws Exception{
    //讀取dbcp.properties
    Properties properties = new Properties();
    properties.load(new FileInputStream(this.getClass().getResource("/dbcp.properties").getFile()));
    DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
    //從連接池中獲取連接
    Connection connection = dataSource.getConnection();
    String sql = "select * from account";
    PreparedStatement stmt = connection.prepareStatement(sql);
    ResultSet set = stmt.executeQuery();
    while(set.next()){
        System.out.println(set.getString("name"));
    }
    //釋放資源
    JDBCUtils.release(stmt, connection);
}

然后運(yùn)行


在這里插入圖片描述

運(yùn)行成功。
附上一個(gè)比較全面的配置文件技掏。

#連接設(shè)置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=

#<!-- 初始化連接 -->
initialSize=10

#最大連接數(shù)量
maxActive=50

#<!-- 最大空閑連接 -->
maxIdle=20

#<!-- 最小空閑連接 -->
minIdle=5

#<!-- 超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒 -->
maxWait=60000


#JDBC驅(qū)動(dòng)建立連接時(shí)附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;] 
#注意:"user" 與 "password" 兩個(gè)屬性會(huì)被明確地傳遞铃将,因此這里不需要包含他們。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由連接池所創(chuàng)建的連接的自動(dòng)提交(auto-commit)狀態(tài)哑梳。
defaultAutoCommit=true

#driver default 指定由連接池所創(chuàng)建的連接的事務(wù)級(jí)別(TransactionIsolation)劲阎。
#可用值為下列之一:(詳情可見(jiàn)javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
2涧衙、C3P0數(shù)據(jù)庫(kù)連接池

jar包下載地址:https://sourceforge.net/projects/c3p0/
官網(wǎng)地址:https://www.mchange.com/projects/c3p0/
官網(wǎng)里面也有下載入口哪工,和數(shù)據(jù)庫(kù)連接池的使用教程。
官網(wǎng)的文檔教程十分詳細(xì)弧哎,所以也就不過(guò)多贅述了雁比。
直接上案例。
編寫測(cè)試代碼

@Test
public void demo1() throws Exception{
    //創(chuàng)建一個(gè)連接池
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    //設(shè)置四個(gè)參數(shù)
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    dataSource.setJdbcUrl("jdbc:mysql:///test");
    dataSource.setUser("root");
    dataSource.setPassword("123456");
    
    Connection connection = dataSource.getConnection();
    String sql = "select * from account";
    PreparedStatement stmt = connection.prepareStatement(sql);
    ResultSet set = stmt.executeQuery();
    while(set.next()){
        System.out.println(set.getString("name"));
    }
    JDBCUtils.release(stmt, connection);
}

需要注意的是撤嫩,如果運(yùn)行時(shí)報(bào)ClassNotFoundExecption異常偎捎,說(shuō)明你的jar包版本是c3p0-0.9.2之后的,該版本之后的版本還需要添加一個(gè)輔助包序攘,mchange-commons-java-0.2.3.4.jar茴她。
這是jar包的下載地址。鏈接:https://pan.baidu.com/s/17o0s92Us-UPQPJFeJjpOzQ
提取碼:lt2v
復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤手機(jī)App程奠,操作更方便哦

同樣地丈牢,用配置文件實(shí)現(xiàn)一下。
在src目錄新建文件c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///test</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        
        <property name="automaticTestTable">con_test</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>

這是直接從官方文檔上復(fù)制下來(lái)的瞄沙。然后加上了數(shù)據(jù)庫(kù)配置所需要的四個(gè)參數(shù)己沛。
然后編寫測(cè)試代碼

@Test
public void demo2() throws Exception{
    //使用c3p0配置文件
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    Connection connection = dataSource.getConnection();
    String sql = "select * from account";
    PreparedStatement stmt = connection.prepareStatement(sql);
    ResultSet set = stmt.executeQuery();
    while(set.next()){
        System.out.println(set.getString("name"));
    }
    JDBCUtils.release(stmt, connection);
}

注意,c3p0數(shù)據(jù)庫(kù)連接池是不需要自己手動(dòng)加載配置文件的距境,c3p0非常的人性化申尼,這一步已經(jīng)被封裝好了。創(chuàng)建ComboPooledDataSource對(duì)象后直接調(diào)用getConnection()方法即可獲得連接垫桂。前提是你的配置文件名字必須為c3p0-config.xml师幕,且該文件必須放在src目錄下。至于其它的一些配置信息诬滩,在文檔都有講解霹粥,大家可以自行閱讀學(xué)習(xí)灭将。

創(chuàng)建ComboPooledDataSource 對(duì)象有兩種方法,調(diào)用無(wú)參構(gòu)造使用的是配置文件中默認(rèn)的配置后控,而如果調(diào)用有參構(gòu)造宗侦,將配置文件中<name-config></name-config>標(biāo)簽的name屬性值傳入,將會(huì)使用該標(biāo)簽內(nèi)的配置信息忆蚀。

3、Tomcat內(nèi)置的連接池

需要知道的是姑裂,Tomcat內(nèi)容連接池就是DBCP馋袜。
我們知道,將web工程部署到Tomcat有三種方式:

  • 配置server.xml舶斧,添加<Context></Context>標(biāo)簽
  • 配置獨(dú)立的xml文件欣鳖,添加<Context></Context>標(biāo)簽
  • 直接將網(wǎng)站目錄復(fù)制到Tomcat的webapps目錄下

任何工程要能夠在Tomcat運(yùn)行,都需要一個(gè)虛擬目錄茴厉。虛擬目錄指的是什么泽台?指的就是Context元素。當(dāng)我們需要使用連接池時(shí)矾缓,就需要對(duì)Context作如下配置

<Context path="/DBTest" docBase="DBTest"
        debug="5" reloadable="true" crossContext="true">

    <!-- maxActive: Maximum number of dB connections in pool. Make sure you
         configure your mysqld max_connections large enough to handle
         all of your db connections. Set to -1 for no limit.
         -->

    <!-- maxIdle: Maximum number of idle dB connections to retain in pool.
         Set to -1 for no limit.  See also the DBCP documentation on this
         and the minEvictableIdleTimeMillis configuration parameter.
         -->

    <!-- maxWait: Maximum time to wait for a dB connection to become available
         in ms, in this example 10 seconds. An Exception is thrown if
         this timeout is exceeded.  Set to -1 to wait indefinitely.
         -->

    <!-- username and password: MySQL dB username and password for dB connections  -->

    <!-- driverClassName: Class name for the old mm.mysql JDBC driver is
         org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
         Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
         -->
    
    <!-- url: The JDBC connection url for connecting to your MySQL dB.
         -->

  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>

</Context>

這是從官網(wǎng)上復(fù)制下來(lái)的怀酷。
那么該在哪里配置Context元素呢?
配置Context元素的三個(gè)位置:

  • Tomcat安裝目錄/conf/context.xml(如果將連接池配置到了該文件嗜闻,就會(huì)對(duì)當(dāng)前Tomcat內(nèi)部所有的虛擬主機(jī)中的任何工程都有效)
  • Tomcat安裝目錄/conf/Catalina/虛擬主機(jī)目錄/context.xml(如果將連接池配置到了該文件蜕依,就會(huì)對(duì)當(dāng)前虛擬主機(jī)的任何工程都有效)
  • web工程的根目錄/META-INF/context.xml(如果將連接池配置到了該文件,將只對(duì)當(dāng)前工程有效)

接下來(lái)演示一下第三種配置方式
在WebRoot下的META-INF文件夾中新建一個(gè)文件context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/DBTest" docBase="DBTest" debug="5" reloadable="true"
    crossContext="true">

    <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000" username="root"
        password="123456" driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/test" />

</Context>

context.xml文件編寫完成后琉雳,在啟動(dòng)Tomcat服務(wù)器的時(shí)候样眠,Tomcat會(huì)去自動(dòng)加載該文件,并創(chuàng)建數(shù)據(jù)庫(kù)連接池翠肘,存放在Tomcat容器中檐束。此時(shí)我們將可以使用JNDI技術(shù)去訪問(wèn)數(shù)據(jù)庫(kù)連接池。
不了解JNDI技術(shù)的童鞋束倍,我們可以在這里略微提一下

JNDI(Java Naming and Directory Interface)被丧,Java命名和目錄接口,它對(duì)應(yīng)于J2SE中的javax.naming包肌幽,
這套API的主要作用在于:它可以把Java對(duì)象放在一個(gè)容器中(支持JNDI容器 Tomcat)晚碾,并為容器中的java對(duì)象取一個(gè)名稱,以后程序想獲得Java對(duì)象喂急,只需通過(guò)名稱檢索即可格嘁。
其核心API為Context,它代表JNDI容器廊移,其lookup方法為檢索容器中對(duì)應(yīng)名稱的對(duì)象糕簿。

注意事項(xiàng):
Tomcat創(chuàng)建連接池探入,與數(shù)據(jù)庫(kù)連接需要數(shù)據(jù)庫(kù)驅(qū)動(dòng),要將mysql.jar復(fù)制到Tomcat目錄下的lib文件夾中懂诗。
Java程序要想通過(guò)JNDI訪問(wèn)對(duì)象蜂嗽,就必須運(yùn)行在同一個(gè)JNDI容器中。也就是說(shuō)殃恒,該Java程序必須運(yùn)行在Tomcat內(nèi)部植旧,所以使用JNDI的程序一般是Servlet或JSP。

演示一下离唐。
在項(xiàng)目中新建一個(gè)Servlet文件為TomcatServlet

/**
 * 在該程序中病附,通過(guò)JNDI訪問(wèn)Tomcat內(nèi)部的連接池
 * @author Administrator
 *
 */
public class TomcatServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            //創(chuàng)建一個(gè)檢索的對(duì)象
            Context initCtx = new InitialContext();
            //默認(rèn)查找頂級(jí)的Java名稱串    這是固定的:java:comp/env
            Context envCtx = (Context) initCtx.lookup("java:comp/env");
            //根據(jù)設(shè)置名稱查找連接池對(duì)象
            DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
            //獲得連接池中的一個(gè)連接
            Connection conn = ds.getConnection();
            String sql = "select * from account";
            PreparedStatement stmt = conn.prepareStatement(sql);
            ResultSet set = stmt.executeQuery();
            while(set.next()){
                System.out.println(set.getString("name"));
            }
            JDBCUtils.release(stmt, conn);
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

千萬(wàn)別忘了數(shù)據(jù)庫(kù)驅(qū)動(dòng),將mysql-connector-java-5.1.47-bin.jar復(fù)制到Tomcat安裝目錄下的lib文件夾中,然后在MyEclipse中部署項(xiàng)目并運(yùn)行亥鬓。接著在瀏覽器中訪問(wèn)Servlet程序


在這里插入圖片描述

說(shuō)明查詢成功完沪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嵌戈,隨后出現(xiàn)的幾起案子覆积,更是在濱河造成了極大的恐慌,老刑警劉巖熟呛,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宽档,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惰拱,警方通過(guò)查閱死者的電腦和手機(jī)雌贱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)偿短,“玉大人欣孤,你說(shuō)我怎么就攤上這事∥舳海” “怎么了降传?”我有些...
    開(kāi)封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)勾怒。 經(jīng)常有香客問(wèn)我婆排,道長(zhǎng),這世上最難降的妖魔是什么笔链? 我笑而不...
    開(kāi)封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任段只,我火速辦了婚禮,結(jié)果婚禮上鉴扫,老公的妹妹穿的比我還像新娘赞枕。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布炕婶。 她就那樣靜靜地躺著姐赡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柠掂。 梳的紋絲不亂的頭發(fā)上项滑,一...
    開(kāi)封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音涯贞,去河邊找鬼枪狂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宋渔,可吹牛的內(nèi)容都是我干的摘完。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼傻谁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了列粪?” 一聲冷哼從身側(cè)響起审磁,我...
    開(kāi)封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎岂座,沒(méi)想到半個(gè)月后态蒂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡费什,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年钾恢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸳址。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瘩蚪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出稿黍,到底是詐尸還是另有隱情疹瘦,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布巡球,位于F島的核電站言沐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酣栈。R本人自食惡果不足惜险胰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望矿筝。 院中可真熱鬧起便,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至奖年,卻和暖如春细诸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背陋守。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工讯屈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涡上。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓甲锡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親中燥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寇甸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容