版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
JSP中使用數(shù)據(jù)庫(kù)知識(shí)點(diǎn)回顧EL簡(jiǎn)介掌握EL主要作用掌握EL獲取數(shù)據(jù)基本用法掌握EL運(yùn)算符了解EL保留字了解如何禁用EL掌握常用的EL隱式對(duì)象(內(nèi)置對(duì)象)EL的應(yīng)用及實(shí)例演示本章目標(biāo)JDBC概述JDBC常用API(Driver、DriverManager、Connection、Statement、ResultSet、PreparedStatement、CallableStatement)連接數(shù)據(jù)庫(kù)的基本過(guò)程使用JDBC進(jìn)行事務(wù)處理JDBC概述概述(什么是JDBC)java數(shù)據(jù)庫(kù)連接(JavaDatabaseConnectivity,JDBC)是一種用于執(zhí)行SQL語(yǔ)句的JavaAPI,由一組用Java編程語(yǔ)言編寫(xiě)的類和接口組成。JDBC為數(shù)據(jù)庫(kù)開(kāi)發(fā)人員提供了一組標(biāo)準(zhǔn)的API,使他們能夠用純JavaAPI來(lái)編寫(xiě)數(shù)據(jù)庫(kù)應(yīng)用程序。MySQLOracleMySQL驅(qū)動(dòng)Oracle驅(qū)動(dòng)應(yīng)用程序MySQLOracleMySQL驅(qū)動(dòng)Oracle驅(qū)動(dòng)應(yīng)用程序JDBCJDBC概述JDBC的目的? 推廣java的應(yīng)用。 設(shè)計(jì)出一種通用的數(shù)據(jù)庫(kù)訪問(wèn)接口。使應(yīng)用程序開(kāi)發(fā)人員使用JDBC可以連接任何提供了JDBC驅(qū)動(dòng)程序的數(shù)據(jù)庫(kù)系統(tǒng)。JDBC的用途是什么? 簡(jiǎn)單地說(shuō),JDBC可做三件事: 數(shù)據(jù)庫(kù)建立連接。 發(fā)送SQL語(yǔ)句。 處理結(jié)果。
JDBC概述組成JDBC的2個(gè)包:java.sqljavax.sql(javax是java擴(kuò)展包)開(kāi)發(fā)JDBC應(yīng)用需要以上2個(gè)包的支持外還需要導(dǎo)入相應(yīng)JDBC的數(shù)據(jù)庫(kù)實(shí)現(xiàn)(即數(shù)據(jù)庫(kù)驅(qū)動(dòng))第一個(gè)JDBC程序編程從user表中讀取數(shù)據(jù),并打印在頁(yè)面中。一、搭建實(shí)驗(yàn)環(huán)境:
1、在sqlserver中創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),并創(chuàng)建user表和插入表的數(shù)據(jù)。
2、新建一個(gè)Java工程,并導(dǎo)入數(shù)據(jù)驅(qū)動(dòng)。二、編寫(xiě)程序,在程序中加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)
Class.forName(StringclassName);三、建立連接(Connection) Connectionconn=DriverManager.getConnection(url,user,pass);
四、創(chuàng)建用于向數(shù)據(jù)庫(kù)發(fā)送SQL的Statement對(duì)象,并發(fā)送sql Statementst=conn.createStatement(); ResultSetrs=st.executeQuery(sql);五、從代表結(jié)果集的ResultSet中取出數(shù)據(jù),打印到頁(yè)面六、斷開(kāi)與數(shù)據(jù)庫(kù)的連接,并釋放相關(guān)資源JDBC編程步驟裝載驅(qū)動(dòng)程序建立連接操作數(shù)據(jù)釋放資源JDBC訪問(wèn)數(shù)據(jù)庫(kù)的流程通過(guò)Class.forName加載驅(qū)動(dòng)程序;通過(guò)DriverManager類獲得表示數(shù)據(jù)庫(kù)連接的Connection類對(duì)象;通過(guò)Connection對(duì)象綁定要執(zhí)行的語(yǔ)句,生成Statement類對(duì)象;執(zhí)行SQL語(yǔ)句,接收?qǐng)?zhí)行結(jié)果集ResultSet;可選的對(duì)結(jié)果集ResultSet類對(duì)象的處理;必要的關(guān)閉ResultSet、Statement和ConnectionJDBC常用API常用的類或者接口作用DriverManager類驅(qū)動(dòng)管理類,支持驅(qū)動(dòng)器和數(shù)據(jù)庫(kù)連接的創(chuàng)建Connection接口代表與某一數(shù)據(jù)庫(kù)的連接Statement接口在連接中執(zhí)行SQL并取得執(zhí)行結(jié)構(gòu)PreparedStatement接口是Statement的子接口,代表預(yù)編譯的SQL聲明CallableStatement接口是Statement的子接口,代表SQL的存儲(chǔ)過(guò)程ResultSet接口代表執(zhí)行SQL后產(chǎn)生的數(shù)據(jù)庫(kù)結(jié)果集DriverManagerJdbc程序中的DriverManager用于加載驅(qū)動(dòng),并創(chuàng)建與數(shù)據(jù)庫(kù)的鏈接,這個(gè)API的常用方法:
DriverManager.registerDriver(newDriver())
DriverManager.getConnection(url,user,password),注意:在實(shí)際開(kāi)發(fā)中并不推薦采用registerDriver方法注冊(cè)驅(qū)動(dòng)。原因有二:一、查看Driver的源代碼可以看到,如果采用此種方式,會(huì)導(dǎo)致驅(qū)動(dòng)程序注冊(cè)兩次,也就是在內(nèi)存中會(huì)有兩個(gè)Driver對(duì)象二、程序依賴mysql的api,脫離mysql的jar包,程序?qū)o(wú)法編譯,將來(lái)程序切換底層數(shù)據(jù)庫(kù)將會(huì)非常麻煩。推薦方式:Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);采用此種方式不會(huì)導(dǎo)致驅(qū)動(dòng)對(duì)象在內(nèi)存中重復(fù)出現(xiàn),并且采用此種方式,程序僅僅只需要一個(gè)字符串,不需要依賴具體的驅(qū)動(dòng),使程序的靈活性更高同樣,在開(kāi)發(fā)中也不建議采用具體的驅(qū)動(dòng)類型指向getConnection方法返回的connection對(duì)象。DriverManagerDriverManager加載Driver類并在DriverManager類中注冊(cè)后,它們即可用來(lái)與數(shù)據(jù)庫(kù)建立連接。當(dāng)調(diào)用DriverManager.getConnection方法發(fā)出連接請(qǐng)求時(shí),DriverManager將檢查每個(gè)驅(qū)動(dòng)程序,查看它是否可以建立連接。 以下代碼是通常情況下用驅(qū)動(dòng)程序建立連接所需所有步驟的示例:DriverManagerDriverManager//加裁驅(qū)動(dòng)程序并自動(dòng)注冊(cè)連接實(shí)例Class.forName("oracle.jdbc.driver.OracleDriver");//設(shè)置URLStringurl="jdbc:oracle:thin:@localhost:1521:inspur";//設(shè)置用戶名和密碼Stringusername="scott";Stringpassword="tiger";//通過(guò)DriverManager向DB發(fā)出連接請(qǐng)求,獲得連接對(duì)象Connectionconn=DriverManager.getConnection(url,username,password);數(shù)據(jù)庫(kù)URLURL用于標(biāo)識(shí)數(shù)據(jù)庫(kù)的位置,程序員通過(guò)URL地址告訴JDBC程序連接哪個(gè)數(shù)據(jù)庫(kù),URL的寫(xiě)法為:jdbc:sqlserver://localhost:1433;DatabaseName=sid協(xié)議子協(xié)議主機(jī)域名:端口數(shù)據(jù)庫(kù)常用數(shù)據(jù)庫(kù)URL地址的寫(xiě)法:Oracle寫(xiě)法:jdbc:oracle:thin:@localhost:1521:sidMySql—jdbc:mysql://localhost:3306/sid數(shù)據(jù)庫(kù)URLConnectionJdbc程序中的Connection,它用于代表數(shù)據(jù)庫(kù)的鏈接,Collection是數(shù)據(jù)庫(kù)編程中最重要的一個(gè)對(duì)象,客戶端與數(shù)據(jù)庫(kù)所有交互都是通過(guò)connection對(duì)象完成的,這個(gè)對(duì)象的常用方法:createStatement():創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送sql的statement對(duì)象prepareStatement(sql):創(chuàng)建向數(shù)據(jù)庫(kù)發(fā)送預(yù)編譯sql的PrepareSatement對(duì)象提高性能解決SQL注入問(wèn)題prepareCall(sql):創(chuàng)建執(zhí)行存儲(chǔ)過(guò)程的callableStatement對(duì)象。setAutoCommit(boolean
autoCommit):設(shè)置事務(wù)是否自動(dòng)提交。commit():在鏈接上提交事務(wù)。---與事務(wù)相關(guān)??!rollback():在此鏈接上回滾事務(wù)。StatementJdbc程序中的Statement對(duì)象用于向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句,Statement對(duì)象常用方法:executeQuery(String
sql):用于向數(shù)據(jù)發(fā)送查詢語(yǔ)句。executeUpdate(String
sql):用于向數(shù)據(jù)庫(kù)發(fā)送insert、update或delete語(yǔ)句execute(Stringsql):用于向數(shù)據(jù)庫(kù)發(fā)送任意sql語(yǔ)句addBatch(String
sql):把多條sql語(yǔ)句放到一個(gè)批處理中。executeBatch():向數(shù)據(jù)庫(kù)發(fā)送一批sql語(yǔ)句執(zhí)行。ResultSetJdbc程序中的ResultSet用于代表Sql語(yǔ)句的執(zhí)行結(jié)果。Resultset封裝執(zhí)行結(jié)果時(shí),采用的類似于表格的方式。ResultSet對(duì)象維護(hù)了一個(gè)指向表格數(shù)據(jù)行的游標(biāo)cursor,初始的時(shí)候,游標(biāo)在第一行之前,調(diào)用ResultSet.next()方法,可以使游標(biāo)指向具體的數(shù)據(jù)行,進(jìn)而調(diào)用方法獲取該行的數(shù)據(jù)。ResultSet既然用于封裝執(zhí)行結(jié)果的,所以該對(duì)象提供的大部分方法都是用于獲取數(shù)據(jù)的get方法:獲取任意類型的數(shù)據(jù)getObject(intindex)getObject(stringcolumnName)獲取指定類型的數(shù)據(jù),例如:
getString(intindex)getString(StringcolumnName)提問(wèn):數(shù)據(jù)庫(kù)中列的類型是varchar,獲取該列的數(shù)據(jù)調(diào)用什么方法?Int類型呢?bigInt類型呢?Boolean類型?常用數(shù)據(jù)類型轉(zhuǎn)換表Jdbc(rs)對(duì)應(yīng)方法返回類型getBooleangetBytes()Booleanbyte[]getByte()BytegetShort()ShortgetInt()IntgetLong()LonggetString()StringgetClobgetBlob()ClobBlobgetDate()java.sql.DategetTime()java.sql.TimegetTimestamp()java.sql.TimestampSQL類型BIT(1)bit(10)TINYINTSMALLINTIntBIGINTCHAR,VARCHAR,LONGVARCHARText(clob)BlobDATETIMETIMESTAMP遍歷查詢結(jié)果ResultSet滾動(dòng)結(jié)果集可滾動(dòng)結(jié)果集可滾動(dòng)結(jié)果集的創(chuàng)建Statementstmt=conn.createStatement(type,concurrency);PreparedStatementpstmt=conn.preparedStatement(type,concurrency);變量type來(lái)設(shè)置是否是可滾動(dòng)的結(jié)果集,可以是以下幾個(gè)ResultSet常量TYPE_FORWARD_ONLY:結(jié)果集不能滾動(dòng)TYPE_SCROLL_INSENSITIVE:結(jié)果集可以滾動(dòng),但是對(duì)數(shù)據(jù)庫(kù)變化不敏感,數(shù)據(jù)庫(kù)查詢生成結(jié)果集后發(fā)生了變化,結(jié)果集不發(fā)生變化。TYPE_SCROLL_SENSITIVE:結(jié)果集可以滾動(dòng),但是對(duì)數(shù)據(jù)庫(kù)變化敏感。ResultSet滾動(dòng)結(jié)果集可更新結(jié)果集更新結(jié)果集的內(nèi)容,數(shù)據(jù)庫(kù)將自動(dòng)更新Statementstmt=conn.createStatement(type,concurrency);PreparedStatementpstmt=conn.preparedStatement(type,concurrency);變量concurrency設(shè)置是否可以更新。ResultSet類的concurrency的值:CONCUR_READ_ONLY結(jié)果集不能用于更新數(shù)據(jù)庫(kù)CONCUR_UPDATABLE結(jié)果集可以更新數(shù)據(jù)庫(kù)。ResultSet滾動(dòng)結(jié)果集ResultSet還提供了對(duì)結(jié)果集進(jìn)行滾動(dòng)和更新的方法Statementstmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);next():移動(dòng)到下一行previous():移動(dòng)到前一行absolute(introw):移動(dòng)到指定行beforeFirst():移動(dòng)resultSet的最前面afterLast():移動(dòng)到resultSet的最后面updateRow():更新行數(shù)據(jù)釋放資源Jdbc程序運(yùn)行完后,切記要釋放程序在運(yùn)行過(guò)程中,創(chuàng)建的那些與數(shù)據(jù)庫(kù)進(jìn)行交互的對(duì)象,這些對(duì)象通常是ResultSet,Statement和Connection對(duì)象。特別是Connection對(duì)象,它是非常稀有的資源,用完后必須馬上釋放,如果Connection不能及時(shí)、正確的關(guān)閉,極易導(dǎo)致系統(tǒng)宕機(jī)。Connection的使用原則是盡量晚創(chuàng)建,盡量早的釋放。為確保資源釋放代碼能運(yùn)行,資源釋放代碼也一定要放在finally語(yǔ)句中。1、查詢出T_USER表中所有的數(shù)據(jù)通過(guò)T_USER表實(shí)現(xiàn)用戶登錄驗(yàn)證,實(shí)現(xiàn)對(duì)T_USER表的增刪改2、編寫(xiě)工具類簡(jiǎn)化增刪改查操作。(異常暫不處理)使用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查Jdbc中的statement對(duì)象用于向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句,想完成對(duì)數(shù)據(jù)庫(kù)的增刪改查,只需要通過(guò)這個(gè)對(duì)象向數(shù)據(jù)庫(kù)發(fā)送增刪改查語(yǔ)句即可。Statement對(duì)象的executeUpdate方法,用于向數(shù)據(jù)庫(kù)發(fā)送增、刪、改的sql語(yǔ)句,executeUpdate執(zhí)行完后,將會(huì)返回一個(gè)整數(shù)(即增刪改語(yǔ)句導(dǎo)致了數(shù)據(jù)庫(kù)幾行數(shù)據(jù)發(fā)生了變化)。Statement.executeQuery方法用于向數(shù)據(jù)庫(kù)發(fā)送查詢語(yǔ)句,executeQuery方法返回代表查詢結(jié)果的ResultSet對(duì)象。使用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行添加操作使用executeUpdate(Stringsql)方法完成數(shù)據(jù)添加操作,示例操作: Statementst=conn.createStatement(); Stringsql="insertintouser(….)values(…..)"; intnum=st.executeUpdate(sql); if(num>0){ System.out.println("插入成功?。。?); }使用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行修改操作使用executeUpdate(Stringsql)方法完成數(shù)據(jù)修改操作,示例操作: Statementst=conn.createStatement(); Stringsql=“updateusersetname=‘’wherename=‘’"; intnum=st.executeUpdate(sql); if(num>0){ System.out.println(“修改成功!??!"); }使用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行刪除操作使用executeUpdate(Stringsql)方法完成數(shù)據(jù)刪除操作,示例操作: Statementst=conn.createStatement(); Stringsql=“deletefromuserwhereid=1;
intnum=st.executeUpdate(sql); if(num>0){
System.out.println(“刪除成功?。?!"); }使用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢操作使用executeQuery(Stringsql)方法完成數(shù)據(jù)查詢操作,示例操作: Statementst=conn.createStatement(); Stringsql=“select*fromuserwhereid=1;
ResultSet
rs=st.executeQuery(sql); while(rs.next()){ //根據(jù)獲取列的數(shù)據(jù)類型,分別調(diào)用rs的相應(yīng)方法
//映射到j(luò)ava對(duì)象中
}PreparedStatementPreparedStatement接口 PreparedStatement實(shí)例包含已編譯的SQL語(yǔ)句。就是說(shuō)使SQL語(yǔ)句“準(zhǔn)備好”。包含于PreparedStatement對(duì)象中的SQL語(yǔ)句可具有一個(gè)或多個(gè)IN參數(shù)。IN參數(shù)的值在SQL語(yǔ)句創(chuàng)建時(shí)未被指定。相反的,該語(yǔ)句為每個(gè)IN參數(shù)保留一個(gè)問(wèn)號(hào)(“?”)作為占位符。每個(gè)問(wèn)號(hào)的值必須在該語(yǔ)句執(zhí)行之前,通過(guò)適當(dāng)?shù)膕etXXX方法來(lái)提供。該P(yáng)reparedStatement接口繼承Statement,并與之在三方面有所不同:PreparedStatementPreperedStatement可以避免SQL注入的問(wèn)題。Statement會(huì)使數(shù)據(jù)庫(kù)頻繁編譯SQL,可能造成數(shù)據(jù)庫(kù)緩沖區(qū)溢出。PreparedStatement可對(duì)SQL進(jìn)行預(yù)編譯,從而提高數(shù)據(jù)庫(kù)的執(zhí)行效率。作為Statement的子類,PreparedStatement繼承了Statement的所有功能。另外它還添加了一整套方法,用于設(shè)置發(fā)送給數(shù)據(jù)庫(kù)以取代IN參數(shù)占位符的值。同時(shí),三種方法execute、executeQuery和executeUpdate已被更改以使之不再需要參數(shù)。這些方法的Statement形式(接受SQL語(yǔ)句參數(shù)的形式)不應(yīng)該用于PreparedStatement對(duì)象。PreparedStatement創(chuàng)建PreparedStatement對(duì)象 以下的代碼段(其中con是Connection對(duì)象)創(chuàng)建包含帶兩個(gè)IN參數(shù)占位符的SQL語(yǔ)句的PreparedStatement對(duì)象: PreparedStatementpstmt=con.prepareStatement("UPDATEtable4SETm=?WHEREx=?");pstmt對(duì)象包含語(yǔ)句“UPDATEtable4SETm=?WHEREx=?”,它已發(fā)送給DBMS,并為執(zhí)行作好了準(zhǔn)備。 2傳遞IN參數(shù):
PreparedStatement使用PreparedStatement對(duì)象
在執(zhí)行PreparedStatement對(duì)象之前,必須設(shè)置每個(gè)?參數(shù)的值。這可通過(guò)調(diào)用setXXX方法來(lái)完成,其中XXX是與該參數(shù)相應(yīng)的類型。例如,如果參數(shù)具有Java類型long,則使用的方法就是setLong。setXXX方法的第一個(gè)參數(shù)是要設(shè)置的參數(shù)的序數(shù)位置,第二個(gè)參數(shù)是設(shè)置給該參數(shù)的值。例如,以下代碼將第一個(gè)參數(shù)設(shè)為123456789,第二個(gè)參數(shù)設(shè)為100000000:
一旦設(shè)置了給定語(yǔ)句的參數(shù)值,就可用它多次執(zhí)行該語(yǔ)句,直到調(diào)用clearParameters方法清除它為止。在連接的缺省模式下(啟用自動(dòng)提交),當(dāng)語(yǔ)句完成時(shí)將自動(dòng)提交或還原該語(yǔ)句。 pstmt.setLong(1,123456789);pstmt.setLong(2,100000000);PreparedStatement使用PreparedStatement對(duì)象
如果基本數(shù)據(jù)庫(kù)和驅(qū)動(dòng)程序在語(yǔ)句提交之后仍保持這些語(yǔ)句的打開(kāi)狀態(tài),則同一個(gè)PreparedStatement可執(zhí)行多次。如果這一點(diǎn)不成立,那么試圖通過(guò)使用PreparedStatement對(duì)象代替Statement對(duì)象來(lái)提高性能是沒(méi)有意義的。 利用pstmt(前面創(chuàng)建的PreparedStatement對(duì)象),以下代碼示例了如何設(shè)置兩個(gè)參數(shù)占位符的值并執(zhí)行pstmt10次。如上所述,為做到這一點(diǎn),數(shù)據(jù)庫(kù)不能關(guān)閉pstmt。在該示例中,第一個(gè)參數(shù)被設(shè)置為"Hi"并保持為常數(shù)。在for循環(huán)中,每次都將第二個(gè)參數(shù)設(shè)置為不同的值:從0開(kāi)始,到9結(jié)束。pstmt.setString(1,"Hi");for(inti=0;i<10;i++){
pstmt.setInt(2,i);
introwCount=pstmt.executeUpdate();}PreparedStatement使用PreparedStatement對(duì)象 IN參數(shù)中數(shù)據(jù)類型的一致性
setXXX方法中的XXX是Java類型。它是一種隱含的JDBC類型(一般SQL類型),因?yàn)轵?qū)動(dòng)程序?qū)袹ava類型映射為相應(yīng)的JDBC類型,并將該JDBC類型發(fā)送給數(shù)據(jù)庫(kù)。例如,以下代碼段將PreparedStatement對(duì)象pstmt的第二個(gè)參數(shù)設(shè)置為44,Java類型為short: 驅(qū)動(dòng)程序?qū)?4作為JDBCSMALLINT發(fā)送給數(shù)據(jù)庫(kù),它是Javashort類型的標(biāo)準(zhǔn)映射。 程序員的責(zé)任是確保將每個(gè)IN參數(shù)的Java類型映射為與數(shù)據(jù)庫(kù)所需的JDBC數(shù)據(jù)類型兼容的JDBC類型。不妨考慮數(shù)據(jù)庫(kù)需要JDBCSMALLINT的情況。如果使用方法setByte,則驅(qū)動(dòng)程序?qū)DBCTINYINT發(fā)送給數(shù)據(jù)庫(kù)。這是可行的,因?yàn)樵S多數(shù)據(jù)庫(kù)可從一種相關(guān)的類型轉(zhuǎn)換為另一種類型,并且通常TINYINT可用于SMALLINT適用的任何地方pstmt.setShort(2,44);CallableStatementCallableStatement對(duì)象
CallableStatement對(duì)象為所有的DBMS提供了一種以標(biāo)準(zhǔn)形式調(diào)用存儲(chǔ)過(guò)程的方法。存儲(chǔ)過(guò)程儲(chǔ)存在數(shù)據(jù)庫(kù)中。對(duì)存儲(chǔ)過(guò)程的調(diào)用是CallableStatement對(duì)象所含的內(nèi)容。這種調(diào)用是用一種換碼語(yǔ)法來(lái)寫(xiě)的,有兩種形式:一種形式帶結(jié)果參數(shù),另一種形式不帶結(jié)果參數(shù)。結(jié)果參數(shù)是一種輸出(OUT)參數(shù),是存儲(chǔ)過(guò)程的返回值。兩種形式都可帶有數(shù)量可變的輸入(IN參數(shù))、輸出(OUT參數(shù))或輸入和輸出(INOUT參數(shù))的參數(shù)。問(wèn)號(hào)將用作參數(shù)的占位符。CallableStatementCallableStatement對(duì)象 在JDBC中調(diào)用已儲(chǔ)存過(guò)程的語(yǔ)法如下所示。注意,方括號(hào)表示其間的內(nèi)容是可選項(xiàng);方括號(hào)本身并不是語(yǔ)法的組成部份。帶參數(shù)的: {call過(guò)程名[(?,?,...)]}不帶參數(shù)的: {call過(guò)程名} 通常,創(chuàng)建CallableStatement對(duì)象的人應(yīng)當(dāng)知道所用的DBMS是支持存儲(chǔ)過(guò)程的,并且知道這些存儲(chǔ)過(guò)程都是些什么。然而,如果需要檢查,多種DatabaseMetaData方法都可以提供這樣的信息。例如,如果DBMS支持存儲(chǔ)過(guò)程的調(diào)用,則supportsStoredProcedures方法將返回true,而getProcedures方法將返回對(duì)存儲(chǔ)過(guò)程的描述。CallableStatement繼承Statement的方法(它們用于處理一般的SQL語(yǔ)句),還繼承了PreparedStatement的方法(它們用于處理IN參)。CallableStatement創(chuàng)建CallableStatement對(duì)象
CallableStatement對(duì)象是用Connection方法prepareCall創(chuàng)建的。下例創(chuàng)建CallableStatement的實(shí)例,其中含有對(duì)存儲(chǔ)過(guò)程INSERTPRO_T1T2調(diào)用。
其中?占位符為IN、OUT還是INOUT參數(shù),取決于存儲(chǔ)過(guò)程INSERTPRO_T1T2Stringsql2="{callINSERTPRO_T1T2(?,?)}";CallableStatementcallpro2=conn.prepareCall(sql2);CallableStatementIN和OUT參數(shù)將IN參數(shù)傳給CallableStatement對(duì)象是通過(guò)setXXX方法完成的。該方法繼承自PreparedStatement。所傳入?yún)?shù)的類型決定了所用的setXXX方法(例如,用setFloat來(lái)傳入float值等)。如果存儲(chǔ)過(guò)程返回OUT參數(shù),則在執(zhí)行CallableStatement對(duì)象以前必須先注冊(cè)每個(gè)OUT參數(shù)的JDBC類型(這是必需的,因?yàn)槟承〥BMS要求JDBC類型)。注冊(cè)JDBC類型是用registerOutParameter方法來(lái)完成的。語(yǔ)句執(zhí)行完后,CallableStatement的getXXX方法將取回參數(shù)值。正確的getXXX方法是為各參數(shù)所注冊(cè)的JDBC類型所對(duì)應(yīng)的Java類型。換言之,registerOutParameter使用的是JDBC類型(因此它與數(shù)據(jù)庫(kù)返回的JDBC類型匹配),而getXXX將之轉(zhuǎn)換為Java類型。CallableStatementIN和OUT參數(shù)
作為示例,下述代碼先注冊(cè)O(shè)UT參數(shù),執(zhí)行由cstmt所調(diào)用的已儲(chǔ)存過(guò)程,然后檢索在OUT參數(shù)中返回的值。方法getByte從第一個(gè)OUT參數(shù)中取出一個(gè)Java字節(jié),而getBigDecimal從第二個(gè)OUT參數(shù)中取出一個(gè)BigDecimal對(duì)象(小數(shù)點(diǎn)后面帶三位數(shù)):
CallableStatement與ResultSet不同,它不提供用增量方式檢索大OUT值的特殊機(jī)制。CallableStatementcstmt=con.prepareCall("{callgetTestData(?,?)}");cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.registerOutParameter(2,java.sql.Types.DECIMAL,3);cstmt.executeQuery();bytex=cstmt.getByte(1);java.math.BigDecimaln=cstmt.getBigDecimal(2,3);CallableStatementIN和OUT參數(shù)
既支持輸入又接受輸出的參數(shù)(INOUT參數(shù))除了調(diào)用registerOutParameter方法外,還要求調(diào)用適當(dāng)?shù)膕etXXX方法(該方法是從PreparedStatement繼承來(lái)的)。setXXX方法將參數(shù)值設(shè)置為輸入?yún)?shù),而registerOutParameter方法將它的JDBC類型注冊(cè)為輸出參數(shù)。setXXX方法提供一個(gè)Java值,而驅(qū)動(dòng)程序先把這個(gè)值轉(zhuǎn)換為JDBC值,然后將它送到數(shù)據(jù)庫(kù)中。這種IN值的JDBC類型和提供給registerOutParameter方法的JDBC類型應(yīng)該相同。然后,要檢索輸出值,就要用對(duì)應(yīng)的getXXX方法。例如,Java類型為byte的參數(shù)應(yīng)該使用方法setByte來(lái)賦輸入值。應(yīng)該給registerOutParameter提供類型為T(mén)INYINT的JDBC類型,同時(shí)應(yīng)使用getByte來(lái)檢索輸出值。 下例假設(shè)有一個(gè)已儲(chǔ)存過(guò)程reviseTotal,其唯一參數(shù)是INOUT參數(shù)。方法setByte把此參數(shù)設(shè)為25,驅(qū)動(dòng)程序?qū)阉鳛镴DBCTINYINT類型送到數(shù)據(jù)庫(kù)中。接著,registerOutParameter將該參數(shù)注冊(cè)為JDBCTINYINT。執(zhí)行完該存儲(chǔ)過(guò)程后,將返回一個(gè)新的JDBCTINYINT值。方法getByte將把這個(gè)新值作為Javabyte類型檢索。CallableStatementcstmt=con.prepareCall("{callreviseTotal(?)}");cstmt.setByte(1,25);cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.executeUpdate();bytex=cstmt.getByte(1);CallableStatementIN和OUT參數(shù)
檢索作為OUT參數(shù)的NULL值 返回到OUT參數(shù)中的值可能會(huì)是JDBCNULL。當(dāng)出現(xiàn)這種情形時(shí),將對(duì)JDBCNULL值進(jìn)行轉(zhuǎn)換以使getXXX方法所返回的值為null、0或false,這取決于getXXX方法類型。對(duì)于ResultSet對(duì)象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull進(jìn)行檢測(cè)。如果getXXX方法讀取的最后一個(gè)值是JDBCNULL,則該方法返回true,否則返回false。CallableStatement使用例:try{Class.forName("oracle.jdbc.OracleDriver");Connectionconn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:teacher","scott","tiger");//調(diào)用存儲(chǔ)過(guò)程Stringcall="{callget_emp(?,?,?)}";CallableStatementpstmt=conn.prepareCall(call);pstmt.setString(1,"CLARK");pstmt.registerOutParameter(2,Types.VARCHAR);pstmt.registerOutParameter(3,Types.VARCHAR);pstmt.execute();System.out.println(pstmt.getString(2));System.out.println(pstmt.getString(3));//調(diào)用函數(shù)Stringfun="{?=callfun_emp(?)}";CallableStatementpstmt1=conn.prepareCall(fun);pstmt1.registerOutParameter(1,Types.VARCHAR);pstmt1.setString(2,"CLARK");pstmt1.execute();System.out.println(pstmt1.getString(1));}catch(ClassNotFoundExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}catch(SQLExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}ResultSetMetaDataResultSetMetaData結(jié)果集元數(shù)據(jù)提供了有關(guān)從數(shù)據(jù)庫(kù)查詢返回的結(jié)果集對(duì)象的額外信息,由ResultSetMetaData對(duì)象提供數(shù)據(jù)庫(kù)元數(shù)據(jù)提供了數(shù)據(jù)庫(kù)的相關(guān)信息,由DataBaseMetaData對(duì)象提供//從元數(shù)據(jù)中獲得列數(shù)(常用)ResultSetMetaDatarsmd;rsmd=results.getMetaData();numCols=rsmd.getColumnCount();使用JDBC進(jìn)行批處理業(yè)務(wù)場(chǎng)景:當(dāng)需要向數(shù)據(jù)庫(kù)發(fā)送一批SQL語(yǔ)句執(zhí)行時(shí),應(yīng)避免向數(shù)據(jù)庫(kù)一條條的發(fā)送執(zhí)行,而應(yīng)采用JDBC的批處理機(jī)制,以提升執(zhí)行效率。實(shí)現(xiàn)批處理有兩種方式,第一種方式:Statement.addBatch(sql)執(zhí)行批處理SQL語(yǔ)句executeBatch()方法:執(zhí)行批處理命令clearBatch()方法:清除批處理命令使用JDBC進(jìn)行批處理Connectionconn=null;Statementst=null;ResultSetrs=null;try{conn=JdbcUtil.getConnection();Stringsql1="insertintoperson(name,password,email,birthday) values('kkk','123','abc@','1978-08-08')";Stringsql2="updateusersetpassword='123456'whereid=3";st=conn.createStatement();st.addBatch(sql1);//把SQL語(yǔ)句加入到批命令中st.addBatch(sql2);//把SQL語(yǔ)句加入到批命令中st.executeBatch();}finally{ JdbcUtil.free(conn,st,rs);}使用JDBC進(jìn)行批處理采用Statement.addBatch(sql)方式實(shí)現(xiàn)批處理:優(yōu)點(diǎn):可以向數(shù)據(jù)庫(kù)發(fā)送多條不同的SQL語(yǔ)句。缺點(diǎn):SQL語(yǔ)句沒(méi)有預(yù)編譯。當(dāng)向數(shù)據(jù)庫(kù)發(fā)送多條語(yǔ)句相同,但僅參數(shù)不同的SQL語(yǔ)句時(shí),需重復(fù)寫(xiě)上很多條SQL語(yǔ)句。例如:
Insertintouser(name,password)values(‘a(chǎn)a’,’111’); Insertintouser(name,password)values(‘bb’,’222’); Insertintouser(name,password)values(‘cc’,’333’); Insertintouser(name,password)values(‘dd’,’444’);使用JDBC進(jìn)行批處理實(shí)現(xiàn)批處理的第二種方式:PreparedStatement.addBatch()使用JDBC進(jìn)行批處理conn=JdbcUtil.getConnection();Stringsql="insertintoperson(name,password,email,birthday)values(?,?,?,?)";st=conn.prepareStatement(sql);for(inti=0;i<50000;i++
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度高空作業(yè)安全生產(chǎn)施工合同集2篇
- 二零二五年度綠色環(huán)保木工支模項(xiàng)目合同4篇
- 2025版木箱紙箱包裝設(shè)計(jì)創(chuàng)新與市場(chǎng)推廣合同4篇
- 2025年度個(gè)人購(gòu)房合同產(chǎn)權(quán)轉(zhuǎn)移登記流程4篇
- 危險(xiǎn)品運(yùn)輸車(chē)輛駕駛員崗前培訓(xùn)考核試卷
- 2025版二零二五年度現(xiàn)代木工清工分包合同模板4篇
- 【新課標(biāo)Ⅲ卷】高三第二次全國(guó)大聯(lián)考語(yǔ)文試卷(含答案)
- 愛(ài)學(xué)習(xí)有自信幼兒舞蹈創(chuàng)編15課件講解
- 2025年專業(yè)期刊發(fā)行協(xié)議
- 2025年合伙勞動(dòng)分工協(xié)議
- 2024公路瀝青路面結(jié)構(gòu)內(nèi)部狀況三維探地雷達(dá)快速檢測(cè)規(guī)程
- 2024年高考真題-地理(河北卷) 含答案
- 2024光儲(chǔ)充一體化系統(tǒng)解決方案
- 處理后事授權(quán)委托書(shū)
- 食材配送服務(wù)方案投標(biāo)方案(技術(shù)方案)
- 足療店?duì)I銷策劃方案
- 封條(標(biāo)準(zhǔn)A4打印封條)
- 2024年北京控股集團(tuán)有限公司招聘筆試參考題庫(kù)含答案解析
- 延遲交稿申請(qǐng)英文
- 運(yùn)動(dòng)技能學(xué)習(xí)與控制課件第十章動(dòng)作技能的指導(dǎo)與示范
- 石油天然氣建設(shè)工程交工技術(shù)文件編制規(guī)范(SYT68822023年)交工技術(shù)文件表格儀表自動(dòng)化安裝工程
評(píng)論
0/150
提交評(píng)論