版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章數(shù)據(jù)庫(kù)整合開發(fā)
第6章數(shù)據(jù)庫(kù)整合開發(fā)本章內(nèi)容MySQL簡(jiǎn)介
JDBC概述數(shù)據(jù)庫(kù)連接池
DBUtils框架簡(jiǎn)介簡(jiǎn)易購(gòu)物商城本章內(nèi)容MySQL簡(jiǎn)介6.1MySQL簡(jiǎn)介MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),它由瑞典MySQLAB公司開發(fā),目前屬于Oracle旗下的產(chǎn)品。MySQL是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)之一,在Web應(yīng)用方面,MySQL是最好的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)(RelationalDataBaseManagementSystem,RDBMS)應(yīng)用軟件。6.1MySQL簡(jiǎn)介MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),它由瑞6.2
JDBC概述Java數(shù)據(jù)庫(kù)連接技術(shù)(JavaDataBaseConnectivity,JDBC)是Java訪問(wèn)數(shù)據(jù)庫(kù)資源的標(biāo)準(zhǔn),JDBC標(biāo)準(zhǔn)定義了一組JavaAPI,允許用戶寫出SQL語(yǔ)句,然后交給數(shù)據(jù)庫(kù)。6.2JDBC概述Java數(shù)據(jù)庫(kù)連接技術(shù)(JavaD6.2
JDBC概述如圖6.1所示,如果沒(méi)有JDBC或者ODBC,開發(fā)人員必須使用不同的一組API來(lái)訪問(wèn)不同的數(shù)據(jù)庫(kù);而有了JDBC或者ODBC,則只需要使用一組API,再加上數(shù)據(jù)庫(kù)廠商提供的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序就可以訪問(wèn)不同的數(shù)據(jù)庫(kù)了,如圖6.2所示。所以,利用JDBC,我們就可以把同一個(gè)企業(yè)級(jí)Java應(yīng)用移植到另一個(gè)數(shù)據(jù)庫(kù)應(yīng)用上。6.2JDBC概述如圖6.1所示,如果沒(méi)有JDBC或6.2
JDBC概述圖6.1應(yīng)用程序直接訪問(wèn)數(shù)據(jù)庫(kù)圖6.2應(yīng)用程序訪問(wèn)JDBC6.2JDBC概述圖6.1應(yīng)用程序直接訪問(wèn)數(shù)據(jù)庫(kù)圖6.6.2
JDBC概述JDBC主要包含兩部分:面向Java程序員的JDBCAPI和面向數(shù)據(jù)庫(kù)廠商的JDBCDriveAPI。1.面向Java程序員的JDBCAPI它主要由一系列的接口定義所構(gòu)成。java.sql.DriveManager:該接口定義了用來(lái)處理裝載驅(qū)動(dòng)的程序,并且為創(chuàng)建新的數(shù)據(jù)庫(kù)連接提供支持。java.sql.Connection:該接口定義了實(shí)現(xiàn)對(duì)某一種指定數(shù)據(jù)庫(kù)連接的功能。6.2JDBC概述JDBC主要包含兩部分:面向Java程6.2
JDBC概述java.sql.Statement:該接口定義了在一個(gè)給定的連接中作為SQL語(yǔ)句執(zhí)行聲明的容器以實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作。它主要包含有如下兩種子類型。java.sql.PreparedStatement:該接口定義了用于執(zhí)行帶或不帶IN參數(shù)的預(yù)編譯SQL語(yǔ)句。java.sql.CallableStatement:該接口定義了用于執(zhí)行數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程的調(diào)用。java.sql.ResultSet:該接口定義了執(zhí)行數(shù)據(jù)庫(kù)的操作后返回的結(jié)果集。2.面向數(shù)據(jù)庫(kù)廠商的JDBCDriveAPI6.2JDBC概述java.sql.Statement:6.2
JDBC概述6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接6.2.2SQL的執(zhí)行6.2.3SQL執(zhí)行結(jié)果的處理6.2JDBC概述6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接在Java程序中要操作數(shù)據(jù)庫(kù),一般應(yīng)該通過(guò)如下幾步。1.下載數(shù)據(jù)庫(kù)開發(fā)所需要的驅(qū)動(dòng)包用戶可以從對(duì)應(yīng)的數(shù)據(jù)庫(kù)廠商的官網(wǎng)進(jìn)行下載,例如,下載MySQL驅(qū)動(dòng)包,如圖6.3所示,選擇“JDBCDriverforMySQL”進(jìn)行下載。下載的驅(qū)動(dòng)包是一個(gè)壓縮包,將包內(nèi)的“mysql-connector-java-5.1.42-bin.jar”復(fù)制到“WebRoot\lib”文件夾下,如圖6.4所示。6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接在Java程序中要操作數(shù)據(jù)庫(kù),一6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接圖6.3下載MySQL驅(qū)動(dòng)包圖6.4加載MySQL驅(qū)動(dòng)包6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接圖6.3下載MySQL驅(qū)動(dòng)包圖6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接2.?dāng)?shù)據(jù)庫(kù)管理工具在開發(fā)中,我們一般會(huì)創(chuàng)建一個(gè)專用于創(chuàng)建數(shù)據(jù)庫(kù)連接和釋放數(shù)據(jù)庫(kù)連接的工具類。建立與數(shù)據(jù)庫(kù)的連接需要完成如下兩個(gè)步驟。(1)加載驅(qū)動(dòng)類到內(nèi)存Class.forName("com.mysql.jdbc.Driver");(2)創(chuàng)建與數(shù)據(jù)源的連接Connectioncon=DriverManager.getConnection(Stringurl,Stringusername,Stringpassword);6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接2.?dāng)?shù)據(jù)庫(kù)管理工具6.2.2
SQL的執(zhí)行在實(shí)際開發(fā)中,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí),只需要調(diào)用以下方法:
Connectionconn=DBUtil.getConnection();就可以獲得一個(gè)java.sql.Connection類型的數(shù)據(jù)庫(kù)連接對(duì)象,通過(guò)這個(gè)連接對(duì)象,用戶可以操作數(shù)據(jù)庫(kù),發(fā)送目標(biāo)SQL給數(shù)據(jù)庫(kù),并接收響應(yīng)結(jié)果。6.2.2SQL的執(zhí)行在實(shí)際開發(fā)中,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí),6.2.2
SQL的執(zhí)行在已建立數(shù)據(jù)庫(kù)連接的基礎(chǔ)上,向數(shù)據(jù)庫(kù)發(fā)送要執(zhí)行的SQL語(yǔ)句的接口是Statement。Statement用于執(zhí)行靜態(tài)的SQL語(yǔ)句。(1)java.sql.Statementjava.sql.Statement類型的對(duì)象,是通過(guò)java.sql.Connection對(duì)象獲得的,其代碼如下:Statementst=conn.createStatement();所獲得的Statement對(duì)象st,可以用來(lái)執(zhí)行SQL語(yǔ)句,Statement執(zhí)行SQL語(yǔ)句的主要方法有兩個(gè):intexecuteUpdate(Stringsql);ResultSetexecuteQuery(Stringsql);6.2.2SQL的執(zhí)行在已建立數(shù)據(jù)庫(kù)連接的基礎(chǔ)上,向數(shù)據(jù)6.2.2
SQL的執(zhí)行其中,executeUpdate(Stringsql)方法可用來(lái)執(zhí)行數(shù)據(jù)庫(kù)的更新操作。該方法的返回值類型為int,代表影響的記錄條數(shù),即插入了幾條數(shù)據(jù),修改了幾條數(shù)據(jù),刪除了幾條數(shù)據(jù)等。而executeQuery(Stringsql)方法可用來(lái)執(zhí)行數(shù)據(jù)庫(kù)的查詢操作。該方法的返回值類型是java.sql.ResultSet,該類型能夠存儲(chǔ)數(shù)據(jù)庫(kù)返回的所有記錄,并支持按條讀取結(jié)果數(shù)據(jù)。6.2.2SQL的執(zhí)行其中,executeUpdate(6.2.2
SQL的執(zhí)行(2)java.sql.PreparedStatement接口在Statement中可以看到,動(dòng)態(tài)SQL的生成是通過(guò)字符串拼接而成的,但是字符串拼接會(huì)帶來(lái)很多的安全隱患,其中最為常見(jiàn)的安全漏洞就是SQL注入。下面以登錄功能為例,在.zzti.dao包下的UserDAO接口中定義登錄判斷方法,代碼如下:publicUserDOfindUser(Stringusername,Stringpassword)throwsSQLException;具體代碼如下:6.2.2SQL的執(zhí)行(2)java.sql.Prepa6.2.2SQL的執(zhí)行在代碼的第6行,我們將拼接后的SQL語(yǔ)句打印到控制臺(tái)進(jìn)行觀察。在第12行處,需要將獲得的數(shù)據(jù)庫(kù)查詢結(jié)果進(jìn)行封裝,這里暫不實(shí)現(xiàn)這個(gè)功能。下面先來(lái)創(chuàng)建一個(gè).zzti.dao.impl.mysql.
jdbc.test.UserDAOImplTest類,對(duì)方法findUser進(jìn)行測(cè)試,具體代碼如下。1publicUserDOfindUser(Stringusername,Stringpassword)throwsSQLException{2 Stringsql="select*fromuserwhereusername='"+3 username+4 "'andpassword='"+5 password+"'";6 System.out.println("登錄sql是:"+sql);7 Connectionconn=DBUtil.getConnection();8 Statementst=conn.createStatement();9 ResultSetrs=st.executeQuery(sql);10 if(rs.next()){11 UserDOuser=newUserDO();12 //將查詢結(jié)果封裝到user對(duì)象中,此處先不處理13 returnuser;14 }15 returnnull;16 }6.2.2SQL的執(zhí)行1publicUserDO6.2.2SQL的執(zhí)行Assert.assertNotNull(Objecto)是Junit的斷言,該斷言方法判斷對(duì)象o是否為空,為空則當(dāng)前測(cè)試方法通過(guò),否則測(cè)試方法失敗。執(zhí)行結(jié)果顯示,使用不存在的用戶名和密碼,調(diào)用登錄方法執(zhí)行結(jié)果為登錄正常。在輸出的SQL結(jié)果顯示,最終執(zhí)行的SQL如下:
1publicclassUserDAOImplTest{2 privateUserDAOuserDAO=(UserDAO)3 DAOFactory.getDAO(".zzti.dao.impl.mysql.jdbc.UserDAOImpl");4 @Test5 publicvoidtestFinUser(){6 Stringusername="test'or1=1#";7 Stringpassword="";8 try{9 Assert.assertNull(userDAO.findUser(username,password));10 }catch(SQLExceptione){11 e.printStackTrace();12 fail("出現(xiàn)異常,執(zhí)行失敗");13 }14 }15}6.2.2SQL的執(zhí)行1publicclass6.2.2SQL的執(zhí)行select*fromuserwhereusername='test'or1=1#'andpassword=‘’在這個(gè)SQL中,“#”代表MySQL中的注釋。該語(yǔ)句的本意是從數(shù)據(jù)庫(kù)中獲取全部的數(shù)據(jù),因?yàn)椤皁r1=1”使得這個(gè)條件恒為真。select*fromuserwhereusername='test'or1=16.2.2SQL的執(zhí)行select*fromuser6.2.2SQL的執(zhí)行為了避免SQL注入的問(wèn)題,JDBC提供了一種SQL預(yù)編譯的機(jī)制,即PreparedStatement。首先用戶提交的SQL中可以不指定具體的參數(shù),對(duì)于可變值部分讓用戶使用“?”(即占位符)來(lái)代替。然后再對(duì)SQL中的占位符單獨(dú)設(shè)置值,將兩者提交給數(shù)據(jù)庫(kù)引擎進(jìn)行編譯,此時(shí)數(shù)據(jù)庫(kù)引擎僅僅編譯帶有占位符“?”的SQL語(yǔ)句,等到編譯完成后,在執(zhí)行SQL時(shí),將參數(shù)帶入編譯結(jié)果,此時(shí),參數(shù)就只會(huì)作為參數(shù)整體進(jìn)行數(shù)據(jù)比較,而不會(huì)作為SQL語(yǔ)法的一部分。6.2.2SQL的執(zhí)行為了避免SQL注入的問(wèn)題,JDBC提6.2.2SQL的執(zhí)行PreparedStatement對(duì)象的創(chuàng)建方式如下:PreparedStatementps=conn.prepareStatement(Stringsql);而SQL也需要進(jìn)行相應(yīng)的改寫:Stringsql="select*fromuserwhereusername=?andpassword=?";與之前的SQL對(duì)比可以發(fā)現(xiàn),原來(lái)的形式參數(shù)部分被占位符“?”代替,那么就需要將形式參數(shù)與具體的“?”綁定。綁定操作可通過(guò)調(diào)用setXXX方法來(lái)完成,其中,XXX是與該參數(shù)相對(duì)應(yīng)的類型。例如,如果參數(shù)的數(shù)據(jù)類型是long,則使用的方法就是setLong。setXXX方法的第一個(gè)參數(shù)是要設(shè)置的參數(shù)的序數(shù)位置,第二個(gè)參數(shù)是設(shè)置給該參數(shù)的值。例如,上述SQL將第一個(gè)參數(shù)設(shè)為形式參數(shù)username,第二個(gè)參數(shù)設(shè)為形式參數(shù)password,代碼如下所示:ps.setString(1,username);ps.setString(2,password);6.2.2SQL的執(zhí)行PreparedStatement對(duì)6.2.3SQL執(zhí)行結(jié)果處理無(wú)論是Statement,還是PreparedStatement,在執(zhí)行SQL的時(shí)候,主要應(yīng)用的執(zhí)行方法是executeQuery和executeUpdate,Statement在執(zhí)行execute*方法時(shí),需要以SQL為字符串參數(shù)進(jìn)行傳遞,而PreparedStatement則不需要參數(shù)。調(diào)用規(guī)則總結(jié)如表6.2所示。6.2.3SQL執(zhí)行結(jié)果處理無(wú)論是Statement,還是6.2.3SQL執(zhí)行結(jié)果處理類名方法定義說(shuō)明StatementResultSetexecuteQuery(Stringsql)執(zhí)行select等StatementintexecuteUpdate(Stringsql)執(zhí)行insert、update、delete等PreparedStatementResultSetexecuteQuery()執(zhí)行select等PreparedStatementintexecuteUpdate(Stringsql)執(zhí)行insert、update、delete等表6.2SQL執(zhí)行結(jié)果6.2.3SQL執(zhí)行結(jié)果處理類名方法定義說(shuō)明6.3數(shù)據(jù)庫(kù)連接池創(chuàng)建數(shù)據(jù)庫(kù)連接是一個(gè)十分耗時(shí)的操作,也容易讓數(shù)據(jù)庫(kù)產(chǎn)生安全隱患。因此,在程序初始化的時(shí)候,集中創(chuàng)建了多個(gè)數(shù)據(jù)庫(kù)連接,并對(duì)它們進(jìn)行集中管理,以供程序使用,這樣就可以保證較快的數(shù)據(jù)庫(kù)讀/寫速度,而且更加安全可靠。數(shù)據(jù)庫(kù)連接池的運(yùn)行原理如圖6.16所示。6.3數(shù)據(jù)庫(kù)連接池創(chuàng)建數(shù)據(jù)庫(kù)連接是一個(gè)十分耗時(shí)的操作,也容6.3數(shù)據(jù)庫(kù)連接池Servlet1Servlet2......ServletnDAO1.....DAOmMySQLuser1......usersConnectionConnection......Connection圖6.16數(shù)據(jù)庫(kù)連接池原理6.3數(shù)據(jù)庫(kù)連接池Servlet1Servlet2....6.3數(shù)據(jù)庫(kù)連接池6.3.1DataSource6.3.2Tomcat數(shù)據(jù)源6.3.3DBCP6.3數(shù)據(jù)庫(kù)連接池6.3.1DataSource6.3.1DataSourceJDBC1.0原來(lái)是用DriverManager類來(lái)產(chǎn)生一個(gè)對(duì)數(shù)據(jù)源的連接。JDBC2.0用一種替代的方法,使用java.sql.DataSource實(shí)現(xiàn),代碼變得更小巧精致,也更容易控制。編寫數(shù)據(jù)庫(kù)連接池需實(shí)現(xiàn)Java.sql.DataSource接口。DataSource接口中定義了兩個(gè)重載的getConnection方法:6.3.1DataSourceJDBC1.0原來(lái)是用Dri6.3.1DataSourceConnectiongetConnection()ConnectiongetConnection(Stringusername,Stringpassword)開發(fā)數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)DataSource接口時(shí),在DataSource的實(shí)現(xiàn)類的構(gòu)造方法中批量創(chuàng)建與數(shù)據(jù)庫(kù)的連接,并把創(chuàng)建的連接加入存儲(chǔ)java.sql.Connection對(duì)象的集合中。實(shí)現(xiàn)getConnection方法,讓getConnection方法每次調(diào)用時(shí),從存儲(chǔ)java.sql.Connection對(duì)象的集合中取一個(gè)Connection返回給用戶。6.3.1DataSourceConnectionget6.3.2Tomcat數(shù)據(jù)源Tomcat提供了數(shù)據(jù)源和連接池的實(shí)現(xiàn),開發(fā)者直接使用即可。這里的Tomcat需要JDBC驅(qū)動(dòng),而不再是應(yīng)用程序需要JDBC驅(qū)動(dòng),所以要先將對(duì)應(yīng)數(shù)據(jù)庫(kù)的JDBC驅(qū)動(dòng)類庫(kù)復(fù)制到Tomcat目錄中的lib文件夾下,供Tomcat調(diào)用。首先在Tomcat目錄中的“l(fā)ib”目錄下放入數(shù)據(jù)庫(kù)驅(qū)動(dòng)jar包,在工程的“META-INF”目錄下創(chuàng)建一個(gè)“context.xml”文件,如圖6.17和圖6.18所示。6.3.2Tomcat數(shù)據(jù)源Tomcat提供了數(shù)據(jù)源和連接6.3.2Tomcat數(shù)據(jù)源圖6.17添加MySQL驅(qū)動(dòng)包圖6.18工程添加配置文件6.3.2Tomcat數(shù)據(jù)源圖6.17添加MySQL驅(qū)動(dòng)6.3.2Tomcat數(shù)據(jù)源“context.xml”的配置內(nèi)容如下:這些屬性含義如表6.4所示。1<Context>2<Resourcename="shop"3 auth="Container"4 type="javax.sql.DataSource"5 username="root"6 password="root"7 driverClassName="com.mysql.jdbc.Driver"8 url="jdbc:mysql://localhost:3306/shop"9 initialSize="10"10 maxActive="20"11 maxIdle="4"/>12</Context>6.3.2Tomcat數(shù)據(jù)源“context.xml”的配6.3.2Tomcat數(shù)據(jù)源鍵名含義name指定資源相對(duì)于java:comp/env上下文的JNDI名auth指定資源的管理者(默認(rèn)Container即可)type指定資源所屬的Java類的完整限定名(默認(rèn)即可)maxIdle指定連接池中保留的空閑數(shù)據(jù)庫(kù)連接的最大數(shù)目maxWait指定等待一個(gè)數(shù)據(jù)庫(kù)連接成為可用狀態(tài)的最大時(shí)間,單位毫秒username指定連接數(shù)據(jù)庫(kù)的用戶名password指定連接數(shù)據(jù)庫(kù)的密碼driverClassName指定JDBC驅(qū)動(dòng)程序類名url指定連接數(shù)據(jù)庫(kù)的URL表6.4Tomcat數(shù)據(jù)源配置文件屬性解析6.3.2Tomcat數(shù)據(jù)源鍵名含義name指定資6.3.2Tomcat數(shù)據(jù)源這里<Resource>元素的name屬性即為我們使用JNDI去檢索的關(guān)鍵字,在本例中為“shop”。接下來(lái)采用與之前工程相同的方式,創(chuàng)建數(shù)據(jù)庫(kù)工具類.zzti.util.tomcat.DBUtil來(lái)簡(jiǎn)化對(duì)數(shù)據(jù)庫(kù)的操作。6.3.2Tomcat數(shù)據(jù)源這里<Resource>元素的6.3.2Tomcat數(shù)據(jù)源1publicclassDBUtil{2privatestaticDataSourceds=null;3static{4try{5ContextinitCtx=newInitialContext();6ContextenvCtx=(Context)initCtx.lookup("java:comp/env");7ds=(DataSource)envCtx.lookup("shop");8//根據(jù)<Resource>元素的name屬性值到JNDI容器中檢索連接池對(duì)象9}catch(Exceptione){10thrownewExceptionInInitializerError(e);11}12}13publicstaticConnectiongetConnection()throwsSQLException{14returnds.getConnection();//利用數(shù)據(jù)源獲取連接15}16}6.3.2Tomcat數(shù)據(jù)源1publicclas6.3.3DBCP數(shù)據(jù)庫(kù)連接池(DataBaseConnectionPool,DBCP)是Java數(shù)據(jù)庫(kù)連接池的一種,由Apache開發(fā),通過(guò)數(shù)據(jù)庫(kù)連接池可以讓程序自動(dòng)管理數(shù)據(jù)庫(kù)連接的釋放和斷開。DBCP是Apache上的一個(gè)Java連接池項(xiàng)目,也是Tomcat使用的連接池組件。單獨(dú)使用DBCP需要準(zhǔn)備3個(gè)包:commons-dbcp-版本.jar;commons-pool-版本.jar;commons-logging-版本.jar。6.3.3DBCP數(shù)據(jù)庫(kù)連接池(DataBaseConn6.3.3DBCPDBCP的配置文件的內(nèi)容如下,其參數(shù)含義如表6.5所示。參數(shù)描述username傳遞給JDBC驅(qū)動(dòng)的用于建立連接的用戶名password傳遞給JDBC驅(qū)動(dòng)的用于建立連接的密碼url傳遞給JDBC驅(qū)動(dòng)的用于建立連接的URLdriverClassName使用的JDBC驅(qū)動(dòng)的完整有效的Java類名connectionProperties當(dāng)建立新連接時(shí)被發(fā)送給JDBC驅(qū)動(dòng)的連接參數(shù)表6.5DBCP常見(jiàn)配置參數(shù)含義6.3.3DBCPDBCP的配置文件的內(nèi)容如下,其參數(shù)含義6.4DBUtils框架簡(jiǎn)介CommonsDBUtils是Apache組織提供的一個(gè)對(duì)JDBC進(jìn)行簡(jiǎn)單封裝的開源工具類庫(kù),使用它能夠簡(jiǎn)化JDBC應(yīng)用程序的開發(fā),同時(shí)也不會(huì)影響程序的性能。DBUtils是Java編程中的數(shù)據(jù)庫(kù)操作實(shí)用工具,簡(jiǎn)單且實(shí)用。6.4DBUtils框架簡(jiǎn)介CommonsDBUtil6.4DBUtils框架簡(jiǎn)介DBUtils對(duì)于數(shù)據(jù)表的讀操作,它可以把結(jié)果轉(zhuǎn)換成List、Array、Set等Java集合,以便于程序員操作。對(duì)于數(shù)據(jù)表的寫操作,也變得很簡(jiǎn)單,只需寫SQL語(yǔ)句;可以使用數(shù)據(jù)源、JNDI、數(shù)據(jù)庫(kù)連接池等技術(shù)來(lái)優(yōu)化性能,重用已經(jīng)構(gòu)建好的數(shù)據(jù)庫(kù)連接對(duì)象,而不必像PHP、ASP那樣,需要費(fèi)時(shí)費(fèi)力地不斷重復(fù)構(gòu)建和析構(gòu)這樣的對(duì)象。CommonsDBUtils的核心類有3個(gè):mons.dbutils.ResultSetHandler、mons.dbutils.QueryRunner、mons.dbutils.DBUtils。6.4DBUtils框架簡(jiǎn)介DBUtils對(duì)于數(shù)據(jù)表的讀6.4DBUtils框架簡(jiǎn)介6.4.1QueryRunner6.4.2ResultSetHandler6.4.3資源釋放6.4DBUtils框架簡(jiǎn)介6.4.1QueryRun6.4.1QueryRunnerQueryRunner類簡(jiǎn)單化了SQL查詢,它與ResultSetHandler組合在一起使用可以完成大部分的數(shù)據(jù)庫(kù)操作,能夠大大減少編碼量。(1)QueryRunner類的構(gòu)造方法①默認(rèn)的構(gòu)造方法QueryRunnerqueryRunner=newQueryRunner();。②需要一個(gè)javax.sql.DataSource來(lái)作參數(shù)的構(gòu)造方法。QueryRunnerqr=newQueryRunner(DBUtil.getDataSource())6.4.1QueryRunnerQueryRunner類6.4.1QueryRunner(2)QueryRunner類的主要方法①publicObjectquery(Connectionconn,Stringsql,Object[]params,ResultSetHandlerrsh)throwsSQLException:執(zhí)行一個(gè)查詢操作,在這個(gè)查詢中,對(duì)象數(shù)組中的每個(gè)元素值被用來(lái)作為查詢語(yǔ)句的置換參數(shù)。該方法會(huì)自行處理PreparedStatement和ResultSet的創(chuàng)建和關(guān)閉流程。②publicObjectquery(Stringsql,Object[]params,ResultSetHandlerrsh)throwsSQLException:基本與第一種方法相同,唯一的不同在于它不將數(shù)據(jù)庫(kù)連接提供給方法,并且它是從提供給構(gòu)造方法的DataSource數(shù)據(jù)源或使用setDataSource方法設(shè)置的數(shù)據(jù)源。6.4.1QueryRunner(2)QueryRunn6.4.1QueryRunner③publicObjectquery(Connectionconn,Stringsql,ResultSetHandlerrsh)throwsSQLException:執(zhí)行一個(gè)不需要置換參數(shù)的查詢操作。④publicintupdate(Connectionconn,Stringsql,Object[]params)throwsSQLException:用來(lái)執(zhí)行一個(gè)更新操作,如插入、更新或刪除。⑤publicintupdate(Connectionconn,Stringsql)throwsSQLException:用來(lái)執(zhí)行一個(gè)不需要置換參數(shù)的更新操作。6.4.1QueryRunner③publicObj6.4.2ResultSetHandlerResultSetHandler接口用于處理java.sql.ResultSet,將數(shù)據(jù)按要求轉(zhuǎn)換為另一種形式。ResultSetHandler接口提供了一個(gè)單獨(dú)的處理java.sql.ResultSet的方法:
Objecthandle(java.sql.ResultSetrs)6.4.2ResultSetHandlerResultSe6.4.2ResultSetHandler(1)查詢類操作方法介紹ResultSetHandler接口的實(shí)現(xiàn)類見(jiàn)表6.6,下面對(duì)每個(gè)接口的實(shí)現(xiàn)類的具體使用方式進(jìn)行介紹。功能實(shí)現(xiàn)類單行數(shù)據(jù)處理ScalarHandler、ArrayHandler、MapHandler、BeanHandler多行數(shù)據(jù)處理BeanListHandler、ArrayListHandler、MapListHandler、
ColumnListHandler、KeyedHandler、BeanMapHandler可供擴(kuò)展的類BaseResultSetHandler表6.6ResultSetHandler接口實(shí)現(xiàn)類說(shuō)明6.4.2ResultSetHandler(1)查詢類操作6.4.2ResultSetHandler①ArrayHandler:把結(jié)果集中的第一行數(shù)據(jù)轉(zhuǎn)換成對(duì)象數(shù)組,示例代碼如下。②ArrayListHandler:把結(jié)果集中的每一行數(shù)據(jù)都轉(zhuǎn)換成一個(gè)對(duì)象數(shù)組,再存放到List中,示例代碼如下。1publicstaticvoidqueryToArray(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromauction";4 Object[]rs=queryRunner.query(conn,sql,newArrayHandler());5 for(inti=0;i<rs.length;i++){6 System.out.print("第一列:"+rs[i]+"\t");7 }8 System.out.print("\n");9 }1publicstaticvoidqueryToArrayList(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromauction";4 Listrs=queryRunner.query(conn,sql,newArrayListHandler());5 for(Objectrecord:rs){6 System.out.println(Arrays.toString((Object[])record));7 }8 }6.4.2ResultSetHandler①ArrayH6.4.2ResultSetHandler③BeanHandler<T>:把結(jié)果集中的第一行數(shù)據(jù)封裝到一個(gè)對(duì)應(yīng)的JavaBean實(shí)例中,示例代碼如下。④BeanListHandler<T>:把結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)對(duì)應(yīng)的JavaBean實(shí)例中,再存放到List中,示例代碼如下。1publicstaticvoidqueryToBean(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 4 AuctionDOauc=queryRunner.query(conn,5"select*fromauction",6newBeanHandler<AuctionDO>(AuctionDO.class));7 System.out.println(auc);8 }1publicstaticvoidqueryToBeanList(Connectionconn)throwsSQLException{2 Stringsql="select*fromauction";3 QueryRunnerqueryRunner=newQueryRunner();4 List<AuctionDO>list=queryRunner.query(conn,sql,5 newBeanListHandler<AuctionDO>(AuctionDO.class));6 for(inti=0;i<list.size();i++){7 System.out.println(list.get(i));8 }9 }6.4.2ResultSetHandler③BeanHa6.4.2ResultSetHandler⑤MapHandler:把結(jié)果集中的第一行數(shù)據(jù)封裝到一個(gè)Map中,key是列名,value就是對(duì)應(yīng)的值,示例代碼如下。⑥MapListHandler:把結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map中,然后再存放到List,示例代碼如下。1publicstaticvoidqueryToMap(Connectionconn)throwsSQLException{2 Stringsql="select*fromauction";3 QueryRunnerqueryRunner=newQueryRunner();4 Map<String,Object>map=queryRunner.query(conn,sql,newMapHandler());5 Set<Entry<String,Object>>set=map.entrySet();6 for(Entry<String,Object>entry:set){7 System.out.println(entry.getKey()+":"+entry.getValue());8 }9}1publicstaticvoidqueryToMapList(Connectionconn)throwsSQLException{2 Stringsql="select*fromauction";3 QueryRunnerqueryRunner=newQueryRunner();4 ist<Map<String,Object>>list=queryRunner.query(conn,sql,newMapListHandler());5 for(Map<String,Object>mapValue:list){6 Set<Entry<String,Object>>set1=mapValue.entrySet();7 for(Entry<String,Object>entry:set1){8 System.out.println(entry.getKey()+":"+entry.getValue());9 }10}11 }6.4.2ResultSetHandler⑤MapHan6.4.2ResultSetHandler⑦ColumnListHandler<T>:把結(jié)果集中的某一列的數(shù)據(jù)存放到List中,示例代碼如下。⑧KeyedHandler<K>:把結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map中(List),再把這些Map存到一個(gè)Map里,其key為指定的列,示例代碼如下。1publicstaticvoidqueryToColList(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromauction";//whereid=14 List<Object>list=(List<Object>)queryRunner.query(conn,sql,5 newColumnListHandler("name"));6 System.out.println(list);7}1publicstaticvoidqueryToKeyedHandler(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromusers";4 Map<Integer,Map<String,Object>>rs1=queryRunner.query(conn,sql,5 newKeyedHandler<Integer>(1));6 System.out.println("KeyedHandler:"+rs1);7 Map<Integer,Map<String,Object>>rs2=queryRunner.query(conn,sql,8 newKeyedHandler<Integer>("title"));9 System.out.println("KeyedHandler:"+rs2);10}6.4.2ResultSetHandler⑦Column6.4.2ResultSetHandler⑨BeanMapHandler<K,V>:用于獲取所有結(jié)果集,將每行結(jié)果集轉(zhuǎn)換為Javabean作為value,并指定某列為key,封裝到HashMap中。相當(dāng)于對(duì)每行數(shù)據(jù)進(jìn)行與BeanHandler相同的處理后,再指定列值為Key封裝到HashMap中。1publicstaticvoidqueryToBeanMap(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromauction";4 Map<Integer,AuctionDO>rs=queryRunner.query(conn,sql,5 newBeanMapHandler<Integer,AuctionDO>(AuctionDO.class,1));6 System.out.println("BeanMapHandler:"+rs);7}6.4.2ResultSetHandler⑨BeanMa6.4.2ResultSetHandler⑩ScalarHandler<T>:獲取結(jié)果集中第一行數(shù)據(jù)指定列的值,常用來(lái)進(jìn)行單值查詢,示例代碼如下。(2)更新類操作方法介紹在執(zhí)行insert、delete、update等更新數(shù)據(jù)庫(kù)方法時(shí),將調(diào)用QueryRunner的update方法,該方法返回影響的記錄條數(shù)。1publicstaticvoidqueryToBeanMap(Connectionconn)throwsSQLException{2 QueryRunnerqueryRunner=newQueryRunner();3 Stringsql="select*fromauction";4 intrs=runner.query(conn,sql,newScalarHandler<Integer>());5 System.out.println("ScalarHandler:"+rs);6 Stringrs=runner.query(conn,sql,newScalarHandler<String>(2));7 //或者Stringrs=runner.query(conn,sql,newScalarHandler<String>("userName"));8 System.out.println("ScalarHandler:"+rs);9}6.4.2ResultSetHandler⑩Scalar6.4.3資源釋放DBUtils框架提供了關(guān)閉連接、裝載JDBC驅(qū)動(dòng)程序等常規(guī)工作的工具類,里面的所有方法都是靜態(tài)的。主要方法如下:publicstaticvoidclose()throwsSQLExceptionDBUtils類提供了3個(gè)重載的關(guān)閉方法。這些方法檢查所提供的參數(shù)是否為NULL,如果不是,它們就關(guān)閉Connection、Statement和ResultSet6.4.3資源釋放DBUtils框架提供了關(guān)閉連接、裝載6.5簡(jiǎn)易購(gòu)物商城使用DBCP作為數(shù)據(jù)庫(kù)連接池連接數(shù)據(jù)庫(kù),與DBUtils框架整合來(lái)改寫簡(jiǎn)易購(gòu)物商城的前臺(tái)系統(tǒng),將商品、用戶、個(gè)人信息持久化存儲(chǔ)到MySQL數(shù)據(jù)庫(kù)中。6.5簡(jiǎn)易購(gòu)物商城使用DBCP作為數(shù)據(jù)庫(kù)連接池連接數(shù)據(jù)庫(kù),6.5簡(jiǎn)易購(gòu)物商城6.5.1數(shù)據(jù)庫(kù)設(shè)計(jì)6.5.2DAO接口實(shí)現(xiàn)6.5簡(jiǎn)易購(gòu)物商城6.5.1數(shù)據(jù)庫(kù)設(shè)計(jì)6.5.1數(shù)據(jù)庫(kù)設(shè)計(jì)根據(jù)前面章節(jié)的需求分析,簡(jiǎn)易購(gòu)物商城前臺(tái)系統(tǒng)共設(shè)計(jì)數(shù)據(jù)庫(kù)表三張,首先創(chuàng)建數(shù)據(jù)庫(kù)shop,然后在數(shù)據(jù)庫(kù)shop中設(shè)計(jì)auction、user和personalInfo三張數(shù)據(jù)表,具體表結(jié)構(gòu)如圖6.23~圖6.25所示。圖6.23action商品表圖6.24user用戶表圖6.25personal個(gè)人信息表6.5.1數(shù)據(jù)庫(kù)設(shè)計(jì)根據(jù)前面章節(jié)的需求分析,簡(jiǎn)易購(gòu)物商城前6.5.2DAO接口實(shí)現(xiàn)首先在工程中導(dǎo)入相關(guān)的jar包,并創(chuàng)建.zzti.dao包中各個(gè)接口的具體實(shí)現(xiàn)類,放在.zzti.dao.impl.mysql包下,如圖6.26和圖6.27所示。圖6.26導(dǎo)入相關(guān)jar包圖6.27基于DBUtils的DAO實(shí)現(xiàn)6.5.2DAO接口實(shí)現(xiàn)首先在工程中導(dǎo)入相關(guān)的jar包,并6.5.2DAO接口實(shí)現(xiàn)各個(gè)實(shí)現(xiàn)類的具體實(shí)現(xiàn)代碼如下所示。(1)AuctionDAOImpl1publicclassAuctionDAOImplimplementsAuctionDAO{2 @Override3 publicAuctionDOgetAuction(Stringid)throwsSQLException{4 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());5 Stringsql="select*fromauctionwhereid=?";6 AuctionDOauctionDO=queryrunner.query(sql,7 newBeanHandler<AuctionDO>(AuctionDO.class),id);8 returnauctionDO;9 }10 @Override11 publicvoidaddAuction(AuctionDOauc)throwsSQLException{12 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());13 Stringsql="insertintoauctionvalues(?,?,?,?)";14 Object[]params=newObject[]{UUID.randomUUID().toString(),15 auc.getTitle(),auc.getDescription(),auc.getPrice()};16 queryrunner.update(sql,params);17 }6.5.2DAO接口實(shí)現(xiàn)各個(gè)實(shí)現(xiàn)類的具體實(shí)現(xiàn)代碼如下所示。6.5.2DAO接口實(shí)現(xiàn)各個(gè)實(shí)現(xiàn)類的具體實(shí)現(xiàn)代碼如下所示。(1)AuctionDAOImpl18 @Override19 publicList<AuctionDO>getAll()throwsSQLException{20 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());21 Stringsql="select*fromauction";22 List<AuctionDO>list=queryrunner.query(sql,23 newBeanListHandler<AuctionDO>(AuctionDO.class));24 returnlist;25 }26 @Override27 publicvoiddeleteAuction(Stringid)throwsSQLException{28 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());29 Stringsql="deletefromauctionwhereid=?";30 queryrunner.update(sql,id);31 }32 @Override33 publicvoidupdateAuction(AuctionDOauc)throwsSQLException{34 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());35 Stringsql="updateauctionsettitle=?,description=?,price=?whereid=?";36 Object[]params=newObject[]{auc.getTitle(),37 auc.getDescription(),auc.getPrice(),auc.getId()};38 queryrunner.update(sql,params);39 }40}
6.5.2DAO接口實(shí)現(xiàn)各個(gè)實(shí)現(xiàn)類的具體實(shí)現(xiàn)代碼如下所示。6.5.2DAO接口實(shí)現(xiàn)(2)PersonalDAOImpl1publicclassPersonalDAOImplimplementsPersonalDAO{2 @Override3 publicPersonalInfoDOgetPersonalInfo(Stringusername)throwsSQLException{4 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());5 Stringsql="select*frompersonalInfowhereusername=?";6 PersonalInfoDOp=queryrunner.query(sql,7 newBeanHandler<PersonalInfoDO>(PersonalInfoDO.class),username);8 returnp;9 }10@Override11publicvoidsetPersonalInfo(Stringusername,PersonalInfoDOp)throwsSQLException12{13 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());14 Stringsql="insertintopersonalInfovalues(?,?,?,?,?,?,?,?,?,?)";15 Object[]params=newObject[]{16 username,17 p.getAge(),18 p.getGender(),19 p.getAddress(),20 p.getTel(),21 p.getEmail(),22 p.getGraduateSchool(),23 p.getHighestEducation(),24 p.getMajor(),25 p.getRealName()26 };27 queryrunner.update(sql,params);28 }29}
6.5.2DAO接口實(shí)現(xiàn)(2)PersonalDAOImp6.5.2DAO接口實(shí)現(xiàn)(3)UserDAOImpl1publicclassUserDAOImplimplementsUserDAO{2publicList<UserDO>getAll()throwsSQLException{3 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());4 Stringsql="select*fromuser";5 List<UserDO>list=queryrunner.query(sql,6 newBeanListHandler<UserDO>(UserDO.class));7 returnlist;8 }9 publicUserDOfindUser(Stringusername,Stringpassword)throwsSQLException{10 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());11 Stringsql="select*fromuserwhereusername=?andpassword=?";12 Object[]params=newObject[]{username,password};13 UserDOuserDO=queryrunner.query(sql,14 newBeanHandler<UserDO>(UserDO.class),params);15 returnuserDO;16 }17 publicintinsertUser(UserDOu)throwsSQLException{18 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());19 Stringsql="insertintouservalues(?,?)";20 Object[]params=newObject[]{u.getUsername(),u.getPassword()};21 returnqueryrunner.update(sql,params);22 }23 publicintdeleteUser(Stringid)throwsSQLException{24 QueryRunnerqueryrunner=newQueryRunner(DBUtil.getDataSource());25 Stringsql="deletefromuserwhereusername=?";26 returnqueryrunner.update(sql,id);27 }28}
6.5.2DAO接口實(shí)現(xiàn)(3)UserDAOImpl1第6章數(shù)據(jù)庫(kù)整合開發(fā)
第6章數(shù)據(jù)庫(kù)整合開發(fā)本章內(nèi)容MySQL簡(jiǎn)介
JDBC概述數(shù)據(jù)庫(kù)連接池
DBUtils框架簡(jiǎn)介簡(jiǎn)易購(gòu)物商城本章內(nèi)容MySQL簡(jiǎn)介6.1MySQL簡(jiǎn)介MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),它由瑞典MySQLAB公司開發(fā),目前屬于Oracle旗下的產(chǎn)品。MySQL是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)之一,在Web應(yīng)用方面,MySQL是最好的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)(RelationalDataBaseManagementSystem,RDBMS)應(yīng)用軟件。6.1MySQL簡(jiǎn)介MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),它由瑞6.2
JDBC概述Java數(shù)據(jù)庫(kù)連接技術(shù)(JavaDataBaseConnectivity,JDBC)是Java訪問(wèn)數(shù)據(jù)庫(kù)資源的標(biāo)準(zhǔn),JDBC標(biāo)準(zhǔn)定義了一組JavaAPI,允許用戶寫出SQL語(yǔ)句,然后交給數(shù)據(jù)庫(kù)。6.2JDBC概述Java數(shù)據(jù)庫(kù)連接技術(shù)(JavaD6.2
JDBC概述如圖6.1所示,如果沒(méi)有JDBC或者ODBC,開發(fā)人員必須使用不同的一組API來(lái)訪問(wèn)不同的數(shù)據(jù)庫(kù);而有了JDBC或者ODBC,則只需要使用一組API,再加上數(shù)據(jù)庫(kù)廠商提供的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序就可以訪問(wèn)不同的數(shù)據(jù)庫(kù)了,如圖6.2所示。所以,利用JDBC,我們就可以把同一個(gè)企業(yè)級(jí)Java應(yīng)用移植到另一個(gè)數(shù)據(jù)庫(kù)應(yīng)用上。6.2JDBC概述如圖6.1所示,如果沒(méi)有JDBC或6.2
JDBC概述圖6.1應(yīng)用程序直接訪問(wèn)數(shù)據(jù)庫(kù)圖6.2應(yīng)用程序訪問(wèn)JDBC6.2JDBC概述圖6.1應(yīng)用程序直接訪問(wèn)數(shù)據(jù)庫(kù)圖6.6.2
JDBC概述JDBC主要包含兩部分:面向Java程序員的JDBCAPI和面向數(shù)據(jù)庫(kù)廠商的JDBCDriveAPI。1.面向Java程序員的JDBCAPI它主要由一系列的接口定義所構(gòu)成。java.sql.DriveManager:該接口定義了用來(lái)處理裝載驅(qū)動(dòng)的程序,并且為創(chuàng)建新的數(shù)據(jù)庫(kù)連接提供支持。java.sql.Connection:該接口定義了實(shí)現(xiàn)對(duì)某一種指定數(shù)據(jù)庫(kù)連接的功能。6.2JDBC概述JDBC主要包含兩部分:面向Java程6.2
JDBC概述java.sql.Statement:該接口定義了在一個(gè)給定的連接中作為SQL語(yǔ)句執(zhí)行聲明的容器以實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作。它主要包含有如下兩種子類型。java.sql.PreparedStatement:該接口定義了用于執(zhí)行帶或不帶IN參數(shù)的預(yù)編譯SQL語(yǔ)句。java.sql.CallableStatement:該接口定義了用于執(zhí)行數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程的調(diào)用。java.sql.ResultSet:該接口定義了執(zhí)行數(shù)據(jù)庫(kù)的操作后返回的結(jié)果集。2.面向數(shù)據(jù)庫(kù)廠商的JDBCDriveAPI6.2JDBC概述java.sql.Statement:6.2
JDBC概述6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接6.2.2SQL的執(zhí)行6.2.3SQL執(zhí)行結(jié)果的處理6.2JDBC概述6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接在Java程序中要操作數(shù)據(jù)庫(kù),一般應(yīng)該通過(guò)如下幾步。1.下載數(shù)據(jù)庫(kù)開發(fā)所需要的驅(qū)動(dòng)包用戶可以從對(duì)應(yīng)的數(shù)據(jù)庫(kù)廠商的官網(wǎng)進(jìn)行下載,例如,下載MySQL驅(qū)動(dòng)包,如圖6.3所示,選擇“JDBCDriverforMySQL”進(jìn)行下載。下載的驅(qū)動(dòng)包是一個(gè)壓縮包,將包內(nèi)的“mysql-connector-java-5.1.42-bin.jar”復(fù)制到“WebRoot\lib”文件夾下,如圖6.4所示。6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接在Java程序中要操作數(shù)據(jù)庫(kù),一6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接圖6.3下載MySQL驅(qū)動(dòng)包圖6.4加載MySQL驅(qū)動(dòng)包6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接圖6.3下載MySQL驅(qū)動(dòng)包圖6.2.1
創(chuàng)建數(shù)據(jù)庫(kù)連接2.?dāng)?shù)據(jù)庫(kù)管理工具在開發(fā)中,我們一般會(huì)創(chuàng)建一個(gè)專用于創(chuàng)建數(shù)據(jù)庫(kù)連接和釋放數(shù)據(jù)庫(kù)連接的工具類。建立與數(shù)據(jù)庫(kù)的連接需要完成如下兩個(gè)步驟。(1)加載驅(qū)動(dòng)類到內(nèi)存Class.forName("com.mysql.jdbc.Driver");(2)創(chuàng)建與數(shù)據(jù)源的連接Connectioncon=DriverManager.getConnection(Stringurl,Stringusername,Stringpassword);6.2.1創(chuàng)建數(shù)據(jù)庫(kù)連接2.?dāng)?shù)據(jù)庫(kù)管理工具6.2.2
SQL的執(zhí)行在實(shí)際開發(fā)中,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí),只需要調(diào)用以下方法:
Connectionconn=DBUtil.getConnection();就可以獲得一個(gè)java.sql.Connection類型的數(shù)據(jù)庫(kù)連接對(duì)象,通過(guò)這個(gè)連接對(duì)象,用戶可以操作數(shù)據(jù)庫(kù),發(fā)送目標(biāo)SQL給數(shù)據(jù)庫(kù),并接收響應(yīng)結(jié)果。6.2.2SQL的執(zhí)行在實(shí)際開發(fā)中,當(dāng)需要訪問(wèn)數(shù)據(jù)庫(kù)時(shí),6.2.2
SQL的執(zhí)行在已建立數(shù)據(jù)庫(kù)連接的基礎(chǔ)上,向數(shù)據(jù)庫(kù)發(fā)送要執(zhí)行的SQL語(yǔ)句的接口是Statement。Statement用于執(zhí)行靜態(tài)的SQL語(yǔ)句。(1)java.sql.Statementjava.sql.Statement類型的對(duì)象,是通過(guò)java.sql.Connection對(duì)象獲得的,其代碼如下:Statementst=conn.createStatement();所獲得的Statement對(duì)象st,可以用來(lái)執(zhí)行SQL語(yǔ)句,Statement執(zhí)行SQL語(yǔ)句的主要方法有兩個(gè):intexecuteUpdate(Stringsql);ResultSetexecuteQuery(Stringsql);6.2.2SQL的執(zhí)行在已建立數(shù)據(jù)庫(kù)連接的基礎(chǔ)上,向數(shù)據(jù)6.2.2
SQL的執(zhí)行其中,executeUpdate(Stringsql)方法可用來(lái)執(zhí)行數(shù)據(jù)庫(kù)的更新操作。該方法的返回值類型為int,代表影響的記錄條數(shù),即插入了幾條數(shù)據(jù),修改了幾條數(shù)據(jù),刪除了幾條數(shù)據(jù)等。而executeQuery(Stringsql)方法可用來(lái)執(zhí)行數(shù)據(jù)庫(kù)的查詢操作。該方法的返回值類型是java.sql.ResultSet,該類型能夠存儲(chǔ)數(shù)據(jù)庫(kù)返回的所有記錄,并支持按條讀取結(jié)果數(shù)據(jù)。6.2.2SQL的執(zhí)行其中,executeUpdate(6.2.2
SQL的執(zhí)行(2)java.sql.PreparedStatement接口在Statement中可以看到,動(dòng)態(tài)SQL的生成是通過(guò)字符串拼接而成的,但是字符串拼接會(huì)帶來(lái)很多的安全隱患,其中最為常見(jiàn)的安全漏洞就是SQL注入。下面以登錄功能為例,在.zzti.dao包下的UserDAO接口中定義登錄判斷方法,代碼如下:publicUserDOfindUser(Stringusername,Stringpassword)throwsSQLException;具體代碼如下:6.2.2SQL的執(zhí)行(2)java.sql.Prepa6.2.2SQL的執(zhí)行在代碼的第6行,我們將拼接后的SQL語(yǔ)句打印到控制臺(tái)進(jìn)行觀察。在第12行處,需要將獲得的數(shù)據(jù)庫(kù)查詢結(jié)果進(jìn)行封裝,這里暫不實(shí)現(xiàn)這個(gè)功能。下面先來(lái)創(chuàng)建一個(gè).zzti.dao.impl.mysql.
jdbc.test.UserDAOImplTest類,對(duì)方法findUser進(jìn)行測(cè)試,具體代碼如下。1publicUserDOfindUser(Stringusername,Stringpassword)throwsSQLException{2 Stringsql="select*fromuserwhereusername='"+3 username+4 "'andpassword='"+5 password+"'";6 System.out.println("登錄sql是:"+sql);7 Connectionconn=DBUtil.getConnection();8 Statementst=conn.createStatement();9 ResultSetrs=st.executeQuery(sql);10 if(rs.next()){11 UserDOuser=newUserDO();12 //將查詢結(jié)果封裝到user對(duì)象中,此處先不處理13 returnuser;14 }15 returnnull;16 }6.2.2SQL的執(zhí)行1publicUserDO6.2.2SQL的執(zhí)行Assert.assertNotNull(Objecto)是Junit的斷言,該斷言方法判斷對(duì)象o是否為空,為空則當(dāng)前測(cè)試方法通過(guò),否則測(cè)試方法失敗。執(zhí)行結(jié)果顯示,使用不存在的用戶名和密碼,調(diào)用登錄方法執(zhí)行結(jié)果為登錄正常。在輸出的SQL結(jié)果顯示,最終執(zhí)行的SQL如下:
1publicclassUserDAOImplTest{2 privateUserDAOuserDAO=(UserDAO)3 DAOFactory.getDAO(".zzti.dao.impl.mysql.jdbc.UserDAOImpl");4 @Test5 publicvoidtestFinUser(){6 Stringusername="test'or1
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024個(gè)人的簡(jiǎn)單借款合同
- 國(guó)際貿(mào)易協(xié)議樣本
- 廠房租賃合同范例
- 特色農(nóng)產(chǎn)品胡柚購(gòu)銷合同法律問(wèn)題探討
- 共同投資開設(shè)武術(shù)館協(xié)議
- 標(biāo)準(zhǔn)入職協(xié)議書范例
- 旅行社與導(dǎo)游勞動(dòng)合同范本
- 2023年高考地理第一次模擬考試卷-(湖南A卷)(全解全析)
- 房地產(chǎn)代理合同模板
- 2024年建筑渣土運(yùn)輸合同范文
- 荔枝包裝工藝設(shè)計(jì)
- 浙江省9+1高中聯(lián)盟2022-2023學(xué)年高一上學(xué)期11月期中考物理試題(解析版)
- 政府?dāng)?shù)據(jù)信息保密協(xié)議范本
- 聚酯生產(chǎn)技術(shù) 聚酯工藝流程介紹
- 關(guān)于日本動(dòng)漫介紹ppt
- 四年級(jí)除法豎式計(jì)算題500道
- 質(zhì)量保證體系范文(必備14篇)
- 人工智能基礎(chǔ)與應(yīng)用課件
- 兒科運(yùn)用PDCA循環(huán)改進(jìn)提高病歷書寫質(zhì)量
- 聽神經(jīng)瘤講課課件
- 2023年食品安全糧食類理論知識(shí)考試題庫(kù)(含答案)
評(píng)論
0/150
提交評(píng)論