無為

          無為則可為,無為則至深!

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks

          public DBConnBean()
          {
          xdebug = true;
          con = null;
          sql = null;
          }
          public Connection Connect()
          throws Exception
          {
          String msg = null;
          try
          {
          Class.forName(DBDriver).newInstance();
          }
          catch(Exception e)
          {
          msg = "加載數(shù)據(jù)庫驅(qū)動失敗";
          if (xdebug) msg += "(驅(qū)動'"+DBDriver+"')";
          throw new Exception(msg);
          }
          try
          {
          String conStr = conp;
          con = DriverManager.getConnection(conStr,username,password);
          }
          catch(SQLException e)
          {
          msg = "!!數(shù)據(jù)庫連接失敗";
          if (xdebug)
          {
          msg += "(錯誤信息='" + e.getMessage()+"' SQL狀態(tài)值='" + e.getSQLState()+"' 錯誤代碼='" + e.getErrorCode()+"')";
          }
          throw new Exception(msg);
          }
          return con;
          }
          protected void finalize()
          throws Throwable
          {
          super.finalize();
          if (stmt != null) stmt.close();
          if (result != null) result.close();
          }
          //最近一次對數(shù)據(jù)庫查詢受影響的行數(shù)
          public int getAffectedRows()
          {
          return affectedRows;
          }
          public Connection getCon()
          {
          return con;
          }
          public String getConp()
          {
          return conp;
          }
          public String getDBDriver()
          {
          return DBDriver;
          }
          public String getDBName()
          {
          return DBName;
          }
          public boolean getDebug()
          {
          return xdebug;
          }
          public String getPassword()
          {
          return password;
          }
          public ResultSet getResult()
          {
          return result;
          }
          public String getSql()
          {
          return sql;
          }
          public String getUsername()
          {
          return username;
          }
          public void over()
          throws Throwable
          {
          finalize();
          }
          public ResultSet query()
          throws Exception
          {
          result = null;
          affectedRows = 0;
          if (con == null)
          Connect();
          if (stmt == null)
          stmt = con.createStatement();
          if (sql.substring(0,6).equalsIgnoreCase("select"))
          {
          result = stmt.executeQuery(sql);
          }
          else
          {
          affectedRows = stmt.executeUpdate(sql);
          }
          return result;
          }
          public ResultSet query(String s)
          throws Exception
          {
          sql = s;
          return query();
          }
          public void setDBDriver(String s)
          {
          DBDriver = s;
          }
          public void setDebug(boolean b)
          {
          xdebug = b;
          }
          public void setgetConp(String s)
          {
          conp = s;
          }
          public void setgetDBName(String s)
          {
          DBName = s;
          }
          public void setgetUsername(String s)
          {
          username = s;
          }
          public void setPassword(String s)
          {
          password = s;
          }
          public void setSql(String s)
          {
          sql = s;
          }
          }
          ② DBQueryBean.Java的源代碼如下所示:
          package dbaccess;
          import Java.sql.*;
          import Java.util.*;
          import Java.io.*;
          import Java.lang.reflect.*;

          public class DBQueryBean
          implements Serializable
          {
          DBConnBean dbc;
          String sql = null;
          int rowcount = 0;
          int colcount = 0;
          // int limitcount = 0;
          Vector result = null;
          public String _WATCH = "";


          public DBQueryBean()
          {
          dbc = new DBConnBean();
          try {
          dbc.Connect();
          } catch(Exception e) {
          handleException(e);
          }
          }
          protected void finalize()
          throws Throwable
          {
          super.finalize();
          if (dbc != null) dbc.over();
          if (result != null) result.removeAllElements();
          }
          public String get(int row, int col)
          {
          if (result==null || row >= result.size()) return null;
          String r[] = (String[])result.elementAt(row);
          if (col >= Java.lang.reflect.Array.getLength(r)) return null;
          return r[col];
          }
          public int getAffRows() { return dbc.getAffectedRows(); }
          public int getColumncount() {
          return colcount;
          }
          public String[] getRow(int row)
          {
          if (result==null || row >= result.size()) return null;
          return (String [])result.elementAt(row);
          /*String ret[] = new String[colcount];
          Vector r = (Vector)result.elementAt(row);
          for (int i=0; i<colcount; i++)
          ret[i] = (String)r.elementAt(i);
          return ret;*/
          }
          public int getRowcount() {
          return rowcount;
          }
          public void handleException(Exception e)
          {
          _WATCH = e.getMessage();
          }
          public void init()
          {
          rowcount = 0;
          colcount = 0;
          // limitcount = 0;
          result = null;
          }
          public void over()
          throws Throwable
          {
          finalize();
          }
          public int query(String sql)
          {
          result = new Vector();
          int ret = 0;
          try {
          ResultSet rs = dbc.query(sql);
          if (rs == null)
          {
          ret = dbc.getAffectedRows();
          }
          else
          {
          ResultSetMetaData rm = rs.getMetaData();
          colcount = rm.getColumnCount();
          while (rs.next())
          {
          String row[] = new String[colcount];
          for (int i=0; i<colcount; i++)
          row[i] = rs.getString(i+1);
          result.addElement(row);
          rowcount++;
          }
          rs.close(); // to release the resource.
          ret = result.size();
          }
          }
          catch(Exception e)
          {
          handleException(e);
          return -1;
          }

          return ret;
          }
          }

          2. 數(shù)據(jù)庫表結(jié)構(gòu)

          本實(shí)例中主要出現(xiàn)了三個數(shù)據(jù)庫表,表名和字段分別如下所示:

          計劃采購表:jhcg_table
          字段名稱 中文名稱 類型 長度
          Goods_no 物品編號 vchar 10
          Goods_name 物品名稱 Vchar 50
          Amount 采購數(shù)量 Int
          Price 采購單價 float
          Gold 幣種 Vchar 15
          Units 單位 Vchar 10
          Date 時間 Date
          Remark 備注 vchar 100

            庫存統(tǒng)計表:kctj_table


          字段名稱 中文名稱 類型 長度
          Goods_no 物品編號 Vchar 10
          Goods_name 物品名稱 Vchar 50
          amount 庫存數(shù)量 Int
          Date 時間 Date

          remark 備注 Vchar 100

            實(shí)際采購表:sjcg_table


          字段名稱 中文名稱 類型 長度
          Goods_no 物品編號 Vchar 10
          Goods_name 物品名稱 Vchar 50
          Amount 采購數(shù)量 Int
          Price Price 采購單價 Float
          Gold 幣種 Vchar 15
          Units 采購單位 Vchar 10
          Date 時間 Date
          Remark 備注 vchar 100

          其中業(yè)務(wù)邏輯非常簡單,即根據(jù)計劃采購表和庫存統(tǒng)計表生成實(shí)際采購表。同時,對各表完成數(shù)據(jù)庫的增、刪、改、查等通用操作。

          3. JSP設(shè)計

          ① 插入操作

          完成對數(shù)據(jù)庫表的記錄插入功能,其中計劃采購表的插入主頁面(insert_jhcg.htm)為:

          圖1 計劃采購表插入主頁面

          insert_jhcg.htm將用戶輸入傳送給demo_insert_jhcg.jsp,完成插入操作。改jsp文件的功能代碼為:

          <html>
          <body>
          <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/>
          <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/>
          <hr>
          <!--test JavaBean-->
          <%
          if (DBConn == null||DBBean == null){
          out.println("JavaBean not found!");
          return;
          }
          %>

          <!--try db_demo connection-->
          <%
          try{
          DBConn.Connect();
          }catch(Exception e){
          out.println(e.getMessage());
          }
          %>

          <!--execute sql statement-->
          <%
          String insGoodno = request.getParameter("ed_jhcg_no");
          String insGoodname = request.getParameter("ed_jhcg_name");
          int insAmount = (Integer.valueOf(request.getParameter("ed_jhcg_amount"))).intValue();
          float insPrice = (Float.valueOf(request.getParameter("ed_jhcg_price"))).floatValue();
          String insGold = request.getParameter("ed_jhcg_gold");
          String insUnit = request.getParameter("ed_jhcg_unit");
          String insRemark = request.getParameter("ed_jhcg_remark");
          String sqlStatement = "insert into jhcg_table(good_no,good_name,amount,
          price,gold,unit,remark) values("+"'"+insGoodno+"'"+","+"'"+insGoodname+"'"+",
          "+insAmount+","+insPrice+","+"'"+insGold+"'"+","+"'"+insUnit+"'"+","+"'"+
          insRemark+"'"+")";
          try{
          DBBean.query(sqlStatement);
          }catch(Exception e){
          out.println(e.getMessage());
          }
          %>
          <a href="demo_main.htm">Records inserted...Click here to return</a></p>
          </body>
          </html>

          ② 查詢操作

          該查詢主頁面主要提供對三個數(shù)據(jù)庫表的條件查詢功能,如下圖所示:

          圖2 查詢主頁面

          query.htm將用戶選擇查詢的數(shù)據(jù)庫表和查詢條件發(fā)送給demo_query.jsp,由jsp文件完成數(shù)據(jù)庫查詢操作和查詢結(jié)果集的返回及顯示,其功能代碼如下:

          <html>
          <body>
          <%
          String sqlStatement;
          String sqlField = "";
          String whichTable = "";
          String whereClause = "";
          String queryNo = "";
          String queryName = "";
          %>
          <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/>
          <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/>
          <hr>
          <!--test JavaBean-->
          <%
          if (DBConn == null||DBBean == null){
          out.println("JavaBean not found!");
          return;
          }
          %>

          <!--try db_demo connection-->
          <%
          try{
          DBConn.Connect();
          }catch(Exception e){
          out.println(e.getMessage());
          }
          %>

          <!--prepare sql statement-->
          <%
          String queryRequest = request.getParameter("rb_request");
          //out.println("queryRequest:"+queryRequest);
          String whichCB = "";
          if (queryRequest.equals("1")){
          whichCB = "ck_jhcg";
          whichTable = "jhcg_table";
          queryNo = request.getParameter("ed_jhcg_no");
          queryName = request.getParameter("ed_jhcg_name");
          if (!queryNo.equals(""))
          whereClause = " where good_no="+"'"+queryNo+"'";
          if (!queryName.equals("")){
          if (!queryNo.equals(""))
          whereClause += " and good_name="+"'"+queryName+"'";
          else whereClause = " where good_name="+"'"+queryName+"'";
          }
          }
          if (queryRequest.equals("2")){
          whichCB = "ck_kctj";
          whichTable = "kctj_table";
          queryNo = request.getParameter("ed_kctj_no");
          queryName = request.getParameter("ed_kctj_name");
          if (!queryNo.equals(""))
          whereClause = " where good_no="+"'"+queryNo+"'";
          if (!queryName.equals("")){
          if (!queryNo.equals(""))
          whereClause += " and good_name="+"'"+queryName+"'";
          else whereClause = " where good_name="+"'"+queryName+"'";
          }

          }
          if (queryRequest.equals("3")){
          whichCB = "ck_sjcg";
          whichTable = "sjcg_table";
          queryNo = request.getParameter("ed_sjcg_no");
          queryName = request.getParameter("ed_sjcg_name");
          if (!queryNo.equals(""))
          whereClause = " where good_no="+"'"+queryNo+"'";
          if (!queryName.equals("")){
          if (!queryNo.equals(""))
          whereClause += " and good_name="+"'"+queryName+"'";
          else whereClause = " where good_name="+"'"+queryName+"'";
          }

          }
          String[] printTitle = request.getParameterValues(whichCB);

          %>
          <!--create query sql statement-->
          <%
          sqlStatement = "select ";
          for(int i = 0;i<printTitle.length;i++){
          sqlField += printTitle[i]+",";
          }
          sqlStatement += sqlField.substring(0,sqlField.length()-1)+" from "+whichTable;
          if (!whereClause.equals(""))
          sqlStatement += whereClause;
          %>
          <!--show query response-->
          <%
          try{
          DBBean.query(sqlStatement);
          }catch(Exception e){
          out.println("Database Error!");
          }
          int rows = DBBean.getRowcount();
          int cols = DBBean.getColumncount();
          %>
          <Table align="center" width="80%" border=1>
          <tr align=center>
          <%
          for(int i = 0;i < printTitle.length;i++){
          out.println("<td><b>");
          out.println(printTitle[i]);
          out.println("</b></td>");
          }
          %>
          </tr>
          <%
          for (int i = 0;i < rows;i++){
          out.println("<tr>");
          for (int j = 0;j < cols;j++)
          out.println("<td>"+DBBean.get(i,j)+"</td>");
          out.println("</tr>");
          }
          %>
          </Table>
          <br>
          <hr>
          <a href="demo_main.htm">Click here to return</a></p>
          </body>
          </html>

          ③ 生成實(shí)際采購表

          生成數(shù)據(jù)庫表是一個隱式操作,程序根據(jù)計劃采購表和庫存統(tǒng)計表的相應(yīng)字段生成實(shí)際采購表,不需要用戶的任何輸入,其功能代碼如下(demo_create.jsp):

          <%@page import="Java.util.*"%>
          <html>
          <body>
          <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/>
          <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/>
          <hr>
          <!--test JavaBean-->
          <%
          if (DBConn == null||DBBean == null){
          out.println("JavaBean not found!");
          return;
          }
          %>

          <!--try db_demo connection-->
          <%
          try{
          DBConn.Connect();
          }catch(Exception e){
          out.println(e.getMessage());
          }
          %>

          <!--prepare sql statement-->
          <%
          int amount_jhcg,amount_kctj;
          Vector updateRs = new Vector();
          DBBean.query("delete * from sjcg_table"); //delete all old records in sjcg_table
          DBBean.query("select jhcg_table.good_no,jhcg_table.good_name,jhcg_table.amount,kctj_table.amount,jhcg_table.unit from jhcg_table left join kctj_table on kctj_table.good_no=jhcg_table.good_no");
          int rows = DBBean.getRowcount();
          int cols = DBBean.getColumncount();
          for (int i = 0;i < rows;i++){
          String record[] = new String[4];
          record[0] = DBBean.get(i,0);
          record[1] = DBBean.get(i,1);
          amount_jhcg = (Integer.valueOf(DBBean.get(i,2))).intValue();
          if (DBBean.get(i,3) == null) amount_kctj = 0;
          else amount_kctj = (Integer.valueOf(DBBean.get(i,3))).intValue();
          record[2] = Integer.toString(amount_jhcg - amount_kctj);
          record[3] = DBBean.get(i,4);
          updateRs.addElement(record);
          }
          for (int i = 0;i < rows;i++){
          String insRecord[] = (String [])updateRs.elementAt(i);
          String insGoodno,insGoodname,insUnit,insAmount;
          insGoodno = insRecord[0];
          insGoodname = insRecord[1];
          insAmount = insRecord[2];
          insUnit = insRecord[3];
          String sqlStatement = "insert into sjcg_table(good_no,good_name,amount,unit) values?quot;+"'"+insGoodno+"'"+","+"'"+insGoodname+"'"+","+insAmount+","+"'"+insUnit+"'"+")";
          DBBean.query(sqlStatement);
          DBBean.query("delete * from sjcg_table where amount<=0");
          }
          %>
          <a href="demo_main.htm">Database created...Click here to return</a></p>
          </body>
          </html>

          上述的開發(fā)工具綜合應(yīng)用介紹了基于Java開發(fā)電子商務(wù)應(yīng)用系統(tǒng)的全過程,包括應(yīng)用開發(fā)平臺搭建、業(yè)務(wù)流程分析、JavaBean封裝和JSP開發(fā)等內(nèi)容,其中JSP開發(fā)中涉及到了通用SQL(查詢和插入數(shù)據(jù)庫表)和游標(biāo)操作(生成實(shí)際采購表),基本可以完成任何網(wǎng)絡(luò)數(shù)據(jù)庫應(yīng)用的需求。本實(shí)例基本上可以將前面介紹的基于Java的電子商務(wù)開發(fā)技術(shù)串接起來,指導(dǎo)讀者進(jìn)行電子商務(wù)應(yīng)用開發(fā)。

          如何在JSP中實(shí)現(xiàn)分頁顯示?

          分頁顯示是Web數(shù)據(jù)庫應(yīng)用中經(jīng)常需要遇到的問題,當(dāng)用戶的數(shù)據(jù)庫查詢結(jié)果遠(yuǎn)遠(yuǎn)超過了計算機(jī)屏幕的顯示能力的時候,我們該如何合理的將數(shù)據(jù)呈現(xiàn)給用戶呢?答案就是數(shù)據(jù)庫分頁顯示,可以完美的解決上述問題。下面是一個數(shù)據(jù)庫分頁操作的通用實(shí)例,對任何數(shù)據(jù)庫平臺上的分頁功能都有很好的借鑒意義。

          <%@ page contentType="text/html;charset=8859_1" %>
          <%
          //變量聲明
          Java.sql.Connection sqlCon; //數(shù)據(jù)庫連接對象
          Java.sql.Statement sqlStmt; //SQL語句對象
          Java.sql.ResultSet sqlRst; //結(jié)果集對象

          Java.lang.String strCon; //數(shù)據(jù)庫連接字符串
          Java.lang.String strSQL; //SQL語句

          int intPageSize; //一頁顯示的記錄數(shù)
          int intRowCount; //記錄總數(shù)
          int intPageCount; //總頁數(shù)
          int intPage; //待顯示頁碼
          Java.lang.String strPage;

          int i;

          //設(shè)置一頁顯示的記錄數(shù)
          intPageSize = 2;

          //取得待顯示頁碼
          strPage = request.getParameter("page");
          if(strPage==null){//表明在QueryString中沒有page這一個參數(shù),此時顯示第一頁數(shù)據(jù)
          intPage = 1;
          }
          else{//將字符串轉(zhuǎn)換成整型
          intPage = Java.lang.Integer.parseInt(strPage);
          if(intPage<1) intPage = 1;
          }

          //裝載JDBC驅(qū)動程序
          Java.sql.DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

          //設(shè)置數(shù)據(jù)庫連接字符串
          strCon = "jdbc:oracle:thin:@linux:1521:ora4cweb";

          //連接數(shù)據(jù)庫
          sqlCon = Java.sql.DriverManager.getConnection(strCon,"hzq","hzq");

          //創(chuàng)建一個可以滾動的只讀的SQL語句對象
          sqlStmt = sqlCon.createStatement(Java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,Java.sql.ResultSet.CONCUR_READ_ONLY);

          //準(zhǔn)備SQL語句
          strSQL = "select name,age from test";

          //執(zhí)行SQL語句并獲取結(jié)果集
          sqlRst = sqlStmt.executeQuery(strSQL);

          //獲取記錄總數(shù)
          sqlRst.last();
          intRowCount = sqlRst.getRow();

          //記算總頁數(shù)
          intPageCount = (intRowCount+intPageSize-1) / intPageSize;

          //調(diào)整待顯示的頁碼
          if(intPage>intPageCount) intPage = intPageCount;
          %>

          <html>
          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
          <title>JSP數(shù)據(jù)庫操作例程 - 數(shù)據(jù)分頁顯示 - JDBC 2.0 - Oracle</title>
          </head>

          <body>

          <table border="1" cellspacing="0" cellpadding="0">
          <tr>
          <th>姓名</th>
          <th>年齡</th>
          </tr>

          <%
          if(intPageCount>0){
          //將記錄指針定位到待顯示頁的第一條記錄上
          sqlRst.absolute((intPage-1) * intPageSize + 1);

          //顯示數(shù)據(jù)
          i = 0;
          while(i<intPageSize && !sqlRst.isAfterLast()){
          %>
          <tr>
          <td><%=sqlRst.getString(1)%></td>
          <td><%=sqlRst.getString(2)%></td>
          </tr>
          <%
          sqlRst.next();
          i++;
          }
          }
          %>

          </table>

          第<%=intPage%>頁 共<%=intPageCount%>頁
          <%if(intPage<intPageCount){%><a href="jdbc20-oracle.jsp?page=<%=intPage+1%>">下一頁
          </a><%}%> <%if(intPage>1){%><a href="jdbc20-oracle.jsp?page=<%=intPage-1%>">上一頁</a><%}%>

          </body>
          </html>

          <%
          //關(guān)閉結(jié)果集
          sqlRst.close();

          //關(guān)閉SQL語句對象
          sqlStmt.close();

          //關(guān)閉數(shù)據(jù)庫
          sqlCon.close();
          %>

          附錄:JDBC TM技術(shù)解析

          1. JDBCTM的定義

          JDBCTM 是一種用于執(zhí)行 SQL 語句的 JavaTM API,它由一組用 Java 編程語言編寫的類和接口組成。JDBC 為工具/數(shù)據(jù)庫開發(fā)人員提供了一個標(biāo)準(zhǔn)的API,使他們能夠用純 Java API 來編寫數(shù)據(jù)庫應(yīng)用程序。

          有了 JDBC,向各種關(guān)系數(shù)據(jù)庫發(fā)送 SQL 語句就是一件很容易的事。換言之,有了 JDBC API,就不必為訪問 Sybase 數(shù)據(jù)庫專門寫一個程序,為訪問 Oracle 數(shù)據(jù)庫又專門寫一個程序,為訪問 Informix 數(shù)據(jù)庫又寫另一個程序,等等。您只需用 JDBC API 寫一個程序就夠了它可向相應(yīng)數(shù)據(jù)庫發(fā)送 SQL 語句。而且,使用 Java 編程語言編寫的應(yīng)用程序,就無須去憂慮要為不同的平臺編寫不同的應(yīng)用程序。將Java 和 JDBC 結(jié)合起來將使程序員只須寫一遍程序就可讓它在任何平臺上運(yùn)行。

          Java 具有堅固、安全、易于使用、易于理解和可從網(wǎng)絡(luò)上自動下載等特性,是編寫數(shù)據(jù)庫應(yīng)用程序的杰出語言。所需要的只是 Java應(yīng)用程序與各種不同數(shù)據(jù)庫之間進(jìn)行對話的方法。而 JDBC 正是作為此種用途的機(jī)制。

          JDBC 擴(kuò)展了 Java 的功能。例如,用 Java 和 JDBC API 可以發(fā)布含有 applet 的網(wǎng)頁,而該 applet 使用的信息可能來自遠(yuǎn)程數(shù)據(jù)庫企業(yè)也可以用 JDBC 通過 Intranet 將所有職員連到一個或多個內(nèi)部數(shù)據(jù)庫中(即使這些職員所用的計算機(jī)有 Windows、 Macintosh 和UNIX 等各種不同的操作系統(tǒng))。隨著越來越多的程序員開始使用Java 編程語言,對從 Java 中便捷地訪問數(shù)據(jù)庫的要求也在日益增加。

          MIS 管理員們都喜歡 Java 和 JDBC 的結(jié)合,因?yàn)樗剐畔鞑プ兊萌菀缀徒?jīng)濟(jì)。企業(yè)可繼續(xù)使用它們安裝好的數(shù)據(jù)庫,并能便捷地存取信息,即使這些信息是儲存在不同數(shù)據(jù)庫管理系統(tǒng)上。新程序的開發(fā)期很短。安裝和版本控制將大為簡化。程序員可只編寫一遍應(yīng)用程序或只更新一次,然后將它放到服務(wù)器上,隨后任何人就都可得到最新版本的應(yīng)用程序。對于商務(wù)上的銷售信息服務(wù), Java 和JDBC 可為外部客戶提供獲取信息更新的更好方法。

          2. JDBC 的用途

          簡單地說,JDBC 可做三件事:與數(shù)據(jù)庫建立連接、發(fā)送 SQL 語句并處理結(jié)果。下列代碼段給出了以上三步的基本示例:

          Connection con = DriverManager.getConnection("jdbc:odbc:wombat","login",
          "password");
          Statement stmt = con.createStatement();
          ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
          while (rs.next()) {
          int x = rs.getInt("a");
          String s = rs.getString("b");
          float f = rs.getFloat("c");
          }

          上述代碼對基于JDBC的數(shù)據(jù)庫訪問做了經(jīng)典的總結(jié),當(dāng)然,在本小節(jié)的后續(xù)部分會對它做詳盡的分析講解。

          3. JDBC API

          JDBC 是個"低級"接口,也就是說,它用于直接調(diào)用 SQL 命令。在這方面它的功能極佳,并比其它的數(shù)據(jù)庫連接 API 易于使用,但它同時也被設(shè)計為一種基礎(chǔ)接口,在它之上可以建立高級接口和工具。高級接口是"對用戶友好的"接口,它使用的是一種更易理解和更為方便的 API,這種API在幕后被轉(zhuǎn)換為諸如 JDBC 這樣的低級接口。

          在關(guān)系數(shù)據(jù)庫的"對象/關(guān)系"映射中,表中的每行對應(yīng)于類的一個實(shí)例,而每列的值對應(yīng)于該實(shí)例的一個屬性。于是,程序員可直接對 Java 對象進(jìn)行操作;存取數(shù)據(jù)所需的 SQL 調(diào)用將在"掩蓋下"自動生成。此外還可提供更復(fù)雜的映射,例如將多個表中的行結(jié)合進(jìn)一個 Java 類中。

          隨著人們對 JDBC 的興趣日益增漲,越來越多的開發(fā)人員一直在使用基于 JDBC 的工具,以使程序的編寫更加容易。程序員也一直在編寫力圖使最終用戶對數(shù)據(jù)庫的訪問變得更為簡單的應(yīng)用程序。例如應(yīng)用程序可提供一個選擇數(shù)據(jù)庫任務(wù)的菜單。任務(wù)被選定后,應(yīng)用程序?qū)⒔o出提示及空白供填寫執(zhí)行選定任務(wù)所需的信息。所需信息輸入應(yīng)用程序?qū)⒆詣诱{(diào)用所需的 SQL 命令。在這樣一種程序的協(xié)助下,即使用戶根本不懂 SQL 的語法,也可以執(zhí)行數(shù)據(jù)庫任務(wù)。

          4. JDBC與ODBC和其它API的比較

          目前,Microsoft 的 ODBC API 可能是使用最廣的、用于訪問關(guān)系數(shù)據(jù)庫的編程接口。它能在幾乎所有平臺上連接幾乎所有的數(shù)據(jù)庫。為什么 Java 不使用 ODBC?對這個問題的回答是:Java 可以使用 ODBC,但最好是在 JDBC 的幫助下以 JDBC-ODBC 橋的形式使用,這一點(diǎn)我們稍后再說。現(xiàn)在的問題已變成:"為什么需要 JDBC"?答案是顯然的:ODBC 不適合直接在 Java 中使用,因?yàn)樗褂?C 語言接口。從Java 調(diào)用本地 C 代碼在安全性、實(shí)現(xiàn)、堅固性和程序的自動移植性方面都有許多缺點(diǎn)。從 ODBC C API 到 Java API 的字面翻譯是不可取的。例如,Java 沒有指針,而 ODBC 卻對指針用得很廣泛(包括很容易出錯的指針"void *")。您可以將 JDBC 想象成被轉(zhuǎn)換為面向?qū)ο蠼涌诘?ODBC,而面向?qū)ο蟮慕涌趯?Java 程序員來說較易于接收。

          ODBC 很難學(xué)。它把簡單和高級功能混在一起,而且即使對于簡單的查詢,其選項(xiàng)也極為復(fù)雜。相反,JDBC 盡量保證簡單功能的簡便性,而同時在必要時允許使用高級功能。啟用"純 Java "機(jī)制需要象 JDBC 這樣的 Java API。如果使用ODBC,就必須手動地將 ODBC 驅(qū)動程序管理器和驅(qū)動程序安裝在每臺客戶機(jī)上。如果完全用 Java 編寫 JDBC 驅(qū)動程序則 JDBC 代碼在所有 Java 平臺上(從網(wǎng)絡(luò)計算機(jī)到大型機(jī))都可以自 動安裝、移植并保證安全性。

          總之,JDBC API 對于基本的 SQL 抽象和概念是一種自然的 Java 接口。它建立在 ODBC 上而不是從零開始。因此,熟悉 ODBC 的程序員將發(fā)現(xiàn) JDBC 很容易使用。JDBC 保留了 ODBC 的基本設(shè)計特征;事實(shí)上,兩種接口都基于 X/Open SQL CLI(調(diào)用級接口)。它們之間最大的區(qū)別在于:JDBC 以 Java 風(fēng)格與優(yōu)點(diǎn)為基礎(chǔ)并進(jìn)行優(yōu)化,因此更加易于使用。

          目前,Microsoft 又引進(jìn)了 ODBC 之外的新 API: RDO、 ADO 和OLE DB。這些設(shè)計在許多方面與 JDBC 是相同的,即它們都是面向?qū)ο蟮臄?shù)據(jù)庫接口且基于可在 ODBC 上實(shí)現(xiàn)的類。但在這些接口中,我們未看見有特別的功能使我們要轉(zhuǎn)而選擇它們來替代 ODBC,尤其是在 ODBC 驅(qū)動程序已建立起較為完善的市場的情況下。它們最多也就是在 ODBC 上加了一種裝飾而已。

          5. JDBC對B/S和C/S模式的支持

          JDBC API 既支持?jǐn)?shù)據(jù)庫訪問的兩層模型(C/S),同時也支持三層模型(B/S)。在兩層模型中,Java applet或應(yīng)用程序?qū)⒅苯优c數(shù)據(jù)庫進(jìn)行對話。這將需要一個JDBC驅(qū)動程序來與所訪問的特定數(shù)據(jù)庫管理系統(tǒng)進(jìn)行 通訊。用戶的SQL語句被送往數(shù)據(jù)庫中,而其結(jié)果將被送回給用戶。數(shù)據(jù)庫可以位于另一臺計算機(jī)上,用戶通過網(wǎng)絡(luò)連接到上面。這就叫做客戶機(jī)/服務(wù)器配置,其中用戶的計算機(jī)為客戶機(jī),提供數(shù)據(jù)庫的計算機(jī)為服務(wù)器。網(wǎng)絡(luò)可以是 Intranet(它可將公司職員連接起來),也可以是 Internet。

          在三層模型中,命令先是被發(fā)送到服務(wù)的"中間層",然后由它將SQL 語句發(fā)送給數(shù)據(jù)庫。數(shù)據(jù)庫對 SQL 語句進(jìn)行處理并將結(jié)果送回到中間層,中間層再將結(jié)果送回給用戶。MIS 主管們都發(fā)現(xiàn)三層模型很吸引人,因?yàn)榭捎弥虚g層來控制對公司數(shù)據(jù)的訪問和可作的的更新的種類。中間層的另一個好處是,用戶可以利用易于使用的高級API,而中間層將把它轉(zhuǎn)換為相應(yīng)的低級調(diào)用。最后,許多情況下三層結(jié)構(gòu)可提供一些性能上的好處。

          到目前為止,中間層通常都用 C 或 C++ 這類語言來編寫,這些語言執(zhí)行速度較快。然而,隨著最優(yōu)化編譯器(它把 Java 字節(jié)代碼轉(zhuǎn)換為高效的特定于機(jī)器的代碼)的引入,用 Java 來實(shí)現(xiàn)中間層將變得越來越實(shí)際。這將是一個很大的進(jìn)步,它使人們可以充分利用 Java 的諸多優(yōu)點(diǎn)(如堅固、多線程和安全等特征)。JDBC 對于從Java的中間層來訪問數(shù)據(jù)庫非常重要。

          6. SQL 的一致性

          結(jié)構(gòu)化查詢語言 (SQL) 是訪問關(guān)系數(shù)據(jù)庫的標(biāo)準(zhǔn)語言。困難之處在于:雖然大多數(shù)的 DBMS (數(shù)據(jù)庫管理系統(tǒng))對其基本功能都使用了標(biāo)準(zhǔn)形式的 SQL,但它們卻不符合最近為更高級的功能定義的標(biāo)準(zhǔn) SQL 語法或語義。例如,并非所有的數(shù)據(jù)庫都支持儲存程序或外部連接,那些支持這一功能的數(shù)據(jù)庫又相互不一致。人們希望 SQL 中真正標(biāo)準(zhǔn)的那部份能夠進(jìn)行擴(kuò)展以包括越來越多的功能。但同時 JDBC API 又必須支持現(xiàn)有的 SQL。

          JDBC API 解決這個問題的一種方法是允許將任何查詢字符串一直傳到所涉及的 DBMS 驅(qū)動程序上。這意味著應(yīng)用程序可以使用任意多的 SQL 功能,但它必須冒這樣的風(fēng)險:有可能在某些 DBMS 上出錯。事實(shí)上,應(yīng)用程序查詢甚至不一定要是 SQL,或者說它可以是個為特定的 DBMS 設(shè)計的 SQL 的專用派生物(例如,文檔或圖象查詢)。

          JDBC 處理 SQL 一致性問題的第二種方法是提供 ODBC 風(fēng)格的轉(zhuǎn)義子句,這將在后續(xù)部分中討論。轉(zhuǎn)義語法為幾個常見的 SQL 分歧提供了一種標(biāo)準(zhǔn)的 JDBC 語法。例如,對日期文字和已儲存過程的調(diào)用都有轉(zhuǎn)義語法。

          對于復(fù)雜的應(yīng)用程序,JDBC 用第三種方法來處理 SQL 的一致性問題它利用 DatabaseMetaData 接口來提供關(guān)于 DBMS 的描述性信息,從而使應(yīng)用程序能適應(yīng)每個 DBMS 的要求和功能。

          由于 JDBC API 將用作開發(fā)高級數(shù)據(jù)庫訪問工具和 API 的基礎(chǔ) API,因此它還必須注意其所有上層建筑的一致性。"符合JDBC標(biāo)準(zhǔn)TM" 代表用戶可依賴的 JDBC 功能的標(biāo)準(zhǔn)級別。要使用這一說明,驅(qū)動程序至少必須支持 ANSI SQL-2 Entry Level(ANSI SQL-2 代表美國國家標(biāo)準(zhǔn)局 1992 年所采用的標(biāo)準(zhǔn)。Entry Level代表SQL功能的特定清單)。驅(qū)動程序開發(fā)人員可用 JDBC API 所帶的測試工具包來確定他們的驅(qū)動程序是否符合這些標(biāo)準(zhǔn)。

          "符合 JDBC 標(biāo)準(zhǔn)TM" 表示提供者的 JDBC 實(shí)現(xiàn)已經(jīng)通過了JavaSoft 提供的一致性測試。這些一致性測試將檢查 JDBC API中定義的所有類和方法是否都存在,并盡可能地檢查程序是否具有SQL Entry Level 功能。當(dāng)然,這些測試并不完全,而且 JavaSoft 目前也無意對各提供者的實(shí)現(xiàn)進(jìn)行標(biāo)級。但這種一致性定義的確可對JDBC實(shí)現(xiàn)提供一定的可信度。隨著越來越多的數(shù)據(jù)庫提供者、連接提供者、Internet 提供者和應(yīng)用程序編程員對 JDBC API 的接受,JDBC 也正迅速成為 Java 數(shù)據(jù)庫訪問的標(biāo)準(zhǔn)。



          凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
          、轉(zhuǎn)載請注明來處和原文作者。非常感謝。

          posted on 2006-11-20 13:44 草兒 閱讀(229) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 侯马市| 万山特区| 柘荣县| 搜索| 巴林右旗| 治多县| 老河口市| 景东| 张掖市| 抚顺县| 延津县| 文山县| 莱西市| 利津县| 云和县| 定陶县| 淮滨县| 吉安县| 普安县| 台山市| 宁波市| 扶余县| 修文县| 宜昌市| 吴桥县| 留坝县| 嵊泗县| 娄烦县| 天峨县| 临汾市| 南川市| 正定县| 永川市| 承德市| 湘阴县| 自贡市| 中宁县| 西乌珠穆沁旗| 余姚市| 大田县| 龙南县|