數(shù)據(jù)庫連接的建立及關(guān)閉是一種極耗系統(tǒng)資源的操作,尤其是在多層結(jié)構(gòu)的應(yīng)用環(huán)境中,這種資源的耗費(fèi)對系統(tǒng)性能影響尤為明顯。在工作時做系統(tǒng)優(yōu)化對這方面的很有體會,相同功能的查詢語句,由于打開關(guān)閉數(shù)據(jù)庫連接的次數(shù)不同導(dǎo)致兩個查詢語句耗費(fèi)的時間差別很大。一個數(shù)據(jù)庫連接對象均對應(yīng)一個物理數(shù)據(jù)庫連接,每次操作都打開一個物理連接,使用完后立即關(guān)閉連接。頻繁地打開、關(guān)閉連接將會造成系統(tǒng)性能低下。雖然寫高性能的sql語句能夠減少訪問數(shù)據(jù)庫的次數(shù),但是也不能完全規(guī)避平凡操作數(shù)據(jù)庫的的行為,因為有時候我們訪問量大,就會伴有多線程和高并發(fā),這時候我們就該考慮還有什么辦法能提高系統(tǒng)的性能了。辦法總比問題多,數(shù)據(jù)庫連接池的使用幫我們大大的降低了平凡的開關(guān)數(shù)據(jù)庫。
數(shù)據(jù)庫連接池的解決方案是:當(dāng)應(yīng)用程序啟動時,系統(tǒng)主動建立足夠的數(shù)據(jù)庫連接,并將這些連接組成一個連接池。每次應(yīng)用程序請求數(shù)據(jù)庫連接時,無須重新打開連接,而是從池中取出已有的連接使用,使用完后,雖然使用了close()關(guān)閉連接,但是沒有真正關(guān)閉數(shù)據(jù)庫連接,而是直接將連接歸還給了連接池。通過使用連接池,將大大提高程序運(yùn)行效率。
1、數(shù)據(jù)庫連接池是Connection對象的工廠。數(shù)據(jù)庫連接池的常用參數(shù)有如下:
● 數(shù)據(jù)庫的初始連接數(shù)
● 連接池的最大連接數(shù)
● 連接池的最小連接數(shù)
● 連接池的每次增加的容量
... ...
2、JDBC的數(shù)據(jù)庫連接池使用javax.sql.DataSource來表示,DataSource只是一個接口,該接口通常由商用服務(wù)器(如webLogic、WebSphere)等提供實現(xiàn),也有一些開源組織提供實現(xiàn)(如DBCP和 C3P0等)。商用的我就不多介紹了,一般都是根據(jù)提示配置一下就可以使用了。下面簡單的說一下上面這兩個開源的常用配置屬性,真用到了還可以參考文檔進(jìn)行詳細(xì)的配置。
3、DBCP(DataBaseconnection pool),數(shù)據(jù)庫連接池。是apache上的一個java連接池,也是tomcat使用的連接池組件。單獨使用dbcp需要3個包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立數(shù)據(jù)庫連接是一個非常耗時耗資源的行為,所以通過連接池預(yù)先同數(shù)據(jù)庫建立一些連接,放在內(nèi)存中,應(yīng)用程序需要建立數(shù)據(jù)庫連接時直接到連接池中申請一個就行,用完后再放回去。下面是一些常用的設(shè)置屬性
//創(chuàng)建數(shù)據(jù)源對象 BasicDataSource ds = new BasicDataSource(); //設(shè)置連接池所需的驅(qū)動(以MySql為例) ds.SetDriverClassName("com.mysql.jdbc.Driver"); //設(shè)置連接數(shù)據(jù)庫的url ds.setUrl("jdbc:mysql://localhost:3306/javaee"); //設(shè)置連接數(shù)據(jù)庫的用戶名 ds.setUsername("root"); //連接數(shù)據(jù)庫的密碼 ds.setPassword("root"); //設(shè)置連接池的初始連接數(shù) ds.setInitia1Size(5); //設(shè)置連接池最多可有有多少個活動連接數(shù) ds.setMaxActive(10); //設(shè)置連接池中最少有2個空閑的連接 ds.setMinIdle(2); //通過數(shù)據(jù)源獲取連接 Connection conn = ds.getConnection(); //釋放數(shù)據(jù)庫連接 Conn.close(); |
數(shù)據(jù)源和數(shù)據(jù)庫連接不同,數(shù)據(jù)源無須創(chuàng)建多個,它是產(chǎn)生數(shù)據(jù)庫連接的工廠,因此整個應(yīng)用只需要一個數(shù)據(jù)源即可。建議把上面程序中的ds設(shè)置成static成員變最,并且在應(yīng)用開始時立即初始化數(shù)據(jù)源對象,程序中所有需要獲取數(shù)據(jù)庫連接的地方直接訪問該ds對象,并獲取數(shù)據(jù)庫連接即可,當(dāng)數(shù)據(jù)庫訪問結(jié)束后,程序還是像以前一樣關(guān)閉數(shù)據(jù)庫連接即可。
4、C3P0是一個開源的JDBC連接池,它實現(xiàn)了數(shù)據(jù)源和JNDI綁定,支持JDBC3規(guī)范和JDBC2的標(biāo)準(zhǔn)擴(kuò)展。C3P0不僅可以自動清理不在使用的Connection,還可以自動清理Statement和ResultSet。目前使用它的開源框架有Hibernate,Spring等。
//創(chuàng)建連接池對象 ComboPooledDataSource ds = new ComboPooledDataSource(); //設(shè)置連接池所需的驅(qū)動(以MySql為例) ds.SetDriverClass("com.mysql.jdbc.Driver"); //設(shè)置連接數(shù)據(jù)庫的url ds.setJdbcUrl("jdbc:mysql://localhost:3306/javaee"); //設(shè)置連接數(shù)據(jù)庫的用戶名 ds.setUser("root"); //連接數(shù)據(jù)庫的密碼 ds.setPassword("root"); //設(shè)置連接池的最大連接數(shù) ds.setMaxPoolSize(20); //設(shè)置連接池中最少連接數(shù) ds.setMinPoolSize(2); //設(shè)置連接池的初始連接數(shù) ds.setInitia1PoolSize(5); //設(shè)置連接池的緩存Statement的最大數(shù) ds.setMaxStatements(100); //獲取連接 Connection conn = ds.getConnection(); //釋放數(shù)據(jù)庫連接 Conn.close(); |
看到了數(shù)據(jù)庫連接池的使用,我們是不是很快就會想到多線程編程里是不是也有線程池幫我們解決一些性能問題呢?答案肯定的,想到了就去嘗試吧......