




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、JDBC(Java Data Base Connectivity,java數(shù)據(jù)庫連接),由一些接口和類構(gòu)成的API。JDBC是J2SE的一部分,由java.sql.javax.sql包組成。JDBC的核心是接口,Driver實(shí)現(xiàn)了JDBC的接口。SUN公司設(shè)計(jì)接口(或者規(guī)范、標(biāo)準(zhǔn)),生產(chǎn)廠商來實(shí)現(xiàn)這些接口,即它們各自的Driver。JAVA程序包括JAVA應(yīng)用程序和小應(yīng)用程序,主要是根據(jù)JDBC方法實(shí)現(xiàn)對數(shù)據(jù)庫的訪問和操作。完成的主要任務(wù)有:請求與數(shù)據(jù)庫建立連接;向數(shù)據(jù)庫發(fā)送SQL請求;為結(jié)果集定義存儲應(yīng)用和數(shù)據(jù)類型;查詢結(jié)果;處理錯誤;控制傳輸、提交及關(guān)閉連接到呢個操作。JDBC管理器為我們
2、提供了一個“驅(qū)動程序管理器”,它能夠動態(tài)地管理和維護(hù)數(shù)據(jù)庫查詢所需要的所有驅(qū)動程序?qū)ο?,?shí)現(xiàn)JAVA程序與特定驅(qū)動程序的連接,從而體現(xiàn)JDBC的“與平臺無關(guān)”這一特點(diǎn)。它完成的主要任務(wù)有:為特定數(shù)據(jù)庫選擇驅(qū)動程序;處理JDBC初始化調(diào)用;為每個驅(qū)動程序提供JDBC功能的入口;為JDBC調(diào)用執(zhí)行參數(shù)等。驅(qū)動程序處理JDBC方法,想特定數(shù)據(jù)庫發(fā)送SQL請求,并為JAVA程序獲取結(jié)果。在必要的時候,驅(qū)動程序可以翻譯或優(yōu)化請求,使SQL請求符合DBMS支持的語言。驅(qū)動程序可以完成下列任務(wù):建立與數(shù)據(jù)庫的連接;向數(shù)據(jù)庫發(fā)送請求;用戶程序請求時,執(zhí)行翻譯;將錯誤代碼格式化成標(biāo)準(zhǔn)的JDBC錯誤代碼等。JDB
3、C是獨(dú)立于數(shù)據(jù)庫管理系統(tǒng)的,而每個數(shù)據(jù)庫系統(tǒng)均有自己的協(xié)議與客戶機(jī)通信,因此,JDBC利用數(shù)據(jù)庫驅(qū)動程序來使用這些數(shù)據(jù)庫引擎。JDBC驅(qū)動程序有數(shù)據(jù)庫軟件商和第三方的軟件商提供,因此,根據(jù)編程所使用的數(shù)據(jù)庫系統(tǒng)不同,所需要的驅(qū)動程序也有所不同。應(yīng)用程序JDBCDB2 DriverOracleDB2MySQL四類JDBC驅(qū)動程序盡管存在數(shù)據(jù)庫語言標(biāo)準(zhǔn)SQL-92,但由于數(shù)據(jù)庫技術(shù)發(fā)展的原因,各公司開發(fā)的SQL存在著一定的差異。因此,當(dāng)我們想要連接數(shù)據(jù)庫并存取其中的數(shù)據(jù)時,選擇適當(dāng)類型的JDBC驅(qū)動程序是非常重要的。目前JDBC驅(qū)動程序可細(xì)分為四種類型,如下圖所示。不同類型的JDBC驅(qū)動程序有著不
4、一樣的特性和使用方法。下面將說明不同類型的JDBC驅(qū)動程序之間的差異。類型1:JDBC-ODBC Bridge。這類驅(qū)動程序的特色是必須在我們的計(jì)算機(jī)上事先安裝好ODBC驅(qū)動程序,然后通過JDBC-ODBC Bridge的轉(zhuǎn)換,把JAVA程序中使用的JDBC API轉(zhuǎn)換成ODBC API,進(jìn)而通過ODBC來存取數(shù)據(jù)庫。類型2:JDBC-Native API Bridge。同類型1一樣,這類驅(qū)動程序也必須在我們的計(jì)算機(jī)上先安裝好特定的驅(qū)動程序(類似ODBC),然后通過JDBC-Native API Bridge的轉(zhuǎn)換,把JAVA程序中使用的JDBC API轉(zhuǎn)換成Native API,進(jìn)而存取數(shù)據(jù)
5、庫。類型3:JDBC-Middleware。必須在安裝數(shù)據(jù)庫管理系統(tǒng)的服務(wù)器端加裝軟件(Middleware),中介軟件會負(fù)責(zé)所有存取數(shù)據(jù)庫時必要的轉(zhuǎn)換。類型4:Pure JDBC Driver。使用這類驅(qū)動程序時無需安裝任何附加的軟件,所有存取數(shù)據(jù)庫的操作都直接有JDBC驅(qū)動來完成。用JDBC連接Oracle數(shù)據(jù)庫方法一:在Tomcat中配置Oracle的驅(qū)動程序Oracle JDBC驅(qū)動程序的位置:H:Oraclejdbclibclasses12.jar將此驅(qū)動程序拷貝到Tomcat的安裝目錄的lib文件之中:C:Program Filesapache-tomcat-6.0.14lib此時
6、Tomcat就可以連接到oracle驅(qū)動程序Oracle驅(qū)動名稱:使用Class.forName()方法加載相應(yīng)的數(shù)據(jù)庫驅(qū)動程序:Class.forName(oracle.jdbc.driver.OracleDriver);oracle.jdbc.driver.OracleDriver我們不必死記,在Oracle驅(qū)動程序classes12.jar下面的oralce.jdbc.dreiver包中就可找到相應(yīng)OracleDriver.class。Oracle連接地址:String URL=”jdbc:oracle:thin::1521:myOracle”; 或者:String U
7、RL=”jdbc:oracle:thin:localhost:1521:myOracle”;Connection ct=DriverManager.getConnection(URL);其中jdbc是協(xié)議,1521是Oracle默認(rèn)的端口號,myOracle是數(shù)據(jù)庫的名稱與使用JDBC-ODBC類似,只是連接的驅(qū)動名稱和驅(qū)動地址改變。方法二:JDBC-ODBC Bridge方法Oracle驅(qū)動名稱:使用Class.forName()方法加載相應(yīng)的數(shù)據(jù)庫驅(qū)動程序:Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);Oracle連接地址:String URL=”
8、jdbc:odbc:odbcName”;Connection ct=DriverManager.getConnection(URL);其中odbcName是我們設(shè)置的要創(chuàng)建的數(shù)據(jù)源。連接數(shù)據(jù)庫的步驟:1、注冊驅(qū)動(只做一次)Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);2、建立連接(Connection)String URL=”jdbc:odbc:odbcName”;Connection ct=DriverManager.getConnection(URL,”scott”,”tiger”);數(shù)據(jù)庫連接(Connection)是非常稀有的資源,用完后必須
9、馬上釋放,如果Connection不能及時正確的關(guān)閉或釋放將導(dǎo)致系統(tǒng)脫機(jī)。Connection的使用原則是盡量晚的創(chuàng)建,盡量早的釋放。3、創(chuàng)建執(zhí)行SQL的語句(Statement)Statement st=ct.createStatement();4、執(zhí)行語句(ResultSet)ResultSet rs=st.executeQuery(“select * from emp”);5、處理執(zhí)行結(jié)果While(rs.next()System.out.println(“用戶名:”+rs.getString(2);6、關(guān)閉和釋放資源rs.close();sm.close();ct.close();為了
10、確保JDBC資源不在出現(xiàn)異?;蝈e誤等情況下被不正常關(guān)閉,我們應(yīng)該在用完JDBC資源之后關(guān)閉且釋放他們。JDBC連接池提供了JDBC連接定義和數(shù)目有限的連接,如果數(shù)量不夠,就需要長時間等待。不正常關(guān)閉JDBC連接會導(dǎo)致等待回收無效的JDBC連接。只有正常的關(guān)閉和釋放JDBC連接,JDBC資源才可以被快速的重用,使性能得到改善。為了確保構(gòu)建的代碼在所有的情況下,甚至是異常和錯誤條件下,都能關(guān)閉和釋放JDBC資源。一下代碼顯示了JDBC資源的獲得和使用都封裝在“Try-Catch-Finally”結(jié)構(gòu)中。其中,在finally子句中處理JDBC資源的關(guān)閉,使所有情況下關(guān)閉都將發(fā)生。為了簡潔,此代碼中
11、只把異常拋出并為對異常進(jìn)行處理。public static void main(String args) throws ExceptionString url=jdbc:oracle:thin:localhost:1521:myOracle;Connection ct=null;Statement st=null;ResultSet rs=null;try /1.加載驅(qū)動Class.forName(oracle.jdbc.driver.OracleDriver);/2.得到連接ct=DriverManager.getConnection(url, scott,tiger);/創(chuàng)建執(zhí)行的SQL語
12、句st=ct.createStatement();/執(zhí)行語句rs=st.executeQuery(select * from emp);/處理執(zhí)行結(jié)果while(rs.next()/用戶名System.out.println(用戶名:+rs.getString(2); finallytryif(rs!=null)rs.close();finallytryif(st!=null)st.close();finallyif(ct!=null)ct.close();代碼優(yōu)化:新建一個(public final)工具類JdbcUtils,把優(yōu)化后的代碼都放在這個類里面。由于這個類不需要構(gòu)造實(shí)例,因此我們
13、我們定義一個private的構(gòu)造方法,這樣別人就無法new一個對象了。訪問這個類有兩種方式:一種是單例模式,但是比較復(fù)雜;另一種是提供一些靜態(tài)方法。1、由于驅(qū)動只需要注冊一次,我們知道靜態(tài)代碼塊只有類被裝載到虛擬機(jī)的時候才被執(zhí)行一次,因此,我們把注冊驅(qū)動語句放在一個靜態(tài)的代碼塊中。statictry Class.forName(jdbc:odbc:wanghao); catch (ClassNotFoundException e) throw new ExceptionInInitializerError(e);2、當(dāng)我們的增、刪、改、查的操作很多時,如果程序中每個方法都有URL、用戶名和密碼
14、,我們修改起來就會很麻煩。我們也需要對這一塊優(yōu)化,把他們放到JdbcUtils中,這樣就可以實(shí)現(xiàn)“一改全改”。private static String url=sun.jdbc.odbc.JdbcOdbcDriver;private static String user=scott;private static String password=tiger;3、建立連接語句我們也可以把它放在JdbcUtils的一個靜態(tài)方法中,當(dāng)我們需要鏈接時,我們就到JdbcUtils中去取。public static Connection getConnection() throws SQLExceptio
15、nreturn DriverManager.getConnection(url, user, password);4、對釋放資源部分進(jìn)行優(yōu)化。public static void free(ResultSet rs,Statement st,Connection ct)tryif(rs!=null)rs.close();catch(SQLException e)e.printStackTrace();finallytryif(st!=null)st.close();catch(SQLException e)e.printStackTrace();finallyif(ct!=null)try c
16、t.close(); catch (SQLException e) e.printStackTrace();完整程序代碼如下所示:package com.wanghao.jdbc;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;public class Base /* * param args * throws Exception */public static void main(String args) throws Exception / TODO Auto-generated
17、method stubtest();static void test()throws ExceptionConnection ct=null;Statement st=null;ResultSet rs=null;try /2.得到連接ct=JdbcUtils.getConnection();/創(chuàng)建執(zhí)行的SQL語句st=ct.createStatement();/執(zhí)行語句rs=st.executeQuery(select * from emp);/處理執(zhí)行結(jié)果while(rs.next()/用戶名System.out.println(用戶名:+rs.getString(2); finallyJ
18、dbcUtils.free(rs, st, ct);/工具類JdbcUtilsimport java.sql.Statement;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;public final class JdbcUtils private JdbcUtils()/private static String url=jdbc:odbc:wanghao;private static String url=jdbc
19、:oracle:thin:localhost:1521:myOracle;private static String user=scott;private static String password=tiger;statictry /Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);Class.forName(oracle.jdbc.driver.OracleDriver); catch (ClassNotFoundException e) throw new ExceptionInInitializerError(e);public static Co
20、nnection getConnection() throws SQLExceptionreturn DriverManager.getConnection(url, user, password);public static void free(ResultSet rs,Statement st,Connection ct)tryif(rs!=null)rs.close();catch(SQLException e)e.printStackTrace();finallytryif(st!=null)st.close();catch(SQLException e)e.printStackTra
21、ce();finallyif(ct!=null)try ct.close(); catch (SQLException e) e.printStackTrace();SQL注入,PreparedStatement和Statement 在SQL中包含特殊字符或SQL的關(guān)鍵字(如:or 1 or)時Statement將出現(xiàn)不可預(yù)料的結(jié)果(出現(xiàn)異常或查詢的結(jié)果不正確),可用PreparedStatement來解決。PreparedStatement(從Statement擴(kuò)展而來)相對Statement的優(yōu)點(diǎn):1、沒有SQL注入的問題。2、Statement會使數(shù)據(jù)庫頻繁編譯SQL,可能會造成數(shù)據(jù)庫緩
22、沖區(qū)溢出。3、數(shù)據(jù)庫和驅(qū)動可以對PreparedStatement進(jìn)行優(yōu)化(只有在相關(guān)聯(lián)的數(shù)據(jù)庫連接沒有關(guān)閉的情況下有效)。為什么要始終使用PreparedStatement代替Statement?一.代碼的可讀性和可維護(hù)性.雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護(hù)性上來說.都比直接用Statement的代碼高很多檔次,大家可以通過下面的例子:stmt.executeUpdate(insert into tb_name (col1,col2,col2,col4) values (+var1+,+var2+,+var3+
23、,+var4+);注意Statement和PreparedStatement語句上的區(qū)別:Statement是在執(zhí)行的時候才傳入SQL語句,而PreparedStatement在創(chuàng)建的時候就已經(jīng)傳入了SQL語句。perstmt = con.prepareStatement(insert into tb_name (col1,col2,col2,col4) values (?,?,?,?);perstmt.setString(1,var1);perstmt.setString(2,var2);perstmt.setString(3,var3);perstmt.setString(4,var4);
24、perstmt.executeUpdate();二.PreparedStatement盡最大可能提高性能.每一種數(shù)據(jù)庫都會盡最大努力對預(yù)編譯語句提供最大的性能優(yōu)化.因?yàn)轭A(yù)編譯語句有可能被重復(fù)調(diào)用.所以語句在被DB的編譯器編譯后的執(zhí)行代碼被緩存下來,那么下次調(diào)用時只要是相同的預(yù)編譯語句就不需要編譯,只要將參數(shù)直接傳入編譯過的語句執(zhí)行代碼中(相當(dāng)于一個涵數(shù))就會得到執(zhí)行.這并不是說只有一個Connection中多次執(zhí)行的預(yù)編譯語句被緩存,而是對于整個DB中,只要預(yù)編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執(zhí)行.而statement的語句中,即使是相同一操作,而由于每次
25、操作的數(shù)據(jù)不同所以使整個語句相匹配的機(jī)會極小,幾乎不太可能匹配.比如:insert into tb_name (col1,col2) values (11,22);insert into tb_name (col1,col2) values (11,23);即使是相同操作但因?yàn)閿?shù)據(jù)內(nèi)容不一樣,所以整個語句本身不能匹配,沒有緩存語句的意義.事實(shí)是沒有數(shù)據(jù)庫會對普通語句編譯后的執(zhí)行代碼緩存.當(dāng)然并不是所有預(yù)編譯語句都一定會被緩存,數(shù)據(jù)庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預(yù)編譯結(jié)果.以保存有更多的空間存儲新的預(yù)編譯語句.三.最重要的一點(diǎn)是極大地提高了安全性.即使到目前為
26、止,仍有一些人連基本的惡義SQL語法都不知道.String sql = select * from tb_name where name= +varname+ and passwd=+varpasswd+;如果我們把 or 1 = 1作為varpasswd傳入進(jìn)來.用戶名隨意,看看會成為什么?select * from tb_name = 隨意 and passwd = or 1 = 1;因?yàn)?=1肯定成立,所以可以任何通過驗(yàn)證.更有甚者:把;drop table tb_name;作為varpasswd傳入進(jìn)來,則:select * from tb_name = 隨意 and passwd =
27、 ;drop table tb_name;有些數(shù)據(jù)庫是不會讓你成功的,但也有很多數(shù)據(jù)庫就可以使這些語句得到執(zhí)行.而如果你使用預(yù)編譯語句.你傳入的任何內(nèi)容就不會和原來的語句發(fā)生任何匹配的關(guān)系.只要全使用預(yù)編譯語句,你就用不著對傳入的數(shù)據(jù)做任何過慮.而如果使用普通的statement,有可能要對drop,;等做費(fèi)盡心機(jī)的判斷和過慮.JDBC中的數(shù)據(jù)類型與日期問題Java.util.Date.getTime()返回自1970年1月1日 00:00:00 GMT 以來此 Date 對象表示的毫秒數(shù)。public static void main(String args) throws SQLExcep
28、tion create(4,zhushidong,new Date(),5500.00f);static void create(int id,String name,Date birthday,float money) throws SQLException Util包里面的Date類型!Connection ct=null;PreparedStatement ps=null;ResultSet rs=null;tryct=JdbcUtils.getConnection();String sql=insert into wanghao(id,name,birthday,money)value
29、s (?,?,?,?);ps=ct.prepareStatement(sql);ps.setInt(1, id);ps.setString(2, name);ps.setDate(3, new java.sql.Date(birthday.getTime();ps.setFloat(4, money);int i=ps.executeUpdate(); System.out.println(i=+i);finallyJdbcUtils.free(rs, ps, ct);Util包里面的Date類型是sql包里Date類型的父類,由程序很容已看出我們企圖把一個父類賦值給一個子類,這是不允許的,反
30、過來一個子類賦值給一個父類則是可以的。因此我們需要做這樣的new java.sql.Date(birthday.getTime()一個轉(zhuǎn)換。J2EE 三層架構(gòu)所謂的三層開發(fā)就是將系統(tǒng)的整個業(yè)務(wù)應(yīng)用劃分為表示層業(yè)務(wù)邏輯層數(shù)據(jù)訪問層,這樣有利于系統(tǒng)的開發(fā)、維護(hù)、部署和擴(kuò)展。分層是為了實(shí)現(xiàn)“高內(nèi)聚、低耦合”。采用“分而治之”的思想,把問題劃分開來各個解決,易于控制,易于延展,易于分配資源。表示層:負(fù)責(zé)直接跟用戶進(jìn)行交互,一般也就是指系統(tǒng)的界面,用于數(shù)據(jù)錄入,數(shù)據(jù)顯示等。意味著只做與外觀顯示相關(guān)的工作,不屬于他的工作不用做。 業(yè)務(wù)邏輯層:用于做一些有效性驗(yàn)證的工作,以更好地保證程序運(yùn)行的健壯性。如完成
31、數(shù)據(jù)添加、修改和查詢業(yè)務(wù)等;不允許指定的文本框中輸入空字符串,數(shù)據(jù)格式是否正確及數(shù)據(jù)類型驗(yàn)證;用戶的權(quán)限的合法性判斷等等,通過以上的諸多判斷以決定是否將操作繼續(xù)向后傳遞,盡量保證程序的正常運(yùn)行。 數(shù)據(jù)訪問層:顧名思義,就是用于專門跟數(shù)據(jù)庫進(jìn)行交互。執(zhí)行數(shù)據(jù)的添加、刪除、修改和顯示等。需要強(qiáng)調(diào)的是,所有的數(shù)據(jù)對象只在這一層被引用,如System.Data.SqlClient等,除數(shù)據(jù)層之外的任何地方都不應(yīng)該出現(xiàn)這樣的引用。表示層:1.基于WEB的JSP、Servlet、Struts、Webwork、Spring WEB MVC等;2.基于客戶端的Swing、SWT等(rmi,iiop);業(yè)務(wù)邏輯
32、層:Pojo(Service,Manager)、Domain、Session EJB、Spring用接口隔離,用Domain或DTO傳遞數(shù)據(jù)數(shù)據(jù)訪問層:JDBC、Ibatis、Hibernate、JDO、Entity Bean用接口隔離,用Domain或DTO傳遞數(shù)據(jù)數(shù)據(jù)訪問層是為業(yè)務(wù)邏輯層服務(wù)的,業(yè)務(wù)邏輯層操作的是對象而數(shù)據(jù)庫是關(guān)系型數(shù)據(jù)庫。我們需要在我們的數(shù)據(jù)訪問層把表和字段屏蔽掉,把它變成對象來傳遞給我們的業(yè)務(wù)邏輯。傳遞要通過Domain Object(域?qū)ο螅珼omain Object是一塊比較重要的知識,下面我們來講一下Domain Object。Domain Object(域?qū)ο?/p>
33、)的三種模型由于當(dāng)前O/R Mapping, DAO開發(fā)結(jié)構(gòu)的層次劃分,導(dǎo)致出現(xiàn)了大量的純粹數(shù)據(jù)對象。這些數(shù)據(jù)對象只帶有g(shù)etter, setter屬性,而不具有屬于自己的方法,起著Data Transfer Object的作用。 Domain Object 則是重新提出并進(jìn)一步探討純面向?qū)ο缶幊痰母拍睿簩ο蟛粌H應(yīng)該具有數(shù)據(jù),而且應(yīng)該具有自己的方法。第一種模型(貧血的Domain Object)只有g(shù)etter/setter方法的純數(shù)據(jù)類,所有的業(yè)務(wù)邏輯完全由business object來完成(又稱TransactionScript),這種模型下的domain object被Martin F
34、owler稱之為“貧血的domain object”。下面用舉一個具體的代碼來說明一般情況下,Domain Object單獨(dú)放在一個domain包里面。一個Domain Object都會有一張表和他對應(yīng)。例如下面的Domain 對象Staff就在數(shù)據(jù)庫中對應(yīng)一張名叫STAFF的表。public class Staff private int id;private String name;private Date birthday;private float money;public int getId() return id;public void setId(int id) this.id
35、= id;public String getName() return name;public void setName(String name) = name;public Date getBirthday() return birthday;public void setBirthday(Date birthday) this.birthday = birthday;public float getMoney() return money;public void setMoney(float money) this.money = money;下面我們定義一個數(shù)據(jù)訪問層
36、的接口,這個接口是給業(yè)務(wù)邏輯層用的,最終業(yè)務(wù)邏輯層會用這個接口完成對數(shù)據(jù)的增、刪、改、查操作。接口我們一般也放在一個專門的包里面如:com.wanghao.jdbc.dao,在這個包中有一個StaffDao接口,是專門訪問Staff對象用的。package com.wanghao.jdbc.dao;import com.wanghao.jdbc.domain.Staff;public interface StaffDao public void addStaff(Staff staff);public Staff getStaff(int staffId);public Staff findS
37、taff(String loinName,String password);public void update(Staff staff);public void delete(Staff staff);三層架構(gòu)這樣設(shè)計(jì)有一個好處就是:讓我們的業(yè)務(wù)邏輯層不依賴數(shù)據(jù)訪問層的具體實(shí)現(xiàn),業(yè)務(wù)邏輯層只使用接口,至于具體實(shí)現(xiàn)是什么,它并不關(guān)心。這樣的好處是:比如上面的StaffDaoJdbcImplement實(shí)現(xiàn),我們是用JDBC實(shí)現(xiàn)的。我們也可以把這個實(shí)現(xiàn)換成Hibernate來實(shí)現(xiàn),用的還是同一個接口。這種替換如果服從三層架構(gòu),就會在不影像到你的業(yè)務(wù)邏輯層的情況下,且換掉你的數(shù)據(jù)訪問層。接下來我們用
38、JDBC實(shí)現(xiàn)這個接口。接口的實(shí)現(xiàn)類我們也要轉(zhuǎn)本放一個包里面,如我們的例子就把接口的實(shí)現(xiàn)類StaffDaoJdbcImplement放在com.wanghao.jdbc.dao.implement里面。代碼如下所示:package com.wanghao.jdbc.dao.implement;import java.sql.*;import com.wanghao.jdbc.JdbcUtils;import com.wanghao.jdbc.dao.DaoException;import com.wanghao.jdbc.dao.StaffDao;import com.wanghao.jdbc.
39、domain.Staff;public class StaffDaoJdbcImplement implements StaffDaopublic void addStaff(Staff staff) Connection ct=null;PreparedStatement ps=null;ResultSet rs=null;tryct=JdbcUtils.getConnection();String sql=insert into staff(id,name,birthday,money) values(?,?,?,?);ps=ct.prepareStatement(sql);ps.setI
40、nt(1, staff.getId();ps.setString(2, staff.getName();ps.setDate(3, new java.sql.Date(staff.getBirthday().getTime();ps.setFloat(4, staff.getMoney();ps.executeUpdate();catch(SQLException e)throw new DaoException(e.getMessage(),e);finallyJdbcUtils.free(rs, ps, ct);public void delete(Staff staff) Connect
41、ion ct=null;PreparedStatement ps=null;ResultSet rs=null;tryct=JdbcUtils.getConnection();String sql=delete from staff where id=+staff.getId();ps=ct.prepareStatement(sql);ps.executeUpdate();catch(SQLException e)throw new DaoException(e.getMessage(),e);finallyJdbcUtils.free(rs, ps, ct);public Staff fin
42、dStaff(String loinName, String password) Connection ct=null;PreparedStatement ps=null;ResultSet rs=null;Staff staff=null;tryct=JdbcUtils.getConnection();String sql=select id,name,money,birthday from staff where name=?;ps=ct.prepareStatement(sql);ps.setString(1, loinName);rs=ps.executeQuery();while(r
43、s.next()staff = mappingStaff(rs);catch(SQLException e)throw new DaoException(e.getMessage(),e);finallyJdbcUtils.free(rs, ps, ct);return staff;public Staff getStaff(int staffId) Connection ct=null;PreparedStatement ps=null;ResultSet rs=null;Staff staff=null;tryct=JdbcUtils.getConnection();String sql=
44、select id,name,money,birthday from staff where id=?;ps=ct.prepareStatement(sql);ps.setInt(1, staffId);rs=ps.executeQuery();while(rs.next()staff = mappingStaff(rs);catch(SQLException e)throw new DaoException(e.getMessage(),e);finallyJdbcUtils.free(rs, ps, ct);return staff;private Staff mappingStaff(R
45、esultSet rs) throws SQLException Staff staff;staff=new Staff();staff.setId(rs.getInt(id);staff.setName(rs.getString(name);staff.setBirthday(rs.getDate(birthday);staff.setMoney(rs.getFloat(money);return staff;public void update(Staff staff) Connection ct=null;PreparedStatement ps=null;ResultSet rs=nu
46、ll;tryct=JdbcUtils.getConnection();String sql=update staff set money=? where id=?;ps=ct.prepareStatement(sql);ps.setFloat(1, staff.getMoney();ps.setInt(2, staff.getId();ps.executeUpdate();catch(SQLException e)throw new DaoException(e.getMessage(),e);finallyJdbcUtils.free(rs, ps, ct);在上面的代碼中我們遇到了一個比較
47、復(fù)雜的異常處理問題,再此我們插播一曲,講一下編譯時異常和運(yùn)行時異常的轉(zhuǎn)換。1、是否可以捕獲即catch一個異常兒什么也不做?這是絕對不允許的,如果什么也不做,一旦出錯系統(tǒng)不會報任何錯誤,而后臺也沒有任何堆棧,但運(yùn)行結(jié)果就是不正確。這樣的錯誤很難調(diào)試,所以不允許此種操作。2、初級程序員通常只在catch里面做一個簡單的打出堆棧操作e.printStackTrace(),但這樣處理還是不行的。比如一個用戶注冊程序,當(dāng)添加完一個新用戶后,要給這個用戶發(fā)個emai雖然做一個簡單的打出堆棧操作,但是,這個異常我們的業(yè)務(wù)邏輯層并不知道,當(dāng)業(yè)務(wù)邏輯層執(zhí)行到給用戶發(fā)送email找不到這個用戶的時候,就很難調(diào)試
48、了。因此,我們得讓業(yè)務(wù)邏輯層知道這個異常的存在。3、那我們直接把這個異常拋出執(zhí)行throw e;語句,這樣,上層業(yè)務(wù)邏輯代碼就知道有這個異常的存在,這個目的就達(dá)到了。但是現(xiàn)在有一個新的問題存在:上層業(yè)務(wù)邏輯代碼必須被catch(捕獲)。因?yàn)樵谶@里SQLException是一個編譯時異常,即這個異常必須被處理否則不能通過編譯。但很多情況下,即使業(yè)務(wù)邏輯代碼被catch住也沒有什么用,因?yàn)槭堑讓拥臄?shù)據(jù)訪問出錯,業(yè)務(wù)邏輯層也沒有解決的辦法,那么業(yè)務(wù)邏輯層得繼續(xù)拋出異常。這樣就沒有止境了,使我們的代碼變得相當(dāng)?shù)脑愀?。另外它在設(shè)計(jì)上還有一個重大的缺陷,我們用JDBC實(shí)現(xiàn)的接口不能在被替換為Hiberna
49、te。Hibernate不拋出SQLException?;蛘哒f,我們先在使用的是數(shù)據(jù)庫,以后我們要換成磁盤文件,即把數(shù)據(jù)放在文件中,文件中沒有SQLException但有IOException。這就相當(dāng)于底層的數(shù)據(jù)訪問層換不掉了。因此,簡單的把異常拋出去是不合適的。4、結(jié)合以上分析,我們需要采取另外一種方式:把編譯時異常轉(zhuǎn)變成運(yùn)行時異常,這樣,業(yè)務(wù)邏輯層可以選擇處理異?;虿惶幚懋惓!H绻胱龅囊?guī)范些,就在數(shù)據(jù)邏輯層加一個數(shù)據(jù)訪問異常。這樣即可以達(dá)到通知出錯的目的,又不污染我們的接口。代碼如下:package com.wanghao.jdbc.dao;public class DaoExcept
50、ion extends RuntimeException private static final long serialVersionUID=1L;public DaoException() public DaoException(String message) super(message);public DaoException(Throwable cause) super(cause);public DaoException(String message, Throwable cause) super(message, cause);5、上面程序中的陰影部分使用了,是重復(fù)的代碼做的一個優(yōu)
51、化,使用的是重構(gòu)Refactor技術(shù)。這樣對我們以后的程序維護(hù)很有用處。6、下面使用工廠模式消除StaffDaoTest對StaffDaoJdbcImplement類的依賴。高內(nèi)聚低耦合高內(nèi)聚低耦合,是軟件工程中的概念,是判斷設(shè)計(jì)好壞的標(biāo)準(zhǔn),主要是面向?qū)ο蟮脑O(shè)計(jì),主要是看類的內(nèi)聚性是否高,耦合性是否低。內(nèi)聚就是一個模塊內(nèi)各個元素彼此結(jié)合的程度。所謂的高內(nèi)聚是指一個軟件模塊是有相關(guān)性很強(qiáng)的代碼組成,只負(fù)責(zé)一項(xiàng)任務(wù),也就是常說的單一責(zé)任原則。耦合是一個軟件結(jié)構(gòu)內(nèi)不同模塊之間互聯(lián)程度的度量。模塊之間聯(lián)系越緊密,其耦合性越強(qiáng),模塊的獨(dú)立性就越差,模塊間耦合的高低取決于模塊間接口的復(fù)雜性,調(diào)用的方式以及
52、傳遞的信息。對于低耦合,粗淺的理解就是:一個完整的系統(tǒng),模塊與模塊之間,盡可能的使其獨(dú)立。DAO工廠模式工廠模式專門負(fù)責(zé)將大量有共同接口的類實(shí)例化。工廠模式可以動態(tài)決定將哪一個類示例化,不必事先知道每次要實(shí)例化哪一個類。通過DAO的設(shè)計(jì)的確可以讓我們的軟件系統(tǒng)已經(jīng)將數(shù)據(jù)層和表現(xiàn)層進(jìn)行了簡單的分離,讓我們系統(tǒng)各層次的功能更加的清晰。所以我們開始洋洋得意了,DAO的引入讓系統(tǒng)的耦合性更加的松散,表現(xiàn)層再也不需要關(guān)心后臺數(shù)據(jù)操作的變化了。于是我們開始高枕無憂了,我們肆無忌憚的在表現(xiàn)層通過調(diào)用DAO來實(shí)現(xiàn)我們的系統(tǒng)了。事實(shí)真的如此嗎?那我們就舉個例子來看看我們的系統(tǒng)是否真的具有解偶的能力了。 現(xiàn)在我們
53、有個員工管理系統(tǒng),在該系統(tǒng)中,Staff.java表示員工這個對象,它對應(yīng)著數(shù)據(jù)庫中的staff表。還有用于操作Staff對象的DAO接口StaffDAO.java,還有一個StaffDAO的實(shí)現(xiàn)類StaffDAOImplement.java。在StaffDAOImplement.java中我們實(shí)現(xiàn)了操作Staff對象的所有的方法。我們很自豪的說,看我們已經(jīng)把操作封裝在StaffDAO中了,現(xiàn)在我們可以在表現(xiàn)層(jsp,或者VO操作類中)使用StaffDAO satffDAO=new StaffDAOImplement()來調(diào)用DAO操作我們的數(shù)據(jù)對象了。當(dāng)我們陶醉于自己寫的優(yōu)美的代碼的時候,項(xiàng)目經(jīng)理來通知了,由于使用Hibernate的效率偏低,客戶
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 兒童教育合同范本
- 修鄉(xiāng)村路橋合同范本
- 偽造備案租房合同范本
- 創(chuàng)業(yè)五人合作合同范本
- 加盟 商鋪轉(zhuǎn)讓合同范本
- 全國租賃服裝合同范本
- 買賣店鋪裝修合同范本
- 劃經(jīng)營合同范本
- 2025內(nèi)蒙古新工創(chuàng)業(yè)發(fā)展集團(tuán)有限責(zé)任公司公開招聘工作人員筆試參考題庫附帶答案詳解
- epc項(xiàng)目建設(shè)合同范本
- 輪狀病毒性腸炎
- 世界社會主義五百年
- 加氫裂化操作工題庫(合并版)
- 正大集團(tuán)大豬場開發(fā)流程
- 高中政治必修四知識體系每單元的總體框架
- 房地產(chǎn)金融創(chuàng)新與風(fēng)險防范的理論演進(jìn)
- GB/T 41255-2022智能工廠通用技術(shù)要求
- GB/T 41029-2021石油天然氣鉆井海洋棄井作業(yè)規(guī)程
- 深入推進(jìn)依法行政
- GB/T 4026-1992電器設(shè)備接線端子和特定導(dǎo)線線端的識別及應(yīng)用字母數(shù)字系統(tǒng)的通則
- 馬工程教材《公共財政概論》PPT-第二章 公共財政職能
評論
0/150
提交評論