隨筆-28  評論-15  文章-81  trackbacks-0

          前言
           本文根據實例詳細介紹了如何在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驅動程序,常用方法如下:
          方法 描述
          registerDriver(Driver driver) 在DriverManager中注冊JDBC驅動程序
          getConnection(String url,String user,String pwd) 建立和數據庫的連接,返回Connection對象
          setLoginTimeOut(int seconds) 設定等待數據庫連接的最長時間
          setLogWriter(PrintWriter out) 設定輸入數據庫日至的PrintWriter對象
           
          2     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對象。
          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();
          5     ResultSet
           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。
          配置數據源
           配置數據源其實相當簡單:
           首先在server.xml中加入<Resource>元素,打開server.xml,在<Context>中加入以下代碼(以oracle為例):
          <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.initial。
           同樣的代碼在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>
          另:tomcat5.5的配制方法為:
          <Resource name="jdbc/JNDI名字" auth="Container" type="javax.sql.DataSource"
                         maxActive="100" maxIdle="30" maxWait="10000"
                         username="用戶名" password="密碼" driverClassName="oracle.jdbc.driver.OracleDriver"
                         url="jdbc:oracle:thin:@ip:端口:sid"/>

          posted on 2008-01-09 23:24 譚明 閱讀(465) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 万安县| 房产| 城市| 湟中县| 中方县| 当雄县| 黔西| 吉木乃县| 永丰县| 偃师市| 金山区| 永吉县| 紫阳县| 天峨县| 高邑县| 玉屏| 新宁县| 宁城县| 普格县| 广宗县| 高要市| 出国| 海丰县| 南宫市| 泰和县| 顺昌县| 宁强县| 临潭县| 鄂尔多斯市| 绥江县| 体育| 鲜城| 舟曲县| 吉隆县| 项城市| 武城县| 宣化县| 嵩明县| 阳山县| 南汇区| 平利县|