作者:baggio785
日期:2006-4-24
關鍵詞:DataSource(數據源),Tomcat
,連接池
前言
本文根據實例詳細介紹了如何在tomcat中配置數據源。網上此類文章很多,但是基本都是雷同的,而且對一些特殊問題以及原理并未詳細闡述,所以想根據自己的實際經驗,并結合例子寫一篇詳細的文章。
本文是偶的一些拙見,有不正確的地方請大家多多評論指正
。
開發環境
本文的環境:JDK1.4.2,TOMCAT5.0.28,Oracle9i
JDBC簡介
提到數據源,那就不能不說JDBC。JDBC是Java Database Connectivity的縮寫。在java.sql包中提供了JDBC API,定義了訪問數據庫的接口和類。但是JDBC API不能直接訪問數據庫,必須依賴于數據庫廠商提供的JDBC驅動程序,即JDBC DRIVER。
Java.sql
中常用的接口和類如下:
?????? Driver
接口和
DriverManager
類
?????? Connection
?????? Statement
?????? PreparedSataement
?????? ResultSet
?
1???? Driver
接口和
DriverManager
類
?????? DriverManager 類用來建立和數據庫的連接以及管理 JDBC 驅動程序,常用方法如下:
?????? DriverManager 類用來建立和數據庫的連接以及管理 JDBC 驅動程序,常用方法如下:
方法 | 描述 |
registerDriver(Driver driver) | 在 DriverManager 中注冊 JDBC 驅動程序 |
getConnection(String url,String user,String pwd) | 建立和數據庫的連接,返回 Connection 對象 |
setLoginTimeOut(int seconds) | 設定等待數據庫連接的最長時間 |
setLogWriter(PrintWriter out) | 設定輸入數據庫日至的 PrintWriter 對象 |
2???? Connection
?????? Connection 代表和數據庫的連接,其常用方法如下:
?????? Connection 代表和數據庫的連接,其常用方法如下:
方法 | 描述 |
getMetaData() | 返回數據庫的 MetaData 數據。 MetaData 數據包含了數據庫的相關信息,例如當前數據庫連接的用戶名、使用的 JDBC 驅動程序、數據庫允許的最大連接數、數據庫的版本等等。 |
createStatement() | 創建并返回 Statement 對象 |
PrepareStatement(String sql) | 創建并返回 prepareStatement 對象 |
3
???? Statement
?????? Statement 用來執行靜態 sql 語句。例如,對于 insert 、 update 、 delete 語句,調用 executeUpdate(String sql) 方法,而 select 語句可以調用 executeQuery(String sql) 方法, executeQuery(String sql) 方法返回 ResultSet 對象。
?????? Statement 用來執行靜態 sql 語句。例如,對于 insert 、 update 、 delete 語句,調用 executeUpdate(String sql) 方法,而 select 語句可以調用 executeQuery(String sql) 方法, executeQuery(String sql) 方法返回 ResultSet 對象。
4
????
PrepareStatement
?? PrepareStatement 用于執行動態的 sql 語句,即允許 sql 語句中包含參數。使用方法為:
?? String sql = “select col1 from tablename where col2=? And col3=?”;
?? PrepareStatement perpStmt = conn.preparestatement(sql);
?? perpStmt.setstring(1,col2Value);
????? perpStmt.setFloat(2,col3Value);
????? ResultSet rs = perpStmt.executeQuery();
?? PrepareStatement 用于執行動態的 sql 語句,即允許 sql 語句中包含參數。使用方法為:
?? String sql = “select col1 from tablename where col2=? And col3=?”;
?? PrepareStatement perpStmt = conn.preparestatement(sql);
?? perpStmt.setstring(1,col2Value);
????? perpStmt.setFloat(2,col3Value);
????? ResultSet rs = perpStmt.executeQuery();
5
????
ResultSet
ResultSet 用來表示 select 語句查詢得到的記錄集,一個 StateMent 對象在同一時刻只能打開一個 ResultSet 對象。通過 ResultSet 的 getXXX() 方法來得到字段值。 ResultSet 提供了 getString() 、 getFloat() 、 getInt() 等方法。可以通過字段的序號或者字段的名字來制定獲取某個字段的值。例如:在上例中 getString(0),getString(col1) 都可以獲得字段 col1 的值。
ResultSet 用來表示 select 語句查詢得到的記錄集,一個 StateMent 對象在同一時刻只能打開一個 ResultSet 對象。通過 ResultSet 的 getXXX() 方法來得到字段值。 ResultSet 提供了 getString() 、 getFloat() 、 getInt() 等方法。可以通過字段的序號或者字段的名字來制定獲取某個字段的值。例如:在上例中 getString(0),getString(col1) 都可以獲得字段 col1 的值。
事務處理
在實際應用中,我們會遇到同時提交多個 sql 語句,這些 sql 語句要么全部成功,要么全部失敗,如果其中一條提交失敗,則必須撤銷整個事務。為此, Connection 類提供了 3 個控制事務的方法:
方法 | 描述 |
setAutoCommit(boolen autoCommit) | 設置是否自動提交事務,默認為自動提交 。 |
commit() | 提交事務 |
rollback() | 撤銷事務 |
參考例子:
try{
conn.SetautoCommit(false);
stmt = conn.createstatement();
stmt.executeUpdate(“delete form table1 where col1=1”); stmt.eecuteUpdate(“delete from table2 where col2=1”);
conn.comm.it();
}catch(Exception e){
?????? e.printStackTrace;
try{
?????? ?????? conn.rollback();
} catch(Exception e1){
?????? e1.printStackTrace;
}
}
|
通過一個
JSP
例子來訪問
oracle
數據庫:
<%@ page import=”java.util.*”>
<%@ page import=”java.sql.*”>
<%
try{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//
加載
oracle
驅動程序
Class.forName(“oracle.jdbc.driver.OracleDriver.”);
//
注冊
oracle
驅動程序
DriverManager.regidterDriver(new oracle.jdbc.driver.OracleDriver());
//
建立數據庫連接
conn=DriverManager.getConnection(“jdbc:oracle:thin:@your db ip:your db port:sid”,dbuser,dbpassword);
stmt = conn.createStatement();
rs = stmt.executeQuery(“select * from tablename”);
while(rs.next){
?????? out.print(rs.getstring(“colname”));
}
}catch(Exception e){
}
finally{
rs.close();
stmt.close();
conn.close();
}
%>
|
數據源簡介
JDBC2.0 提供了 javax.sql.DataSource 的接口,負責與數據庫建立連接,實際應用時不需要編寫連接數據庫代碼,直接從數據源獲得數據庫的連接。 Dataource 中事先建立了多個數據庫連接,這些數據庫連接保持在數據庫連接池中,當程序訪問數據庫時,只需要從連接池從取出空閑的連接,訪問數據庫結束,在將這些連接歸還給連接池。
DataSource
對象由容器(
Tomcat
)提供,不能使用創建實例的方法來生成
DataSource
對象,要采用
JAVA
的
JNDI
(
Java Nameing and Directory Interface
,
java
命名和目錄接口)來獲得
DataSource
對象的引用。(另有一種說法:“其實從技術上來說,數據源連接方式是不需要目錄服務的,我們同樣可以通過序列化數據源對象直接訪問文件系統。這點是需要明確的。”感興趣的朋友可以試試。)
JNDI
是一種將對象和名字綁定的技術,對象工廠負責生產出對象,這些對象都和唯一的名字相綁定。程序中可以通過這個名字來獲得對象的引用。
Tomcat
把
DataSource
作為一種可配置的
JNDI
資源來處理,生成
DataSource
對象的工廠為
org.apache.comm.ons.dbcp.BasicDataSourceFactory
。
?
配置數據源
配置數據源其實相當簡單:
<Resource name="jdbc/ JNDI
名字
"
?????????????? auth="Container"
?????????????? type="javax.sql.DataSource"/>
?<ResourceParams name="jdbc/JNDI
名字
">
??? <parameter>
?????<name>factory</name>
????? <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
??? </parameter>
??? <parameter>
????? <name>maxActive</name>
????? <value>100</value>
??? </parameter>
??? <parameter>
????? <name>maxIdle</name>
????? <value>30</value>
??? </parameter>
?
??? <parameter>
????? <name>maxWait</name>
????? <value>10000</value>
??? </parameter>
?
??? <parameter>
???? <name>username</name>
???? <value>
用戶名
</value>
??? </parameter>
??? <parameter>
???? <name>password</name>
???? <value>
密碼
</value>
??? </parameter>
?
??? <parameter>
?????? <name>driverClassName</name>
?????? <value>oracle.jdbc.driver.OracleDriver</value>
??? </parameter>
?
??? <parameter>
?? ???<name>url</name>
????? <value>jdbc:oracle:thin:@ip:
端口
:sid </value>
??? </parameter>
?</ResourceParams>
|
<Resource>
元素的屬性如下:
屬性 | 描述 |
name | 指定 Resource 的 JNDI 的名字 |
auth | 指定管理 Resource 的 Manager ,由兩個可選值: Container 和 Application 。 Container 表示由容器來創建和管理 Resource , Application 表示由 WEB 應用來創建和管理 Resource 。如果在 web application deployment descriptor 中使用 <resource-ref> ,這個屬性是必需的,如果使用 <resource-env-ref> ,這個屬性是可選的。 |
type | 指定 Resource 所屬的 java 類名 |
<ResourceParams>
元素的屬性如下:
屬性 | 描述 |
name | 指定 ResourceParams 的 JNDI 的名字,必須和 Resource 的 name 保持一致 |
factory | 指定生成 DataSource 對象的 factory 的類名 |
maxActive | 指定數據庫連接池中處于活動狀態的數據庫連接最大數目, 0 表示不受限制 |
maxIdle | 指定數據庫連接池中 處于 空閑狀態的數據庫連接的最大數目, 0 表示不受限制 |
maxWait | 指定數據庫連接池中的數據庫連接處于空閑狀態的最長時間(單位為毫秒),超過這一事件,將會拋出異常。 -1 表示可以無限期等待。 |
username | 指定連接數據庫的用戶名 |
password | 指定連接數據庫的密碼 |
driverClassName | 指定連接數據庫的 JDBC 驅動程序 |
url | 指定連接數據庫的 URL |
其他文章說以上配置就OK了,對于web.xml的配置可有可無,其實不是這樣子的。如果在web應用中訪問了由Servlet容器管理的某個JNDI Resource,則必須在web.xml中聲明對這個JNDI Resource的引用。表示資源引用的元素為<resource-ref>,該元素加在<wepapp></ wepapp >中。
<resource-ref>
???? <descryiption>DB Connection</descryiption>
<res-ref-name>jdbc/JNDI
名字
</ res-ref-name>
<res-type>javax.sql.DataSource </ res- type>
<res-auth>Container </ res- auth>
</resource-ref>
|
<resource-ref> 元素的屬性如下:
屬性 | 描述 |
description | 對所引用的資源的說明 |
res-ref-name | 指定所引用資源的 JNDI 名字,與 <Resource> 元素中的 name 屬性保持一致 |
res-type | 指定所引用資源的類名字,與 <Resource> 元素中的 type 屬性保持一致 |
res-auth | 指定所引用資源的 Manager ,與 <Resource> 元素中的 auth 屬性保持一致 |
到這里,數據源就已經配置成功了。但是我在測試的時候除了一點小麻煩,主要原因是對DataSource的概念沒搞清楚。我是這么測試的,寫一個測試類,然后在eclipse中進行junit測試, 捕獲的異常為:
javax.naming.NoInitialContextException
: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:?java.naming.factory.initia
l
。
同樣的代碼在JSP文件中正常運行,后來翻了一些資料,終于找到了問題的所在了。原來DataSource是由容器(TOMCAT)提供的,所以我的測試會拋出異常。為了再次驗證想法是否正確,在jsp文件中import剛才拋出異常的類,在進行連接數據庫,結果一切正常。
下面的例子是實際應用中使用
DataSource
,在
jsp
文件中連接
oracle
。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%@ page import="javax.naming.*"%>
<%@ page import="javax.sql.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
?<head>
?</head>
<body>
<%
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource db = (DataSource)envContext.lookup("jdbc/javablogorl");
// javablogorl
為
<Resource>
元素中
name
屬性的值
Connection conn = db.getConnection( );?
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM blog_systemadmin");
while(rs.next()){
?????? out.print(rs.getString("admin_name")+" ");
?????? out.print(rs.getString("admin_password")+"<br>");
}
rs.close();
stmt.close();
conn.close();
%>?
?</body>
</html>
|
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=674822
Name pusjndi is not bound in this Context
不知怎么解決,盼指導:kongfanyu7241@sohu.com
另外配置數據源的Resource name等到底放在server.xml文件那個位置??