最近在研究JAVA的數據源連接方式,學習的時候發現了一位同行寫的文章,轉載過來,留作記錄!
一、問題引入
在java程序中,需要訪問數據庫,做增刪改查等相關操作。如何訪問數據庫,做數據庫的相關操作呢?
二、Java連接數據庫方法概述
java.sql提供了一些接口和類,用於支持數據庫增刪改查等相關的操作。該jar包定義了java訪問各種不同數據庫(mysql,oracle,sqlserver。。。。。)的統一接口和標准。同時,各個數據庫廠商都提供了該jar包中定義的各個接口的實現類,用於具體實現本廠數據庫的增刪改查操作,即稱之為“數據庫驅動jdbc driver”。例如mysql的數據庫驅動為:com.mysql.jdbc.driver;oracle的數據庫驅動為:oracle.jdbc.driver.oracledriver。
在java程序中訪問數據庫,做數據庫連接時,可以采用兩種方式:
1、使用java.sql API
利用該包提供的各種接口和類直接訪問數據庫。
2、使用數據庫連接池
目前存在多個開源的java數據庫連接池,這些連接池都是在java.sql基礎上編寫而成。
Ø 該連接池的解決的問題是:
當使用java.sql中提供的api創 建數據庫連接時候,需要耗費很大的資源,要進行用戶名密碼數據庫連接驗證等,即耗費資源也耗費時間。如果在程序中,每次需要訪問數據庫時候,都進行數據庫 連接,那么勢必會造成性能低下;同時,如果用戶失誤忘記釋放數據庫連接,會導致資源的浪費等。而數據庫連接池就是解決該問題,通過管理連接池中的多個連接 對象(connection),實現connection重復利用。從而,大大提高了數據庫連接方面的性能。
Ø 該連接池的功能是:
負責創建,管理,釋放,分配數據庫連接即(connection)。首先,負責創建相應數目的數據庫連接對象(connection)對象,並存放到數據庫連接池(connect pool)中。當用戶請求數據庫連接時,該連接池負責分配某個處於空閑狀態的數據庫連接對象;當用戶發出釋放該數據庫連接時,該連接池負責將該連接對象重新設置為空閑狀態,以便被別的請求重復利用。同時;數據庫連接池負責檢查(空閑時間>最大空閑時間)的數據庫連接,並釋放。
Ø 連接池主要參數介紹
最小連接數:初始化時,系統將負責創建該數目的connection放入連接池中。
最大連接數:系統允許創建connection的最大數值。當系統請求連接時候,且連接池中不存在空閑的連接:如果connection總數未超過最大連接數,那么連接池負責創建新的connection對象,並返回該對象;如果connection總數已經到達該最大連接數,那么連接池將用戶請求轉入等待隊列。
三、常用的數據庫連接池
1、 JNDI
2、 C3p0
3、 Apache 的Jakarta DBCP
4、 BoneCP
其中,sping框架依賴的第三方使用了c3p0和dbcp兩種方式;而bonecp號稱是速度最快的數據庫連接池。JNDI方式創建實現的datasource是真正實現了javax.sql.datasource;其他的三種方式都不是。下面的列表,列出了幾種方式的區別和不同:
序號 |
連接池名稱 |
依賴的jar包 |
實現的datasource類 |
備注 |
1 |
JNDI |
該數據源是由相應的web服務器(例如:tomcat,weblogic,websphere)負責初始化,創建,管理。程序中不需要引入特別的jar包。 |
Javax.sql.datasource |
|
2 |
C3P0 |
c3p0-0.9.xxx.jar |
com.mchange.v2.c3p0.ComboPooledDataSource |
|
3 |
DBCP |
commons-dbcp.jar,commons-pool.jar |
org.apache.commons.dbcp.BasicDataSource |
|
4 |
BoneCP
|
bonecp-0.6.5.jar · google-collections-1.0.jar · slf4j-api-1.5.11.jar · slf4j-log4j12-1.5.11.jar ·log4j-1.2.15.jar
|
BoneCPDataSource |
|
備注:以上幾種方式的數據庫連接池的配置參數大同小異,略有差別;其參數的配置,既可以通過配置文件的方式配置,也可以通過硬編碼的方式配置。
四、分別列出幾種連接池的編碼例子
(所有的例子均可以參考D:\work\qsyworkspace2\jdbctest項目)
1、 使用java.sql API直接訪問數據庫
詳細請參考javasql.java文件。
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/editortest";
String user="root";
String password="123456";
Connection cn=DriverManager.getConnection(url, user, password);
Statement st=cn.createStatement();
String sql="select * from artical where id=1";
ResultSet rs=st.executeQuery(sql);
while(rs.next()){
System.out.println("1:"+rs.getString(1));
System.out.println("2:"+rs.getString(2));
System.out.println("3:"+rs.getString(3));
System.out.println("4:"+rs.getString(4));
}
2、 使用JNDI方式
這種方式,是由web服務器,實現了java.sql.datasource。由web服務器負責初始化數據源,創建connection,分配,管理connection。由於本身是由web服務器實現的功能,因此不需要在項目project中引入特別的jar包,但是需要在服務器的某些配置文件中增加相關的配置。下面,以tomcat服務器為例,講述這種方式的使用。
(1)、修改tomcat的conf下的context.xml文件,增加Resource的配置的支持。
(2)、由於數據源是由tomcat負責創建,所以需要的jdbc驅動應該放到tomcat的lib路徑下。
(3)、編寫使用java代碼,並放在tomcat環境下使用,如下:
public void jnditest(){
// TODO Auto-generated method stub
try {
Context initcontext=new InitialContext();
Context context=(Context) initcontext.lookup("java:comp/env");
DataSource datasource=(DataSource)context.lookup("jdbc/editortest");
Connection cn=datasource.getConnection();
Statement st=cn.createStatement();
String sql="select * from artical where id=1";
ResultSet rs=st.executeQuery(sql);
while(rs.next()){
System.out.println("1:"+rs.getString(1));
System.out.println("2:"+rs.getString(2));
System.out.println("3:"+rs.getString(3));
System.out.println("4:"+rs.getString(4));
}
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
(4)、詳情參考jndisql。Java文件,以及index.jsp。
注意:該測試不能在main方法中測試;可以寫一個jsp在tomcat環境中測試。因為:java單元的環境是jdk;而jsp的環境卻是tomcat;數據連接池是在tomcat中配置的,所以能正常運行的,但java測試的環境只有jdk,所以在引用數據連接池時就時出現找不到環境的錯誤。
使用環境:當使用weblogic或者websphere等高級的web服務器的時候,可以考慮使用這種方式提高性能。
3、 使用C3p0方式
C3P0是開源的數據庫連接組件,支持創建數據庫連接池,管理connection等功能。使用該種方式做數據庫連接時候,需要導入c3p0-0.9.1.2.jar。
同時,關於數據庫連接的具體參數,例如:url,username,password,最小連接數,最大連接數。。。。。等信息既可以在xml配置文件中配置,也可以通過程序編碼方式創建。Spring支持c3p0的數據庫連接池方式,因此在spring環境中使用時,支持在applicationcontext.xml文件中配置。另外,由於數據庫連接池在整個project中針對某個數據庫而言是單例的,所以,即使通過編碼的方式創建,那么要保證其單實例特性。如果存在多個,那么必然會導致性能低下。
下面,列出通過程序編碼方式使用c3p0數據庫連接池的方式。
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/editortest");
ds.setUser("root");
ds.setPassword("123456");
ds.setMaxPoolSize(20);
ds.setInitialPoolSize(10);
ds.setMaxIdleTime(2000);
Connection cn=ds.getConnection();
Statement st=cn.createStatement();
String sql="select * from artical where id=1";
ResultSet rs=st.executeQuery(sql);
while(rs.next()){
System.out.println("1:"+rs.getString(1));
System.out.println("2:"+rs.getString(2));
System.out.println("3:"+rs.getString(3));
System.out.println("4:"+rs.getString(4));
}
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
備注:通常使用方式,都是通過配置文件配置,幾乎不會用到這種硬編碼方式。在此,只是簡單介紹C3P0的使用方式。詳情,可以參考c3p0test.java。
4、 使用dbcp方式
DBCP方式,是apache提供的數據源連接池方式,支持數據庫連接池創建,管理connection等功能。使用環境,需要導入commons-dbcp.jar 和 commons-pool.jar兩個jar包。上面提到的JNDI方式,其實質實用的就是dbcp數據源;只是他是通過在web服務器上做配置,由web服務器負責創建該數據源。
同樣的,dbcp數據源也支持xml配置文件和硬編碼兩種方式。通常使用方式,都是通過配置文件配置,幾乎不會使用硬編碼方式。下面簡單介紹dbcp方式的編碼:
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/editortest");
ds.setUsername("root");
ds.setPassword("123456");
ds.setMaxIdle(20);
ds.setInitialSize(10);
ds.setMaxActive(2000);
try {
Connection cn=ds.getConnection();
Statement st=cn.createStatement();
String sql="select * from artical where id=1";
ResultSet rs=st.executeQuery(sql);
while(rs.next()){
System.out.println("1:"+rs.getString(1));
System.out.println("2:"+rs.getString(2));
System.out.println("3:"+rs.getString(3));
System.out.println("4:"+rs.getString(4));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
5、 使用BoneCP方式。
BoneCP是快速高效的數據庫連接池組件,據說性能上目前是最好得,比C3P0和DBCP快25倍。使用該組件,需要導入bonecp-0.6.5.jar,google-collections-1.0.jar,slf4j-api-1.5.11.jar,slf4j-log4j12-1.5.11.jar,log4j-1.2.15.jar。
下面,簡單列出編碼方式的使用,做簡單的了解。
BoneCPDataSource ds = new BoneCPDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/editortest");
ds.setUsername("root");
ds.setPassword("123456");
try {
Connection cn = ds.getConnection();
Statement st = cn.createStatement();
String sql = "select * from artical where id=1";
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
System.out.println("1:" + rs.getString(1));
System.out.println("2:" + rs.getString(2));
System.out.println("3:" + rs.getString(3));
System.out.println("4:" + rs.getString(4));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
總結:以上,介紹了幾種常用的數據源連接池;這幾種連接池在使用過程,即支持硬編碼的方式,也支持配置文件的配置方式;在正式實用的時候,應該盡量使用配置的方式,便於維護和管理。硬編碼的方式,可以做為測試使用。同時,spring框架,通過他自己的方式集成上述幾種數據源,理論上來說,都支持。各個數據源連接池都有一些公有的屬性,因為他們都是從javax.sql.datasource繼 承而來,而且都有最大連接數,初始化連接數等概念。同時,他們又分別有各自不同的屬性,做了擴展。這里只是簡單的介紹,在實際使用中,想要實現高性能的數 據庫連接池管理,還需要深入研究每種方式的連接屬性配置;例如:根據實際需要,設置合適的最小連接數和最大連接數,等待時間等。
五、Java(x).sql直接操作數據庫與各個開源數據源(datasource)關系
當使用JDK提供的java(x).sql包中的類訪問數據庫時候,基本上用到的就是drivermanager,connection,statement,resultset。其中drivermanger是類,他調用相應的驅動(即各個數據庫廠商提供的驅動)中的方法生成connection對象。Connection是接口,在各個數據庫廠商提供的數據庫驅動中,都實現了該接口。例如:當使用com.mysql.jdbc.driver時候,生成的connection即為com.mysql.jdbc.Connection對象。
Javax.sql包中定義了接口datasource,統一規定了作為數據源連接池必須提供的方法和屬性等。各個數據源組件中提供的datasource都實現了該接口。當通過數據源連接池的方式獲取connnection的時候,同樣的,各個數據源組件也都提供(實現了java.sql.connection)接口的類。
更為具體的細節,可以參考jdk文檔中關於java(x).sql包中相關類和接口的描述;參考開源數據源連接池組件的相關源碼(例如C3P0);參考相關的數據庫驅動。
六、附錄:Java開源的數據庫連接池
在Java中開源的數據庫連接池有以下幾種 :
1, C3P0 C3P0是一個開放源代碼的JDBC連接池,它在lib目錄中與Hibernate一起發布,包括了實現jdbc3和jdbc2擴展規范說明的Connection 和Statement 池的DataSources 對象。
2,Proxool 這是一個Java SQL Driver驅動程序,提供了對你選擇的其它類型的驅動程序的連接池封裝。可以非常簡單的移植到現存的代碼中。完全可配置。快速,成熟,健壯。可以透明地為你現存的JDBC驅動程序增加連接池功能。
3,Jakarta DBCP DBCP是一個依賴Jakarta commons-pool對象池機制的數據庫連接池.DBCP可以直接的在應用程序用使用。
4,DDConnectionBroker DDConnectionBroker是一個簡單,輕量級的數據庫連接池。
5,DBPool DBPool是一個高效的易配置的數據庫連接池。它除了支持連接池應有的功能之外,還包括了一個對象池使你能夠開發一個滿足自已需求的數據庫連接池。
6,XAPool XAPool是一個XA數據庫連接池。它實現了javax.sql.XADataSource並提供了連接池工具。
7,Primrose Primrose是一個Java開發的數據庫連接池。當前支持的容器包括Tomcat4&5,Resin3與JBoss3.它同樣也有一個獨立的版本可以在應用程序中使用而不必運行在容器中。Primrose通過一個web接口來控制SQL處理的追蹤,配置,動態池管理。在重負荷的情況下可進行連接請求隊列處理。
8,SmartPool SmartPool是一個連接池組件,它模仿應用服務器對象池的特性。SmartPool能夠解決一些臨界問題如連接泄漏(connection leaks),連接阻塞,打開的JDBC對象如Statements,PreparedStatements等. SmartPool的特性包括支持多個pools,自動關閉相關聯的JDBC對象, 在所設定time-outs之后察覺連接泄漏,追蹤連接使用情況, 強制啟用最近最少用到的連接,把SmartPool"包裝"成現存的一個pool等。
9,MiniConnectionPoolManager MiniConnectionPoolManager是一個輕量級JDBC數據庫連接池。它只需要Java1.5(或更高)並且沒有依賴第三方包。
10,BoneCP BoneCP是一個快速,開源的數據庫連接池。幫你管理數據連接讓你的應用程序能更快速地訪問數據庫。比C3P0/DBCP連接池快25倍。