<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    關于EJB學習

         摘要: EJB 結構中的角色 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 這六個角色分別是:?????????Enterprise?Bean?Provider:EJB組件開發者; ...  閱讀全文

    posted @ 2007-01-15 22:58 youngturk 閱讀(245) | 評論 (0)編輯 收藏

    經典例題分析

    ?

    ?1 class ?SuperClass
    ?2 {
    ?3 ???? void ?SuperClass() {System.out.print( " a " );} // 非構造函數,構造函數可聲明為public?SuperClass(){};
    ?4 ???? int ?a? = ? 8 ,b? = ? 6 ;}
    // 成員變量會被子類覆蓋繼承
    ?5 class ?SubClass? extends ?SuperClass
    ?6 {
    ?7 ???? void ?SuperClass() {System.out.print( " b " );} // 非構造函數,實現多態。
    ?8 // ????int?a=30,b=20;
    ?9 ???? /**
    10 ?????*? @return
    11 ????? */

    12 ???? int ?max() { return ?((a? > ?b) ? ?a:b);} }

    13 public ? class ?ABC? {
    14
    15 ???? /**
    16 ?????*? @param ?args
    17 ????? */

    18 ???? public ? static ? void ?main(String[]?args)? {
    19 ????SubClass?sb? = ? new ?SubClass();
    20 ????SubClass?mm? = ? new ?SubClass();
    21 ????mm.SuperClass();
    22 ????System.out.println(sb.max());
    23
    24 ????}

    25
    26 }
    分析
    1,多態在父類構造函數不能被繼承實現多態
    2,相同名字的父類的成員變量會被子類覆蓋,繼承。

    posted @ 2007-01-15 11:17 youngturk 閱讀(332) | 評論 (0)編輯 收藏

    創建數據庫表

    create table 'book'
    (
    ?'book_id'?? int(11)??? not null AUTO_INCREMENT,
    ?'book_name' varchar(100)?? not null default?? '',
    ?'book_author'? varchar(100)??? not null default? '',
    ?'book_price'?? double????????? not null default? '0',
    ?'image'??????? varchar(100)??? not null default? '',
    ?'describe'???? varchar(200)??? not null default? '',
    ?primary key('book_id')
    )
    例示:
    create table 'student'
    (
    'student_id' int(11) not null autou_increment,
    'student_name' varchar(100) not null default '',
    'student_number' double not null default '0',
    primary key('student_id')
    )

    posted @ 2007-01-06 13:21 youngturk 閱讀(529) | 評論 (1)編輯 收藏

    簡單的實現卻不會

    要求假如輸入"asdf as df as" 則輸出字符串之中最長字符串,
    如果兩個同時最長如"asdf as df as asdf" 則輸出asdf|asdf
    如果中間有as/tdf則什么也不輸出。
    public class Zifu {

    ?/**
    ? * @param args
    ? */
    ?public static void main(String[] args) {
    ??// TODO Auto-generated method stub
    ??String str = "asdfa fasd sf asdfa";
    ??????? if (str.indexOf("/") >= 0) {
    ??????????? System.out.println("format error !");
    ??????? } else {
    ??????????? String s[] = str.split(" ");//-------〉將字符串按照空格拆分成字符串數祖
    ??????????? int max = 0;
    ??????????? String ss = "";

    ??????????? for (int i = 0; i < s.length; i++) { //-----s.length為拆分的叔組長度
    ??????????????? if (max < s[i].length()) {//---------s[i].length()為單個數組字符串長度
    ??????????????????? max = s[i].length();
    ??????????????? }

    ??????????? }

    ??????????? for (int i = 0; i < s.length; i++) {
    ??????????????? if (max == s[i].length()) {
    ??????????????????? ss += s[i] + "|";
    ??????????????? }

    ??????????? }

    ??????????? System.out.println(ss);
    ??????? }
    ?}

    ?

    posted @ 2007-01-03 22:33 youngturk 閱讀(224) | 評論 (2)編輯 收藏

    javaScript

    筆試題1
    function ? doPan(value){ ? //指定Main表單提交的URL ?
    ? document.Main.action.value ? = ? value; ? //value ? Form提交的url ?
    ? document.Main.submit(); ? //提交 ?
    ? }

    posted @ 2006-12-28 23:29 youngturk 閱讀(231) | 評論 (0)編輯 收藏

    表單的驗證

    提交表單后,需要對信息進行驗證。表單的驗證有兩種:客戶端驗證和服務器驗證。

    ? 1 )表單的客戶端驗證

    ?????? 表單的客戶端驗證主要是通過 JavaScript 來完成的。

    <html>

    <head>

    <title> 客戶端驗證 </title>

    <Script>

    function Check()

    {

    ??? username=document.form1.username.value;

    ??? age=document.form1.age.value;

    ??? year=document.form1.year.value;

    ??? email=document.form1.email.value;

    ?

    ?

    ?

    ??? <!-- 驗證提交數據的長度 -->

    ??? if(username.length<2||username.length>8)

    ??? {

    ????? alert(" 用戶名長度必須在 2 位到 8 位之間 ");

    ????? return false;

    ??? }

    ?

    ??? <!-- 驗證提交數據的范圍 -->

    ??? if(age.length!=2||isNaN(age)||parseInt(age)<20||parseInt(age)>50)

    ??? {

    ????? alert(" 你的年齡不符合我們的要求! ");

    ????? return false;

    ??? }

    ?

    ??? <!-- 驗證提交數據的類型 -->

    ??? <!-- 限定出生年份是一個 4 位整數 -->

    ??? if(year.length!=4||isNaN(year))

    ??? {

    ????? alert(" 年份填寫不正確! ");

    ????? return false;

    ??? }

    ??? <!-- 限定電子郵箱不能為空,且必須要有“ @ ”和“ . -->

    ??? if(email.length==""||(email.indexOf('@')==-1)||(email.indexOf('.')==-1))

    ??? {

    ????? alert(" 電子郵件填寫不正確! ");

    ????? return false;

    ??? }

    ??? return true;

    }

    </Script>

    </head>

    <body>

    <h3> 客戶端驗證 </h3>

    <form name="form1" action="X.jsp" OnSubmit="return Check();">

    <p> 名: <input name="username"></p>

    <p> &nbsp;&nbsp;&nbsp;&nbsp; 齡: <input name="age"></p>

    <p> 出生年份: <input name="year"></p>

    <p> 電子郵件: <input name="email"></p>

    <p><input type=Submit value=" 提交 "></p>

    </form>

    </body>

    </html>

    ? 2 )表單的服務器端驗證

    ?????? 表單的服務器端驗證是通過服務器端的 X.jsp 來完成的。

    <html>

    <head>

    <title>A Form</title>

    </head>

    <body>

    <h3>The form will be checked by the Server.</h3>

    <form name="fm" action="XXX.jsp" method="post">

    ? <p>UserName:

    ??? <input type="text" name="username">

    ? </p>

    ? <p>PassWord:

    ??? <input type="password" name="password">

    ? </p>

    ? <p>BirthYear:

    ??? <input type="text" name="birthyear">

    ? </p>

    ? <p><center>

    ??? <a href='JavaScript:fm.submit();'> 提交 </a>

    ??? <a href='JavaScript:fm.reset();'> 重置 </a>

    ? </center></p>

    </form>

    </body>

    </html>

    posted @ 2006-12-28 17:38 youngturk 閱讀(274) | 評論 (0)編輯 收藏

    數據庫面試筆試題集

    第二套題
    一、 選擇題
    1. 以下數據結構中不屬于線性數據結構的是____C__。
    A、隊列 B、線性表 C、二叉樹 D、棧
    2. 在結構化方法中,用數據流程圖(DFD)作為描述工具的軟件開發階段是__B____。
    A、可行性分析 B、需求分析 C、詳細設計 D、程序編碼
    3. 結構化程序設計主要強調的是__B____。
    A、程序的規模 B、程序的易讀性 C、程序的執行效率 D、程序的可移植性
    4. 在軟件生命周期中,能準確地確定軟件系統必須做什么和必須具備哪些功能的階段是_D_____。
    A、概要設計 B、詳細設計 C、可行性分析 D、需求分析
    5. 下列關于棧的敘述中正確的是____D__。A、在棧中只能插入數據 B、在棧中只能刪除數據
    C、棧是先進先出的線性表 D、棧是先進后出的線性表
    6. 下面不屬于軟件設計原則的是__C____。A、抽象 B、模塊化 C、自底向上 D、信息隱蔽
    7. 對長度為N的線性表進行順序查找,在最壞情況下所需要的比較次數為__B____。
    A、N+1 B、N C、(N+1)/2 D、N/2
    8. 視圖設計一般有3種設計次序,下列不屬于視圖設計的是__B____。
    A、自頂向下 B、由外向內 C、由內向外 D、自底向上
    9. 下列有關數據庫的描述,正確的是_C_____。A、數據庫是一個DBF文件 B、數據庫是一個關系
    C、數據庫是一個結構化的數據集合 D、數據庫是一組文件
    10. 下列說法中,不屬于數據模型所描述的內容的是__C____。
    A、數據結構 B、數據操作 C、數據查詢 D、數據約束
    11. 在下面的Visual FoxPro表達式中,運算結果是邏輯真的是_D_____。
    A、EMPTY(.NULL.) B、LIKE('acd','ac?') C、AT('a','123abc') D、EMPTY(SPACE(2))
    12. 表達式VAL(SUBS("奔騰586",5,1))*Len("visual foxpro")的結果是__D____。
    A、13.00 B、14.00 C、45.00 D、65.00
    13. 以下關于自由表的敘述,正確的是__C____。
    A、全部是用以前版本的FOXPRO(FOXBASE)建立的表
    B、可以用Visual FoxPro建立,但是不能把它添加到數據庫中
    C、自由表可以添加到數據庫中,數據庫表也可以從數據庫中移出成為自由表
    D、自由表可以添加到數據庫中,但數據庫表不可從數據庫中移出成為自由表
    14. 下面關于數據環境和數據環境中兩個表之間的關系的陳述中,_C_____是正確的。
    A、數據環境是對象,關系不是對象 B、數據環境不是對象,關系是對象
    C、數據環境是對象,關系是數據環境中的對象 D、數據環境和關系均不是對象
    15. 在"報表設計器"中,可以使用的控件是__A____。
    A、標簽、域控件和線條 B、標簽、域控件和列表框
    C、標簽、文本框和列表框 D、布局和數據源
    16.用二維表數據來表示實體及實體之間聯系的數據模型稱為_D_____。
    A、實體--聯系模型 B、層次模型 C、網狀模型 D、關系模型
    17. 用來指明復選框的當前選中狀態的屬性是___C___。A、Selected B、Caption C、Value D、ControlSource
    18. 使用菜單操作方法打開一個在當前目錄下已經存在的查詢文件zgjk.qpr后,在命令窗口生成的命令是__B__。
    A、OPEN QUERY zgjk.qpr B、MODIFY QUERY zgjk.qpr
    C、DO QUERY zgjk.qpr D、CREATE QUERY zgjk.qpr
    19. 可以伴隨著表的打開而自動打開的索引是____C__。
    A、單一索引文件(IDX) B、復合索引文件(CDX)C、結構化復合索引文件 D、非結構化復合索引文件
    20. 在數據庫設計器中,建立兩個表之間的一對多聯系是通過以下索引實現的__A____。
    A、"一方"表的主索引或候選索引,"多方"表的普通索引
    B、"一方"表的主索引,"多方"表的普通索引或候選索引
    C、"一方"表的普通索引,"多方"表的主索引或候選索引
    D、"一方"表的普通索引,"多方"表的候選索引或普通索引
    21. 下列函數中函數值為字符型的是___B___。 A、DATE() B、TIME() C、YEAR() D、DATETIME()
    22. 下面對控件的描述正確的是___B___。
    A、用戶可以在組合框中進行多重選擇 B、用戶可以在列表框中進行多重選擇
    C、用戶可以在一個選項組中選中多個選項按鈕 D、用戶對一個表單內的一組復選框只能選中其中一個
    23. 確定列表框內的某個條目是否被選定應使用的屬性是___D___。
    A、Value B、ColumnCount C、ListCount D、Selected
    24. 設有關系R1和R2,經過關系運算得到結果S,則S是_A_____。
    A、一個關系 B、一個表單 C、一個數據庫 D、一個數組
    25. DBAS指的是___C___。A、數據庫管理系統B、數據庫系統C、數據庫應用系統 D、數據庫服務系統
    26. 設X="ABC",Y="ABCD",則下列表達式中值為.T.的是__C____。A、X=Y B、X==Y C、X$Y D、AT(X,Y)=0
    27. 在表結構中,邏輯型、日期型、備注型字段的寬度分別固定為B___。
    A、3,8,10 B、1,6,4 C、1,8,任意 D、1,8,4
    28. 在標準SQL中,建立視圖的命令是___C___。
    A、CREATE SCHEMA命令 B、CREATE TABLE命令 C、CREATE VIEW命令 D、CREATE INDEX命令
    29. 有關SCAN循環結構,敘述正確的是__B____。
    A、SCAN循環結構中的LOOP語句,可將程序流程直接指向循環開始語句SCAN,首先判斷EOF()函數的真假
    B、在使用SCAN循環結構時,必須打開某一個數據庫
    C、SCAN循環結構的循環體中必須寫有SKIP語句
    D、SCAN循環結構,如果省略了子句\FOR和WHILE條件子句,則直接退出循環
    30. 設有圖書管理數據庫:
    圖書(總編號C(6),分類號C(8),書名C(16),作者C(6),出版單位C(20),單價N(6,2))
    讀者(借書證號C(4),單位C(8),姓名C(6),性別C(2),職稱C(6),地址C(20))
    借閱(借書證號C(4),總編號C(6),借書日期D(8))
    對于圖書管理數據庫,要查詢所藏圖書中,各個出版社的圖書最高單價、平均單價和冊數,下面SQL語句正確的是__D____。
    SELECT 出版單位,______,______,______;
    FROM 圖書管理!圖書 ______ 出版單位
    A、MIN(單價) AVGAGE(單價) COUNT(*) GROUP BY B、MAX(單價) AVG(單價) COUNT(*) ORDER BY
    C、MAX(單價) AVG(單價) SUM(*) ORDER BY D、MAX(單價) AVG(單價) COUNT(*) GROUP BY
    31. 設有圖書管理數據庫:
    圖書(總編號C(6),分類號C(8),書名C(16),作者C(6),出版單位C(20),單價N(6,2))
    讀者(借書證號C(4),單位C(8),姓名C(6),性別C(2),職稱C(6),地址C(20))
    借閱(借書證號C(4),總編號C(6),借書日期D(8))
    對于圖書管理數據庫,求CIE單位借閱圖書的讀者的人數。
    下面SQL語句正確的是__A____。
    SELECT ______ FROM 借閱 WHERE;
    借書證號 _______
    A、COUNT (DISTINCT 借書證號)
    IN (SELECT 借書證號 FROM 讀者 WHERE 單位="CIE")
    B、COUNT (DISTINCT 借書證號)
    IN (SELECT 借書證號 FROM 借閱 WHERE 單位="CIE")
    C、SUM (DISTINCT 借書證號)
    IN (SELECT 借書證號 FROM 讀者 WHERE 單位="CIE")
    D、SUM (DISTINCT 借書證號)
    IN (SELECT 借書證號 FOR 借閱 WHERE 單位="CIE")
    32. 查詢訂購單號(字符型,長度為4)尾字符是"1"的錯誤命令是__C____。
    A、SELECT * FROM 訂單 WHERE SUBSTR(訂購單號,4)="1"
    B、SELECT * FROM 訂單 WHERE SUBSTR(訂購單號,4,1)="1"
    C、SELECT * FROM 訂單 WHERE "1"$訂購單號
    D、SELECT * FROM 訂單 WHERE RIGHT(訂購單號,1)="1"
    33. 在關系模型中,為了實現"關系中不允許出現相同元組"的約束應使用___B___。
    A、臨時關鍵字 B、主關鍵字 C、外部關鍵字 D、索引關鍵字
    34. 根據"職工"項目文件生成emp_sys.exe應用程序的命令是__B____。
    A、BUILD EXE emp_sys FROM 職工 B、BUILD APP emp_sys.exe FROM 職工
    C、LIKE EXE emp_sys FROM 職工 D、LIKE APP emp_sys.exe FROM 職工
    35. 當前盤當前目錄下有數據庫:學院.dbc,其中有"教師"表和"學院"表。
    "教師"表:

    "學院"表:

    有SQL語句:
    SELECT DISTINCT 系號 FROM 教師 WHERE 工資>=;
    ALL (SELECT 工資 FROM 教師 WHERE 系號="02")
    與如上語句等價的SQL語句是___A___。
    A、SELECT DISTINCT 系號 FROM 教師 WHERE工資>=;
    (SELECT MAX(工資) FROM 教師 WHERE 系號="02")
    B、SELECT DISTINCT 系號 FROM 教師 WHERE 工資>=;
    (SELECT MIN(工資) FROM 教師 WHERE 系號="02")
    C、SELECT DISTINCT 系號 FROM 教師 WHERE 工資>=;
    ANY(SELECT 工資 FROM 教師 WHERE 系號="02")
    D、SELECT DISTINCT 系號 FROM 教師 WHERE 工資>=;
    SOME (SELECT 工資 FROM 教師 WHERE 系號="02")
    二、 填空題
    36. 若按功能劃分,軟件測試的方法通常分為白盒測試方法和__黑盒____測試方法。
    37. 數據庫系統的三級模式分別為_概念或概念級_____模式、內部級模式與外部級模式。
    38. 在最壞情況下,冒泡排序的時間復雜度為__n(n-1)/2____。
    39. 在面向對象方法中,信息隱蔽是通過對象的___封裝___性來實現的。
    40. 關系模型的數據操縱即是建立在關系上的數據操縱,一般有__查詢____、增加、刪除和修改四種操作。
    41.要把幫助文件設置為復制到硬盤上的Foxhelp.chm文件,需要在"選項"對話框的__文件位置____選項卡上設置。
    42. TIME( )的返回值的數據類型是__字符 或????C____類型。
    43. 在定義字段有效性規則中,在規則框中輸入的表達式中類型是___邏輯表達式_____。
    44. 設計報表通常包括兩部分內容:_數據源_____和布局。
    45. __內部聯接____是指只有滿足聯接條件的記錄才包含在查詢結果中。
    46. 設有圖書管理數據庫:
    圖書(總編號C(6),分類號C(8),書名C(16),作者C(6),出版單位C(20),單價N(6,2))
    讀者(借書證號C(4),單位C(8),姓名C(6),性別C(2),職稱C(6),地址C(20))
    借閱(借書證號C(4),總編號C(6),借書日期D(8))
    檢索書價在15元至25元(含15元和25元)之間的圖書的書名、作者、書價和分類號,結果按分類號升序排序。
    SELECT 書名,作者,單價,分類號 FROM 圖書;
    WHERE______;
    ORDER BY______;
    47. 設有如下關系表R、S和T:
    R(BH,XM,XB,DWH)
    S(SWH,DWM)
    T(BH,XM,XB,DWH)
    實現R∪T的SQL語句是_______。
    48. 設有如下關系表R:
    R(NO,NAME,SEX,AGE,CLASS)
    主關鍵字是NO
    其中NO為學號,NAME為姓名,SEX為性別,AGE為年齡,CLASS為班號。寫出實現下列功能的SQL語句。
    插入"95031"班學號為30,姓名為"鄭和"的學生記錄;_______。
    49. 設有如下關系表R:
    R(NO,NAME,SEX,AGE,CLASS)
    主關鍵字是NO
    其中NO為學號(數值型),NAME為姓名,SEX為性別,AGE為年齡,CLASS為班號。寫出實現下列功能的SQL語句。
    刪除學號為20的學生記錄;______。
    第二套題答案
    1-5 CBBDD 6-10 CBBCC 11-15 DDCCA 16-20 DCBCA 21-25 BBDAC 26-30 CDCBD 31-35 ACBBA
    36.黑盒 37.概念或概念級 38.n(n-1)/2 39.封裝 40.查詢 41.文件位置 42.字符 或 C 43.邏輯表達式
    44.數據源 45.內部聯接
    46. 單價 BETWEEN 15 AND 25 或 單價 BETW 15 AND 25 或 單價 BETWE 15 AND 25 或 單價>=15 and 單價<=25 或 單價>=15 and 單價=<25 或 單價=>15 and 單價<=25 或 單價=>15 and 單價=<25 與 分類號 ASC 或 分類號
    47. SELECT * FROM R UNION SELECT * FROM T 或 SELE * FROM R UNIO SELE * FROM T 或 SELECT * FROM R UNIO SELECT * FROM T 或 SELE * FROM R UNION SELE * FROM T
    48. INSERT INTO R(NO,NAME,CLASS) VALUES(30,"鄭和","95031") 或 INSE INTO R(NO,NAME,CLASS) VALUES(30,"鄭和","95031")
    49. DELETE FROM R WHERE NO=20 或 DELE FROM R WHERE NO=20 或 DELE FROM R WHER NO=20 或 DELETE FROM R WHER NO=20

    posted @ 2006-12-27 22:21 youngturk 閱讀(3421) | 評論 (0)編輯 收藏

    數據庫筆試題(1)

    /*
    建表:
    dept:
    ?deptno(primary key),dname,loc
    emp:
    ?empno(primary key),ename,job,mgr,sal,deptno
    */

    1 列出emp表中各部門的部門號,最高工資,最低工資
    select max(sal) as 最高工資,min(sal) as 最低工資,deptno from emp group by deptno;

    2 列出emp表中各部門job為'CLERK'的員工的最低工資,最高工資
    select max(sal) as 最高工資,min(sal) as 最低工資,deptno as 部門號 from emp where job = 'CLERK' group by deptno;

    3 對于emp中最低工資小于1000的部門,列出job為'CLERK'的員工的部門號,最低工資,最高工資
    select max(sal) as 最高工資,min(sal) as 最低工資,deptno as 部門號 from emp as b
    where job='CLERK' and 1000>(select min(sal) from emp as a where a.deptno=b.deptno) group by b.deptno

    4 根據部門號由高而低,工資有低而高列出每個員工的姓名,部門號,工資
    select deptno as 部門號,ename as 姓名,sal as 工資 from emp order by deptno desc,sal asc

    5 寫出對上題的另一解決方法
    (請補充)

    6 列出'張三'所在部門中每個員工的姓名與部門號
    select ename,deptno from emp where deptno = (select deptno from emp where ename = '張三')

    7 列出每個員工的姓名,工作,部門號,部門名
    select ename,job,emp.deptno,dept.dname from emp,dept where emp.deptno=dept.deptno

    8 列出emp中工作為'CLERK'的員工的姓名,工作,部門號,部門名
    select ename,job,dept.deptno,dname from emp,dept where dept.deptno=emp.deptno and job='CLERK'

    9 對于emp中有管理者的員工,列出姓名,管理者姓名(管理者外鍵為mgr)
    select a.ename as 姓名,b.ename as 管理者 from emp as a,emp as b where a.mgr is not null and a.mgr=b.empno

    10 對于dept表中,列出所有部門名,部門號,同時列出各部門工作為'CLERK'的員工名與工作
    select dname as 部門名,dept.deptno as 部門號,ename as 員工名,job as 工作 from dept,emp
    where dept.deptno *= emp.deptno and job = 'CLERK'

    11 對于工資高于本部門平均水平的員工,列出部門號,姓名,工資,按部門號排序
    select a.deptno as 部門號,a.ename as 姓名,a.sal as 工資 from emp as a
    where a.sal>(select avg(sal) from emp as b where a.deptno=b.deptno) order by a.deptno

    12 對于emp,列出各個部門中平均工資高于本部門平均水平的員工數和部門號,按部門號排序
    select count(a.sal) as 員工數,a.deptno as 部門號 from emp as a
    where a.sal>(select avg(sal) from emp as b where a.deptno=b.deptno) group by a.deptno order by a.deptno

    13 對于emp中工資高于本部門平均水平,人數多與1人的,列出部門號,人數,按部門號排序
    select count(a.empno) as 員工數,a.deptno as 部門號,avg(sal) as 平均工資 from emp as a
    where (select count(c.empno) from emp as c where c.deptno=a.deptno and c.sal>(select avg(sal) from emp as b where c.deptno=b.deptno))>1
    group by a.deptno order by a.deptno

    14 對于emp中低于自己工資至少5人的員工,列出其部門號,姓名,工資,以及工資少于自己的人數
    select a.deptno,a.ename,a.sal,(select count(b.ename) from emp as b where b.sal<a.sal) as 人數 from emp as a
    where (select count(b.ename) from emp as b where b.sal<a.sal)>5

    posted @ 2006-12-27 12:02 youngturk 閱讀(3022) | 評論 (2)編輯 收藏

    Java的數據庫連接編程(JDBC)技術

    [本講的知識要點]:JDBC、JDBC的工作原理,訪問數據庫的方法、Statement、PreparedStatement、CallableStatement,ResultSet等對象的編程使用

    9.1 基本知識

    9.1.1 JDBC:Java DataBase Connectivity(Java 數據庫連接技術),它是將Java與SQL結合且獨立于特定的數據庫系統的應用程序編程接口(API--它是一種可用于執行SQL語句的Java API,即由一組用Java語言編寫的類與接口所組成)。

    ? 有了JDBC從而可以使Java程序員用Java語言來編寫完整的數據庫方面的應用程序。另外也可以操作保存在多種不同的數據庫管理系統中的數據,而與數據庫管理系統中數據存儲格式無關。同時Java語言的與平臺的無關性,不必在不同的系統平臺下編寫不同的數據庫應用程序。

    9.1.2 JDBC設計的目的

    (1)ODBC:微軟的ODBC是用C編寫的,而且只適用于Windows平臺,無法實現跨平臺地操作數據庫。

    (2)SQL語言:SQL盡管包含有數據定義、數據操作、數據管理等功能,但它并不是一個完整的編程語言,而且不支持流控制,需要與其它編程語言相配合使用。

    (3)JDBC的設計:由于Java語言具有健壯性、安全、易使用并自動下載到網絡等方面的優點,因此如果采用Java語言來連接數據庫,將能克服ODBC局限于某一系統平臺的缺陷;將SQL語言與Java語言相互結合起來,可以實現連接不同數據庫系統,即使用JDBC可以很容易地把SQL語句傳送到任何關系型數據庫中。

    (4)JDBC設計的目的:它是一種規范,設計出它的最主要的目的是讓各個數據庫開發商為Java程序員提供標準的數據庫訪問類和接口,使得獨立于DBMS的Java應用程序的開發成為可能(數據庫改變,驅動程序跟著改變,但應用程序不變)。

    9.1.3 JDBC的主要功能:(1)創建與數據庫的連接;(2)發送SQL語句到任何關系型數據庫中;(3)處理數據并查詢結果。

    編程實例:

    try

    { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //(1)創建與數據庫的連接

    ? Connection con=DriverManager.getConnection("jdbc:odbc:DatabaseDSN","Login","Password");

    Statement stmt=con.createStatement();

    ResultSet rs=stmt.executeQuery("select * from DBTableName");//(2)發送SQL語句到數據庫中 ? ? ? ? ? ? ?

    while(rs.next())

    { String name=rs.getString("Name") ; ? ? ? ? //(3)處理數據并查詢結果。

    ? int age=rs.getInt("age");

    ? float wage=rs.getFloat("wage");

    }

    rs.close(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //(4)關閉

    stmt.close();

    con.close();

    }

    catch(SQLException e)

    { ? System.out.println("SQLState:"+ e.getSQLState());

    ? System.out.println("Message:" + e.getMessage());

    ? System.out.println("Vendor:" + e.getErrorCode());

    }

    9.1.4 JDBC與ODBC的對比,從而體會JDBC的特點

    (1)ODBC是用C語言編寫的,不是面向對象的;而JDBC是用Java編寫的,是面向對象的。

    (2)ODBC難以學習,因為它把簡單的功能與高級功能組合在一起,即便是簡單的查詢也會帶有復雜的任選項;而JDBC的設計使得簡單的事情用簡單的做法來完成。

    (3)ODBC是局限于某一系統平臺的,而JDBC提供Java與平臺無關的解決方案。

    (4)但也可以通過Java來操作ODBC,這可以采用JDBc-ODBC橋接方式來實現(因為Java不能直接使用ODBC,即在Java中使用本地C的代碼將帶來安全缺陷)。

    9.1.5 JDBC驅動程序的類型: 目前比較常見的JDBC驅動程序可分為以下四個種類:

    (1)JDBC-ODBC橋加ODBC驅動程序

    JavaSoft橋產品利用ODBC驅動程序提供JDBC訪問。注意,必須將ODBC二進制代碼(許多情況下還包括數據庫客戶機代碼)加載到使用該驅動程序的每個客戶機上。因此,這種類型的驅動程序最適合于企業網(這種網絡上客戶機的安裝不是主要問題),或者是用Java編寫的三層結構的應用程序服務器代碼。

    JDBC-ODBC 橋接方式利用微軟的開放數據庫互連接口(ODBC API)同數據庫服務器通訊,客戶端計算機首先應該安裝并配置ODBC driver 和JDBC-ODBC bridge兩種驅動程序。

    (2)本地API

    這種類型的驅動程序把客戶機API上的JDBC調用轉換為Oracle、Sybase、Informix、DB2或其它DBMS的調用。注意,象橋驅動程序一樣,這種類型的驅動程序要求將某些二進制代碼加載到每臺客戶機上。

    這種驅動方式將數據庫廠商的特殊協議轉換成Java代碼及二進制類碼,使Java 數據庫客戶方與數據庫服務器方通信。例如:Oracle用SQLNet協議,DB2用IBM 的數據庫協議。數據庫廠商的特殊協議也應該被安裝在客戶機上。

    (3)JDBC網絡純Java驅動程序

    這種驅動程序將JDBC轉換為與DBMS無關的網絡協議,之后這種協議又被某個服務器轉換為一種DBMS協議。這種網絡服務器中間件能夠將它的純Java客戶機連接到多種不同的數據庫上。所用的具體協議取決于提供者。通常,這是最為靈活的JDBC驅動程序。有可能所有這種解決方案的提供者都提供適合于Intranet用的產品。為了使這些產品也支持Internet訪問,它們必須處理Web所提出的安全性、通過防火墻的訪問等方面的額外要求。幾家提供者正將JDBC驅動程序加到他們現有的數據庫中間件產品中。

    這種方式是純Java driver。數據庫客戶以標準網絡協議(如HTTP、SHTTP)同數據庫訪問服務器通信,數據庫訪問服務器然后翻譯標準網絡協議成為數據庫廠商的專有特殊數據庫訪問協議(也可能用到ODBC driver)與數據庫通信。對Internet 和Intranet 用戶而言這是一個理想的解決方案。Java driver 被自動的,以透明的方式隨Applets自Web服務器而下載并安裝在用戶的計算機上。

    (4)本地協議純Java驅動程序

    這種類型的驅動程序將JDBC調用直接轉換為DBMS所使用的網絡協議。這將允許從客戶機機器上直接調用DBMS服務器,是Intranet訪問的一個很實用的解決方法。

    這種方式也是純Java driver。數據庫廠商提供了特殊的JDBC協議使Java數據庫客戶與數據庫服務器通信。然而,將把代理協議同數據庫服務器通信改用數據庫廠商的特殊JDBC driver。這對Intranet 應用是高效的,可是數據庫廠商的協議可能不被防火墻支持,缺乏防火墻支持在Internet 應用中會存在潛在的安全隱患。

    9.2 JDBC的工作原理

    ? JDBC的設計基于X/Open SQL CLI(調用級接口)這一模型。它通過定義出一組 API對象和方法以用于同數據庫進行交互。



    在Java程序中要操作數據庫,一般應該通過如下幾步(利用JDBC訪問數據庫的編程步驟):

    (1)加載連接數據庫的驅動程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

    (2)創建與數據源的連接

    String url="jdbc:odbc:DatabaseDSN";

    Connection con=DriverManager.getConnection(url,"Login","Password");

    (3)查詢數據庫:創建Statement對象并執行SQL語句以返回一個ResultSet對象。

    Statement stmt=con.createStatement();

    ResultSet rs=stmt.executeQuery("select * from DBTableName");

    (4)獲得當前記錄集中的某一記錄的各個字段的值

    ? String name=rs.getString("Name");

    ? int age=rs.getInt("age");

    ? float wage=rs.getFloat("wage");

    (5)關閉查詢語句及與數據庫的連接(注意關閉的順序先rs再stmt最后為con)

    ? rs.close(); ?

    ? stmt.close();

    ? con.close();

    9.3 JDBC的結構

    ? JDBC主要包含兩部分:面向Java程序員的JDBC API及面向數據庫廠商的JDBC Drive API。

    (1)面向Java程序員的JDBC API:Java程序員通過調用此API從而實現連接數據庫、執行SQL語句并返回結果集等編程數據庫的能力,它主要是由一系列的接口定義所構成。

    java.sql.DriveManager:該接口主要定義了用來處理裝載驅動程序并且為創建新的數據庫連接提供支持。

    java.sql.Connection:該接口主要定義了實現對某一種指定數據庫連接的功能。

    java.sql.Statement:該接口主要定義了在一個給定的連接中作為SQL語句執行聲明的容器以實現對數據庫的操作。它主要包含有如下的兩種子類型。

    ? java.sql.PreparedStatement:該接口主要定義了用于執行帶或不帶 IN 參數的預編譯 SQL 語句。

    ? java.sql.CallableStatement:該接口主要定義了用于執行數據庫的存儲過程的雕用。

    java.sql.ResultSet:該接口主要定義了用于執行對數據庫的操作所返回的結果集。

    (2)面向數據庫廠商的JDBC Drive API:數據庫廠商必須提供相應的驅動程序并實現JDBC API所要求的基本接口(每個數據庫系統廠商必須提供對DriveManager、Connection、Statement、ResultSet等接口的具體實現),從而最終保證Java程序員通過JDBC實現對不同的數據庫操作。

    9.4 數據庫應用的模型

    (1)兩層結構(C/S):在此模型下,客戶端的程序直接與數據庫服務器相連接并發送SQL語句(但這時就需要在客戶端安裝被訪問的數據庫的JDBC驅動程序),DBMS服務器向客戶返回相應的結果,客戶程序負責對數據的格式化。

    client端 ? ? ? ODBC/JDBC ? ? ? ? Server端(DBMS)

    或數據庫專用協議 ?





    主要的缺點:受數據庫廠商的限制,用戶更換數據庫時需要改寫客戶程序;受數據庫版本的限制,數據庫廠商一旦升級數據庫,使用該數據庫的客戶程序需要重新編譯和發布;對數據庫的操作與處理都是在客戶程序中實現,使客戶程序在編程與設計時較為復雜。



    (2)三(或多)層結構(B/S):在此模型下,主要在客戶端的程序與數據庫服務器之間增加了一個中間服務器(可以采用C++或Java語言來編程實現),隔離客戶端的程序與數據庫服務器。客戶端的程序(可以簡單為通用的瀏覽器)與中間服務器進行通信,然后由中間服務器處理客戶端程序的請求并管理與數據庫服務器的連接。



    客戶端程序 HTTP RMI CORBA 中間服務器 ? JDBC ? 數據庫服務器





    9.5 通過JDBC 實現對數據庫的訪問

    (1)引用必要的包

    import java.sql.*; //它包含有操作數據庫的各個類與接口 ?

    (2)加載連接數據庫的驅動程序類 ?

    ? 為實現與特定的數據庫相連接,JDBC必須加載相應的驅動程序類。這通常可以采用Class.forName()方法顯式地加載一個驅動程序類,由驅動程序負責向DriverManager登記注冊并在與數據庫相連接時,DriverManager將使用此驅動程序。

    ? ? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

    注意:這條語句直接加載了sun公司提供的JDBC-ODBC Bridge驅動程序類。

    (3)創建與數據源的連接

    String url="jdbc:odbc:DatabaseDSN";

    Connection con=DriverManager.getConnection(url,"Login","Password");

    注意:采用DriverManager類中的getConnection()方法實現與url所指定的數據源建立連接并返回一個Connection類的對象,以后對這個數據源的操作都是基于該Connection類對象;但對于Access等小型數據庫,可以不用給出用戶名與密碼。

    String url="jdbc:odbc:DatabaseDSN";

    Connection con=DriverManager.getConnection(url);

    System.out.println(con.getCatalog()); //取得數據庫的完整路徑及文件名 

    ? JDBC借用了url語法來確定全球的數據庫(數據庫URL類似于通用的URL),對由url所指定的數據源的表示格式為

    ? jdbc::[ database locator]

    jdbc---指出要使用JDBC

    subprotocal---定義驅動程序類型

    database locator---提供網絡數據庫的位置和端口號(包括主機名、端口和數據庫系統名等) ? jdbc:odbc://host.domain.com:port/databasefile ?

    主協議jdbc ? 驅動程序類型為odbc,它指明JDBC管理器如何訪問數據庫,該例指名為采用JDBC-ODBC橋接方式;其它為數據庫的位置表示。 ?

    例如:裝載mySQL JDBC驅動程序

    Class.forName("org.gjt.mm.mysql.Driver ");

    String url

    ="jdbc:mysql://localhost/softforum?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
      //testDB為你的數據庫名
      Connection conn= DriverManager.getConnection(url);

    例如:裝載Oracle JDBC OCI驅動程序(用thin模式)

    Class.forName("oracle.jdbc.driver.OracleDriver ");

    String url="jdbc:oracle:thin:@localhost:1521:orcl";
      //orcl為你的數據庫的SID
      String user="scott";
      String password="tiger";
      Connection conn= DriverManager.getConnection(url,user,password);

    注意:也可以通過con.setCatalog("MyDatabase")來加載數據庫。

    例如:裝載DB2驅動程序

    Class.forName("com.ibm.db2.jdbc.app.DB2Driver ")

    String url="jdbc:db2://localhost:5000/sample";
      //sample為你的數據庫名
      String user="admin";
      String password="";
      Connection conn= DriverManager.getConnection(url,user,password);



    例如:裝載MicroSoft SQLServer驅動程序

    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver ");

    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs";
      //pubs為你的數據庫的
      String user="sa";
      String password="";   
      Connection conn= DriverManager.getConnection(url,user,password);

    (4)查詢數據庫的一些結構信息

    ? 這主要是獲得數據庫中的各個表,各個列及數據類型和存儲過程等各方面的信息。根據這些信息,從而可以訪問一個未知結構的數據庫。這主要是通過DatabaseMetaData類的對象來實現并調用其中的方法來獲得數據庫的詳細信息(即數據庫的基本信息,數據庫中的各個表的情況,表中的各個列的信息及索引方面的信息)。

    ? DatabaseMetaData dbms=con.getMetaData();

    ? System.out.println("數據庫的驅動程序為 "+dbms.getDriverName());

    (5)查詢數據庫中的數據:

    ? 在JDBC中查詢數據庫中的數據的執行方法可以分為三種類型,分別對應Statement (用于執行不帶參數的簡單SQL語句字符串),PreparedStatement(預編譯SQL語句)和CallableStatement(主要用于執行存儲過程)三個接口。

    9.5.1、實現對數據庫的一般查詢Statement

    1、創建Statement對象(要想執行一個SQL查詢語句,必須首先創建出Statement對象,它封裝代表要執行的SQL語句)并執行SQL語句以返回一個ResultSet對象,這可以通過Connection類中的createStatement()方法來實現。

    ? Statement stmt=con.createStatement();

    2、執行一個SQL查詢語句,以查詢數據庫中的數據。Statement接口提供了三種執行SQL語句的方法:executeQuery()、executeUpdate() 和execute()。具體使用哪一個方法由SQL語句本身來決定。

    l ? ? 方法 executeQuery 用于產生單個結果集的語句,例如 SELECT 語句等。

    l ? ? 方法 executeUpdate 用于執行INSERT、UPDATE或DELETE 語句以及SQL DDL(數據定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或DELETE 語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個整數,指示受影響的行數(即更新計數)。對于 CREATE TABLE 或DROP TABLE 等不操作行的語句,executeUpdate 的返回值總為零。

    l ? ? ? 方法 execute 用于執行返回多個結果集、多個更新計數或二者組合的語句。一般不會需要該高級功能。

    下面給出通過Statement類中的executeQuery()方法來實現的代碼段。executeQuery()方法的輸入參數是一個標準的SQL查詢語句,其返回值是一個ResultSet類的對象。

    ResultSet rs=stmt. executeQuery ("select * from DBTableName"); ? ? ?
    要點:①JDBC在編譯時并不對將要執行的SQL查詢語句作任何檢查,只是將其作為一個String類對象,直到驅動程序執行SQL查詢語句時才知道其是否正確。對于錯誤的SQL查詢語句,在執行時將會產生 SQLException。

    ? ? ②一個Statement對象在同一時間只能打開一個結果集,對第二個結果集的打開隱含著對第一個結果集的關閉。

    ? ? ③如果想對多個結果集同時操作,必須創建出多個Statement對象,在每個Statement對象上執行SQL查詢語句以獲得相應的結果集。

    ? ? ④如果不需要同時處理多個結果集,則可以在一個Statement對象上順序執行多個SQL查詢語句,對獲得的結果集進行順序操作。

    import java.sql.*;

    public class ResultSetTest

    { ? public static void main(String args[])

    ? ? { ? ? try

    ? ? ? ? ? { ?

    ? ? ? ? ? ? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

    ? ? ? ? ? ? Connection con=DriverManager.getConnection("jdbc:odbc:studlist");

    ? ? ? ? ? ? Statement stmt=con.createStatement();

    ? ? ? ? ? ? ResultSet rs1=stmt.executeQuery("select name from student");

    ? ? ? ? ? ? ResultSet rs2=stmt.executeQuery("select age from student");

    //此時rs1已經被關閉 ? ? ? ? ? ?

    ? ? ? ? ? ? while(rs2.next())

    ? ? ? ? ? ? { ?

    ? ? ? ? ? ? ? System.out.println(rs2.getObject(1));

    ? ? ? ? ? ? }

    ? ? ? ? ? ? rs2.close();

    ? ? ? ? ? ? stmt.close();

    ? ? ? ? ? ? con.close();

    ? ? ? ? ? }

    ? ? ? ? ? catch(Exception e)

    ? ? ? ? ? {

    ? ? ? ? ? ? System.out.println(e);

    ? ? ? ? ? } ?

    ? }

    }

    注意:

    此時顯示出的將是姓名還是年齡?(將顯示的是rs2的結果集的內容,即學生的年齡,因為采用JDBC-ODBC方式的驅動程序時,并且是采用同一個Statement對象,它只會保留最新的結果集,rs1中的內容將會被新的結果集所取代)。

    3、 關閉Statement對象:每一個Statement對象在使用完畢后,都應該關閉。

    ? stmt.close();

    9.5.2、預編譯方式執行SQL語句PreparedStatement

    ? 由于Statement對象在每次執行SQL語句時都將該語句傳給數據庫,如果需要多次執行同一條SQL語句時,這樣將導致執行效率特別低,此時可以采用PreparedStatement對象來封裝SQL語句。如果數據庫支持預編譯,它可以將SQL語句傳給數據庫作預編譯,以后每次執行該SQL語句時,可以提高訪問速度;但如果數據庫不支持預編譯,將在語句執行時才傳給數據庫,其效果類同于Statement對象。

    ? 另外PreparedStatement對象的SQL語句還可以接收參數,可以用不同的輸入參數來多次執行編譯過的語句,較Statement靈活方便(詳見后文介紹)。

    1、 創建PreparedStatement對象:從一個Connection對象上可以創建一個PreparedStatement對象,在創建時可以給出預編譯的SQL語句。

    ? PreparedStatement pstmt=con.prepareStatement("select * from DBTableName");

    2、 執行SQL語句:可以調用executeQuery()來實現,但與Statement方式不同的是,它沒有參數,因為在創建PreparedStatement對象時已經給出了要執行的SQL語句,系統并進行了預編譯。

    ? ResultSet rs=pstmt.executeQuery(); // 該條語句可以被多次執行

    3、關閉PreparedStatement

    ? pstmt.close(); //其實是調用了父類Statement類中的close()方法

    9.5.3、執行存儲過程CallableStatement

    ? CallableStatement類是PreparedStatement類的子類,因此可以使用在PreparedStatement類及Statement類中的方法,主要用于執行存儲過程。

    1、 創建CallableStatement對象:使用Connection類中的prepareCall方法可以創建一個CallableStatement對象,其參數是一個String對象,一般格式為:

    l ? ? ? 不帶輸入參數的存儲過程“{call 存儲過程名()}”。

    l ? ? 帶輸入參數的存儲過程“{call存儲過程名(?, ?)}”

    l ? ? ? 帶輸入參數并有返回結果參數的存儲過程“{? = call 存儲過程名(?, ?, ...)}”

    ? CallableStatement cstmt=con.prepareCall("{call Query1()}");

    2、 執行存儲過程:可以調用executeQuery()方法來實現。

    ? ResultSet rs=cstmt.executeQuery(); ?

    3、關閉CallableStatement

    ? cstmt.close(); //其實是調用了父類Statement類中的close()方法

    (6)檢索記錄集以獲得當前記錄集中的某一記錄的各個字段的值

    9.5.4、ResultSet對象:

    ? ① 執行完畢SQL語句后,將返回一個ResultSet類的對象,它包含所有的查詢結果。但對ResultSet類的對象方式依賴于光標(Cursor)的類型,而對每一行中的各個列,可以按任何順序進行處理(當然,如果按從左到右的順序對各列進行處理可以獲得較高的執行效率);

    ResultSet類中的Course方式主要有:

    ResultSet.TYPE_FORWARD_ONLY(為缺省設置):光標只能前進不能后退,也就是只能從第一個一直移動到最后一個。

    ResultSet.TYPE_SCROLL_SENSITIVE:允許光標前進或后退并感應到其它ResultSet的光標的移動情形。

    ResultSet.TYPE_SCROLL_INSENSITIVE:允許光標前進或后退并不能感應到其它ResultSet的光標的移動情形。

    ResultSet類中的數據是否允許修改主要有:

    ResultSet.CONCUR_READ_ONLY(為缺省設置):表示數據只能只讀,不能更改。

    ResultSet.CONCUR_UPDATABLE:表示數據允許被修改。

    ? 可以在創建Statement或PreparedStatement對象時指定ResultSet的這兩個特性。

    Statement stmt=con.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);



    PreparedStatement pstmt=con.PrepareStatement("insert into bookTable values (?,?,?)",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
    ② ResultSet類的對象維持一個指向當前行的指針,利用ResultSet類的next()方法可以移動到下一行(在JDBC中,Java程序一次只能看到一行數據),如果next()的返回值為false,則說明已到記錄集的尾部。另外JDBC也沒有類似ODBC 的書簽功能的方法。

    ? ③ 利用ResultSet類的getXXX()方法可以獲得某一列的結果,其中XXX代表JDBC中的Java數據類型,如 getInt()、getString()、getDate()等。訪問時需要指定要檢索的列(可以采用 int值作為列號(從1開始計數)或指定列(字段)名方式,但字段名不區別字母的大小寫)。

    while(rs.next())

    { String name=rs.getString("Name"); //采用“列名”的方式訪問數據

    ? int age=rs.getInt("age");

    ? float wage=rs.getFloat("wage");

    ? String homeAddress=rs.getString(4); //采用“列號”的方式訪問數據

    }

    9.5.5、數據轉換

    ? 利用ResultSet類的getXXX()方法可以實現將ResultSet中的SQL數據類型轉換為它所返回的Java數據類型。

    9.5.6、NULL結果值

      要確定給定結果值是否是JDBC NULL,必須先讀取該列,然后使用ResultSet.wasNull

    方法檢查該次讀取是否返回JDBC NULL。

      當使用ResultSet.getXXX方法讀取JDBC NULL時,方法wasNull將返回下列值之一:

    (1)Javanull值

      對于返回Java對象的getXXX方法(例如getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject等)。

    (2)零值:對于getByte、getShort、getInt、getLong、getFloat和getDouble。

    (3)false值:對于getBoolean

    9.5.6、獲得結果集中的結構信息:利用ResultSet類的getMetaData()方法來獲得結果集中的一些結構信息(主要提供用來描述列的數量、列的名稱、列的數據類型。利用ResulSetMetaData類中的方法)。

    ResultsetMetaData rsmd=rs.getMetaData();

    rsmd.getColumnCount(); ? //返回結果集中的列數 ? ? ? ?

    rsmd.getColumnLabel(1); //返回第一列的列名(字段名)

    例如:

    Statement stmt=con.createStatement();

    ResultSet rs=stmt.executeQuery("select * from TableName");

    for(int i=1; i<=rs.getMetaData().getColumnCount(); i++) ? //跟蹤顯示各個列的名稱

    ? ? { ? ? System.out.print(rs. getColumnName (i)+"\t");

    ? ? }

    while(rs.next())

    { //跟蹤顯示各個列的值

    ? for(int j=1; j<=rs.getMetaData().getColumnCount(); j++)

    ? ? { ? ? System.out.print(rs.getObject(j)+"\t");

    ? ? }

    }

    9.6、更新數據庫

    ? 前面主要介紹如何實現對數據庫的查詢操作,但在許多應用中需要實現對數據庫的更新,這主要涉及修改、插入和刪除等(即SQL語句中的Insert、Update、Delete、Creat、Drap等)。仍然通過創建Statement對象來實現,但不再調用executeQuery()方法,而是使用executeUpdate()方法。

    要點F:正確區分Statement類中的executeQuery()、execute()和executeUpdate()方法的用法:(1)

    executeQuery() 執行一般的SQL查詢語句(即SELECT語句)并返回Resultset對象;(2)execute()可以執行各種SQL查詢語句,并可能返回多個結果集(這一般主要發生在執行了返回多個結果集的存儲過程時),此時可以采用Resultset類的getResultSet()來獲得當前的結果集;(3)executeUpdate()執行對數據庫的更新的SQL語句或DDL語句。

    9.6.1 對表中的記錄進行操作

    ? 對一個表中的記錄可以進行修改、插入和刪除等操作,分別對應SQL的Update、 Insert、Delete操作;executeUpdate()方法的輸入參數仍然為一個String對象(即所要執行的SQL語句),但輸出參數不是ResultSet對象,而是一個整數(它代表操作所影響的記錄行數)。

    Statement stmt=con.createStatement();

    stmt.executeUpdate("Update bookTable set Title='Java2' where Author='zhang'");



    stmt.executeUpdate("Delete from bookTable where Author='zhang'");

    stmt.executeUpdate("Insert into bookTable(BookID,Author,Title) values(1,'Li Ming','Java2')"); //未給出的列,其值為NULL



    程序實例:對數據庫中的表進行更新操作并顯示操作前后的結果

    import java.sql.*;

    public class DBUpdateSetTest

    { ? public static void main(String args[])

    ? ? { ? ? try

    ? ? ? ? ? { ?

    ? ? ? ? ? ? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

    ? ? ? ? ? ? Connection con=DriverManager.getConnection("jdbc:odbc:studlist");

    ? ? ? ? ? ? Statement stmt=con.createStatement();

    ? ? ? ? ? ? ResultSet rs=stmt.executeQuery("select * from student");

    ? ? ? ? ? ? System.out.println("Result before executeUpdate");

    ? ? ? ? ? ? while(rs.next())

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? System.out.println(rs.getString("name"));

    ? ? ? ? ? ? ? ? System.out.println(rs.getString("age"));

    ? ? ? ? ? ? }

    ? ? ? ? ? ? stmt.executeUpdate("Update student set name='Yang' where id=0");

    ? ? ? ? ? ? stmt.executeUpdate("Delete from student where id=2");

    ? ? ? ? ? ? stmt.executeUpdate("Insert into student(id,name,age,sex) values(2,'zhang',30,true)");

    ? ? ? ? ? ? rs=stmt.executeQuery("select * from student");

    ? ? ? ? ? ? System.out.println("Result After executeUpdate");

    ? ? ? ? ? ? while(rs.next())

    ? ? ? ? ? ? {

    ? ? ? ? ? ? ? ? System.out.println(rs.getString("name"));

    ? ? ? ? ? ? ? ? System.out.println(rs.getString("age"));

    ? ? ? ? ? ? }

    ? ? ? ? ? ? rs.close();

    ? ? ? ? ? ? stmt.close();

    ? ? ? ? ? ? con.close();

    ? ? ? ? ? ? }

    ? ? ? ? ? catch(Exception e)

    ? ? ? ? ? {

    ? ? ? ? ? ? System.out.println(e);

    ? ? ? ? ? } ?

    ? ? }

    }

    9.6.2 創建和刪除表

    ? 創建和刪除一個表主要對應于SQL的Create Table和Drop Table語句。這可以通過Statement對象的executeUpdate()方法來完成。

    ① 創建表

    ? Statement stmt=con.createStatement();

    ? stmt.executeUpdate("create table TableName(ID integer, Name VARCHAR(20), Age integer)");

    ? stmt.executeUpdate("Insert into TableName(ID, Name, Age) values(1,'Yang Ming',30)");

    ② 刪除表

    ? Statement stmt=con.createStatement();

    ? stmt.executeUpdate("Drop Table TableName");

    9.6.3 增加和刪除表中的列

    對一個表的列進行更新操作主要是使用SQL的ALTER Table語句。對列所進行的更新操作會影響到表中的所有的行。

    ① 增加表中的一列

    ? Statement stmt=con.createStatement();

    ? stmt.executeUpdate("Alter Table TableName add Column Address VarChar(50)");

    ? stmt.executeUpdate("Update TableName set Address='Beijing,China' where ID=1");

    ② 刪除表中的一列

    ? Statement stmt=con.createStatement();

    ? stmt.executeUpdate("Alter Table TableName Drop Column Address");

    ? stmt.executeQuery("Select * from TableName");

    9.6.4 利用PreparedStatement對象實現數據更新

    ? 同SQL查詢語句一樣,對數據更新語句時也可以在PreparedStatement對象上執行。使用PreparedStatement對象,只需傳遞一次SQL語句,可以多次執行它,并且可以利用數據庫的預編譯技術,提高執行效率。另外也可以接受參數。

    ? PreparedStatement pstmt=con.prepareStatement("Update TableName set Address='Beijing,China' where ID >1");

    ? pstmt.executeUpdate();

    9.7 參數的輸入與輸出

    ? 要實現使用SQL語句的輸入與輸出參數,必須在PreparedStatement類的對象上進行操作;同時由于CallableStatement類是PrepareStatement類的子類,所以在CallableStatemen對象上的操作也可以使用輸入與輸出參數;其主要的編程原理是在生成CallableStatement或PreparedStatement類的對象時,可以在SQL語句中指定輸入或輸出參數,在執行這個SQL語句之前,要對輸入參數進行賦值。

    (1)使用PreparedStatement類的對象

    ? 通過prepareStatement類的對象可以實現在查詢語句與數據更新語句方面都可以設置輸入參數。

    ? 具體的方法是在SQL語句中用“?”標明參數,在執行SQL語句之前,使用setXXX方法給參數賦值,然后使用executeQuery()或executeUpdate()來執行這個SQL語句。每次執行SQL語句之前,可以給參數重新賦值。

    ? setXXX方法用于給相應的輸入參數進行賦值,其中XXX是JDBC的數據類型,如:Int、String等。setXXX方法有兩個參數,第一個是要賦值的參數在SQL語句中的位置, SQL語句中的第一個參數的位置為1,第二個參數的位置為2;setXXX方法的第二個參數是要傳遞的值,如100、“Peking”等,隨XXX的不同而為不同的類型。

    ? PreparedStatement pstmt=con.prepareStatement("Update TableName set Name=? where ID=?");

    ? pstmt.setString(1,"zhang Hua"); //設置第一個參數(Name)為 “zhang Hua”

    ? for(int i=1;i<3;i++)

    ? { pstmt.setInt(2,i); //設置第二個參數(ID)為 1,2

    ? ? pstmt.executeUpdate();

    ? }

    要點:最終實現 Update TableName set Name=zhang Hua where ID=1 與Update TableName set Name=zhang Hua where ID=2的效果。

    (2)使用CallableStatement對象

    ? 如果要求調用數據庫的存儲過程,要使用CallableStatement對象。另外還有些存儲過程要求用戶輸入參數,這可以在生成CallableStatement對象的存儲過程調用語句中設置輸入參數。在執行這個存儲過程之前使用setXXX方法給參數賦值,然后再執行這個存儲過程。

    ? CallableStatement cstmt=con.prepareCall("{call Query(?)}"); //Query為存儲過程名

    ? cstmt.setString(1,"輸入參數"); //為存儲過程提供輸入參數

    ? ResultSet rs=cstmt.executeQuery();

    (3)接收輸出參數

    ? 某些存儲過程可能會返回輸出參數,這時在執行這個存儲過程之前,必須使用CallableStatement的registerOutParameter方法首先登記輸出參數,在registerOutParameter方法中要給出輸出參數的相應位置以及輸出參數的SQL數據類型。在執行完存儲過程以后,必須使用getXXX方法來獲得輸出參數的值。并在getXXX方法中要指出獲得哪一個輸出參數(通過序號來指定)的值。

    實例:存儲過程getTestData有三個輸入參數并返回一個輸出參數,類型分別為VARCHAR。在執行完畢后,分別使用getString()方法來獲得相應的值。

    CallableStatement cstmt = con.prepareCall(“{? = call getTestData (?,?,?)}”);

    cstmt.setString(1,Value); ? ? ? ? ? ? ? ? ? ? ? //設置輸入參數

    cstmt.setInt(2,Value);

    cstmt.setFloat(3,Value);

    cstmt.registerOutParameter(1,java.sql.Types.VARCHAR); ? //登記輸出參數

    ResultSet rs = cstmt.executeQuery(); ? ? ? ? //執行存儲過程

    rs.getString(1); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //獲得第一個字段的值

    String returnResult=cstmt.getString(1); ? ? ? ? ? ? ? //獲得返回的輸出參數的值

    要點:由于getXXX方法不對數據類型作任何轉換,在registerOutParameter方法中指明數據庫將返回的SQL數據類型,在執行完存儲過程以后必須采用相應匹配的getXXX方法來獲得輸出參數的值。



    9.8 批量處理JDBC語句提高處理速度



    有時候JDBC運行得不夠快,這可以使用數據庫相關的存儲過程。當然,作為存儲過程的一個替代方案,可以試試使用Statement 的批量處理特性以提高速度。



      存儲過程的最簡單的形式就是包含一系列SQL語句的過程,將這些語句放在一起便于在同一個地方管理也可以提高速度。Statement 類可以包含一系列SQL語句,因此允許在同一個數據庫事務執行所有的那些語句而不是執行對數據庫的一系列調用。

      使用批量處理功能涉及下面的兩個方法:

      addBatch(String) 方法

      executeBatch方法

      如果你正在使用Statement 那么addBatch 方法可以接受一個通常的SQL語句,或者如果你在使用PreparedStatement ,那么也可以什么都不向它增加。

    executeBatch 方法執行那些SQL語句并返回一個int值的數組,這個數組包含每個語句影響的數據的行數。

    注意:如果將一個SELECT語句或者其他返回一個ResultSet的SQL語句放入批量處理中就會導致一個SQLException異常。

      關于java.sql.Statement 的簡單范例可以是:

    ? ? con = DriverManager.getConnection(url,"myLogin", "myPassword");

    ? ? con.setAutoCommit(false);

    ? ? stmt = con.createStatement();

    ? ? stmt.addBatch("INSERT INTO student " + "VALUES(4,'Yang',20,True)");

    ? ? stmt.addBatch("INSERT INTO student " + "VALUES(5,'li',20,True)");

    ? ? stmt.addBatch("INSERT INTO student " + "VALUES(6,'zhang',20,True)");

    ? ? stmt.addBatch("INSERT INTO student " + "VALUES(7,'wang',20,True)");

    ? ? stmt.addBatch("INSERT INTO student " + "VALUES(8,'liu',20,True)");



    ? ? int [] updateCounts = stmt.executeBatch();

    ? ? con.commit();

    ? ? con.setAutoCommit(true);



     PreparedStatement 有些不同,它只能處理一部分SQL語法,但是可以有很多參數,因此重寫上面的范例的一部分就可以得到下面的結果:

     // 注意這里沒有刪除語句

    PreparedStatement stmt = conn.prepareStatement(

    "INSERT INTO student VALUES(?,?,?,?)"

    );

    User[ ] users = ...;

    for(int i=0; i

    stmt.setInt(1, users.getID());

    stmt.setString(2, users.getName());

    stmt.setInt(3, users.getAge());

    stmt.setBoolean(4, users.getSex());

    stmt.addBatch( );

    }

    int[ ] counts = stmt.executeBatch();

    如果你不知道你的語句要運行多少次,那么這是一個很好的處理SQL代碼的方法。在不使用批量處理的情況下,如果添加50個用戶,那么性能就有影響,如果某個人寫了一個腳本添加一萬個用戶,程序可能變得很糟糕。添加批處理功能就可以幫助提高性能,而且在后面的那種情況下代碼的可讀性也會更好。

    posted @ 2006-12-27 11:40 youngturk 閱讀(433) | 評論 (0)編輯 收藏

    JAVA題庫:5道JAVA題

    module 1 – getting started
    q1.what will happen when you compile and run the following code?
    (4)
    public class myclass{
    static int i;
    public static void main(string argv[]){
    system.out.println(i);
    }
    }
    1) error variable i may not have been initialized
    2) null
    3) 1
    4) 0
    q2.which of the following will compile without error (2)(3)
    1)
    import java.awt.*;
    package mypackage;
    class myclass {}
    2)
    package mypackage;
    import java.awt.*;
    class myclass{}
    3)
    /*this is a comment */

    package mypackage;
    import java.awt.*;
    class myclass{}

    q3.what will happen if you try to compile and run the following code (1)
    public class myclass {
    public static void main(string arguments[]) {
    amethod(arguments);
    }
    public void amethod(string[] arguments) {
    system.out.println(arguments);
    system.out.println(arguments[1]);
    }
    }
    1) error can't make static reference to void amethod.
    2) error method main not correct
    3) error array must include parameter
    4) amethod must be declared with string
    q4.given the following code(2)
    public class sytch{
    int x=2000;
    public static void main(string argv[]){
    system.out.println("ms "+argv[1]+"please pay $"+x);
    }
    what will happen if you attempt to compile and run this code with the command line
    java sytch jones diggle
    1) compilation and output of ms diggle please pay $2000
    2) compile time error
    3) compilation and output of ms jones please pay $2000
    4) compilation but runtime error
    q5.you have a public class called myclass with the main method defined as follows(4)
    public static void main(string parm[]){
    system.out.println(parm[0]);
    }
    if you attempt to compile the class and run the program as follows
    java myclass hello
    what will happen?
    1) compile time error, main is not correctly defined
    2) run time error, main is not correctly defined
    3) compilation and output of java
    4) compilation and output of hello

    posted @ 2006-12-27 00:24 youngturk 閱讀(442) | 評論 (0)編輯 收藏

    僅列出標題
    共33頁: First 上一頁 25 26 27 28 29 30 31 32 33 下一頁 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    公告

    this year :
    1 jQuery
    2 freemarker
    3 框架結構
    4 口語英語

    常用鏈接

    留言簿(6)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    相冊

    EJB學習

    Flex學習

    learn English

    oracle

    spring MVC web service

    SQL

    Struts

    生活保健

    解析文件

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲色图黄色小说| 精品国产污污免费网站| 久久精品国产亚洲av日韩| 免费无码又爽又刺激毛片| 日本不卡免费新一区二区三区| 99亚洲乱人伦aⅴ精品| 亚洲精品综合一二三区在线| 亚洲国产成人久久综合区| 欧美在线看片A免费观看| 毛片无码免费无码播放| 久久www免费人成精品香蕉| 亚洲日韩一中文字暮| 亚洲婷婷综合色高清在线| 亚洲人成色77777| 2048亚洲精品国产| 亚洲国产成人a精品不卡在线| 男人的好看免费观看在线视频| 99re免费在线视频| 久久国产精品免费看| 中文字幕av无码不卡免费| 免费大片黄在线观看| 亚洲aⅴ无码专区在线观看春色| 国产精品久久亚洲不卡动漫| 久久亚洲熟女cc98cm| 亚洲VA中文字幕无码毛片| 亚洲毛片αv无线播放一区| 亚洲一区二区三区香蕉| 色噜噜AV亚洲色一区二区| 久久久久噜噜噜亚洲熟女综合 | 亚洲成Av人片乱码色午夜| 亚洲综合色自拍一区| 国产AⅤ无码专区亚洲AV| 中文字幕第13亚洲另类| 亚洲宅男天堂在线观看无病毒| 亚洲一区二区三区AV无码| 亚洲人成伊人成综合网久久久| 亚洲精品国产美女久久久| 欧洲亚洲国产清在高| 亚洲国产综合专区电影在线| 精品亚洲A∨无码一区二区三区| 亚洲高清免费在线观看|