Java程序設(shè)計(jì)基礎(chǔ)教程(慕課版)(第2版) 課件 第12單元 綜合實(shí)訓(xùn)-簡(jiǎn)易網(wǎng)上銀行系統(tǒng)_第1頁(yè)
Java程序設(shè)計(jì)基礎(chǔ)教程(慕課版)(第2版) 課件 第12單元 綜合實(shí)訓(xùn)-簡(jiǎn)易網(wǎng)上銀行系統(tǒng)_第2頁(yè)
Java程序設(shè)計(jì)基礎(chǔ)教程(慕課版)(第2版) 課件 第12單元 綜合實(shí)訓(xùn)-簡(jiǎn)易網(wǎng)上銀行系統(tǒng)_第3頁(yè)
Java程序設(shè)計(jì)基礎(chǔ)教程(慕課版)(第2版) 課件 第12單元 綜合實(shí)訓(xùn)-簡(jiǎn)易網(wǎng)上銀行系統(tǒng)_第4頁(yè)
Java程序設(shè)計(jì)基礎(chǔ)教程(慕課版)(第2版) 課件 第12單元 綜合實(shí)訓(xùn)-簡(jiǎn)易網(wǎng)上銀行系統(tǒng)_第5頁(yè)
已閱讀5頁(yè),還剩78頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第12單元綜合實(shí)訓(xùn)——簡(jiǎn)易網(wǎng)上銀行系統(tǒng)Java程序設(shè)計(jì)基礎(chǔ)教程((慕課版)(第2版))目錄導(dǎo)航12.1

JDBC12.3測(cè)試12.2日志12.4事務(wù)12.5簡(jiǎn)易網(wǎng)上銀行系統(tǒng)12.6單元小結(jié)12.1.1JDBC簡(jiǎn)介JDBC的全稱是JavaDatabaseConnectivity(Java數(shù)據(jù)庫(kù)連接),它是一套用于執(zhí)行SQL(StructuredQueryLanguage,結(jié)構(gòu)化查詢語(yǔ)言)語(yǔ)句的JavaAPI。通過(guò)該API,開(kāi)發(fā)者可以快速連接到關(guān)系數(shù)據(jù)庫(kù),并使用SQL實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的增、刪、改、查功能。JDBC要求各數(shù)據(jù)庫(kù)廠商按照統(tǒng)一的規(guī)范提供數(shù)據(jù)庫(kù)驅(qū)動(dòng),用戶無(wú)須直接與底層數(shù)據(jù)進(jìn)行交互,大大增強(qiáng)了代碼的可移植性。JDBC模型示意圖如圖所示。12.1.2JDBC的通用API導(dǎo)入MySQL驅(qū)動(dòng)包的步驟如下。01OPTIONDriver接口step01

右擊項(xiàng)目名稱,在彈出的快捷菜單中選擇“BuildPath”→“ConfigureBuildPath”,如左圖所示;進(jìn)入“JavaBuildPath”界面,如右圖所示。12.1.2JDBC的通用APIstep02

在“Libraries”選項(xiàng)卡中單擊“AddExternalJARs”按鈕,選擇源代碼中的MySQL驅(qū)動(dòng)包,如左圖所示。step03

然后單擊“打開(kāi)”按鈕即可,如右圖所示。12.1.2JDBC的通用APIDriverManager類用于加載JDBC驅(qū)動(dòng)并創(chuàng)建與數(shù)據(jù)庫(kù)的連接。該類有兩個(gè)靜態(tài)方法,一個(gè)是registerDriver(Driverdriver)方法,用于向DriverManager類中注冊(cè)給定的JDBC驅(qū)動(dòng)程序;另一個(gè)是getConnection(Stringurl,Stringuser,Stringpwd)方法,用于建立用戶和數(shù)據(jù)庫(kù)的連接,并返回一個(gè)Connection對(duì)象。下面通過(guò)任務(wù)12-1了解DriverManager類的使用。02OPTIONDriverManager類Connection接口代表Java程序?qū)?shù)據(jù)庫(kù)的連接,負(fù)責(zé)對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)和操作。通過(guò)Connection接口,用戶可以根據(jù)自己的需求進(jìn)行數(shù)據(jù)庫(kù)的對(duì)應(yīng)操作。

Connection接口可以創(chuàng)建Statement對(duì)象(使用createStatement()方法)、PreparedStatement對(duì)象(使用prepareStatement()方法)和CallableStatement對(duì)象(使用prepareCall()方法),這些對(duì)象分別用于將一個(gè)SQL語(yǔ)句、一個(gè)參數(shù)化的SQL語(yǔ)句和一個(gè)存儲(chǔ)過(guò)程放到數(shù)據(jù)庫(kù)服務(wù)器上執(zhí)行。Connection接口03OPTION任務(wù)12-1DriverManager類的使用publicclassDriverManagerDemo{publicstaticvoidmain(String[]args){//數(shù)據(jù)庫(kù)驅(qū)動(dòng)的URL,其模式是:jdbc:MySQL://[ip]:[port]/[databaseName][?參數(shù)名1][=參數(shù)值1][&參數(shù)名2][=參數(shù)值2]...Stringurl="jdbc:MySQL://localhost:3306/jdbc?characterEncoding=utf8&useSSL=true";//此處使用root用戶進(jìn)行連接Stringuser="root";//數(shù)據(jù)庫(kù)的密碼Stringpwd="123";//數(shù)據(jù)庫(kù)連接對(duì)象Connectionconn=null;

文件DriverManagerDemo.javatry{//使用DriverManager類獲取一個(gè)數(shù)據(jù)庫(kù)連接conn=DriverManager.getConnection(url,user,pwd);System.out.println("數(shù)據(jù)庫(kù)連接是:"+conn);//獲取到的數(shù)據(jù)庫(kù)連接}catch(SQLExceptione){e.printStackTrace();}finally{if(null!=conn){try{conn.close();}catch(SQLExceptione){e.printStackTrace();}}}}}運(yùn)行結(jié)果如圖12-6所示。12.1.2JDBC的通用APIStatement接口用于執(zhí)行靜態(tài)的SQL語(yǔ)句,并返回處理結(jié)果。Statement接口通過(guò)Connection接口的createStatement()方法獲取。該接口有3個(gè)主要的方法:execute(Stringsql)、executeUpdate(Stringsql)和executeQuery(Stringsql)。execute(Stringsql)方法用于執(zhí)行任何SQL語(yǔ)句,其返回值是一個(gè)boolean類型的對(duì)象。如果返回值為true,表明有查詢結(jié)果,可以通過(guò)Statement接口的getResultSet()方法獲取查詢結(jié)果。executeUpdate(Stringsql)方法用于執(zhí)行SQL語(yǔ)句中的INSERT(插入)、UPDATE(更新)和DELETE(刪除)語(yǔ)句。該方法返回圖12-6運(yùn)行結(jié)果

一個(gè)int類型的值,表示受該語(yǔ)句影響的記錄數(shù)。executeQuery(Stringsql)方法用于執(zhí)行SQL語(yǔ)句中的SELECT(查詢)語(yǔ)句,該方法返回一個(gè)ResultSet對(duì)象。下面通過(guò)任務(wù)12-2了解Statement接口的使用。04OPTIONStatement接口任務(wù)12-2Statement接口的使用publicclassStatementDemo{publicstaticvoidmain(String[]args){//創(chuàng)建一個(gè)表StringcreateTableSql="createtableusers(idintprimarykey,"+"namevarchar(40),passwordvarchar(32),shortNamevarchar(40),"+"accountvarchar(1000))"+"charactersetutf8collateutf8_general_ci;";

//插入一條數(shù)據(jù)StringinsertValueSql="insertintousersvalues(100001,\"zhangsan\","+"\"123456\",\"zs\",\"****,***\")";//數(shù)據(jù)庫(kù)驅(qū)動(dòng)的URL,其模式是:jdbc:MySQL://[ip]:[port]/[databaseName][?參數(shù)名1][=參數(shù)值1][&參數(shù)名2][=參數(shù)值2]...Stringurl="jdbc:MySQL://localhost:3306/jdbc?characterEncoding=utf8&useSSL=true";//此處使用root用戶進(jìn)行連接Stringuser="root";//數(shù)據(jù)庫(kù)的密碼Stringpwd="123";//數(shù)據(jù)庫(kù)的Connection對(duì)象Connectionconn=null;//數(shù)據(jù)庫(kù)的Statement操作對(duì)象Statementstatement=null;文件StatementDemo.java任務(wù)12-2Statement接口的使用try{//使用DriverManager類獲取一個(gè)數(shù)據(jù)庫(kù)連接conn=DriverManager.getConnection(url,user,pwd);//設(shè)置不進(jìn)行自動(dòng)提交conn.setAutoCommit(false);

//獲取Statement對(duì)象statement=conn.createStatement();

//創(chuàng)建一個(gè)users表statement.execute(createTableSql);System.out.println("表創(chuàng)建成功,手動(dòng)提交表創(chuàng)建信息!");//手動(dòng)提交數(shù)據(jù)mit();

//插入數(shù)據(jù)intcount=statement.executeUpdate(insertValueSql);System.out.println("數(shù)據(jù)庫(kù)插入數(shù)據(jù)條數(shù):"+count);//手動(dòng)提交數(shù)據(jù)mit();}catch(SQLExceptione){e.printStackTrace();}finally{//關(guān)閉資源if(null!=statement){try{statement.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=conn){try{conn.close();}catch(SQLExceptione){e.printStackTrace();}}}}}任務(wù)12-2Statement接口的使用運(yùn)行結(jié)果如圖12-7所示。為了驗(yàn)證表是否創(chuàng)建成功并且成功插入數(shù)據(jù),可在MySQLWorkbench中的users表進(jìn)行查詢,如圖12-8所示。PreparedStatement接口是Statement接口的子接口,用于執(zhí)行預(yù)編譯的SQL語(yǔ)句。該語(yǔ)句擴(kuò)展了帶有參數(shù)的SQL語(yǔ)句的執(zhí)行操作,使用占位符“?”來(lái)表示某處需要一個(gè)參數(shù),并通過(guò)set×××()方法進(jìn)行參數(shù)賦值。值得注意的是,PreparedStatement接口支持批處理操作。ResultSet接口用于保存JDBC執(zhí)行查詢操作時(shí)返回的結(jié)果集。該結(jié)果集封裝在邏輯表格中,ResultSet接口使用游標(biāo)進(jìn)行數(shù)據(jù)的獲取。游標(biāo)默認(rèn)指向表格的第一行之前,調(diào)用next()方法時(shí)會(huì)向下一行移動(dòng)。next()方法有一個(gè)boolean類型的返回值。如果邏輯表格含有下一行數(shù)據(jù),則該方法返回true,否則返回false。通常,數(shù)據(jù)使用while條件語(yǔ)句進(jìn)行讀取。05OPTIONPreparedStatement接口和ResultSet接口任務(wù)12-3PreparedStatement接口和ResultSet接口的使用publicclassQueryDemo{publicstaticvoidmain(String[]args){//數(shù)據(jù)庫(kù)驅(qū)動(dòng)的URL,其模式是:jdbc:MySQL://[ip]:[port]/[databaseName][?參數(shù)名1][=參數(shù)值1][&參數(shù)名2][=參數(shù)值2]...Stringurl="jdbc:MySQL://localhost:3306/jdbc?characterEncoding=utf8&useSSL=true";//此處使用root用戶進(jìn)行連接Stringuser="root";//數(shù)據(jù)庫(kù)的密碼Stringpwd="123";

//判斷表是否存在,若存在則刪除表StringsqlDel="droptableifexistsusers";//創(chuàng)建表StringsqlCreate="createtableusers(idintprimarykey,namevarchar(40),"+"short_namevarchar(40),passwordvarchar(40),accountvarchar(1000),"+"input_datevarchar(10),input_timevarchar(19),last_update_datevarchar(10),"+"last_update_timevarchar(19))";文件QueryDemo.java任務(wù)12-3PreparedStatement接口和ResultSet接口的使用//插入數(shù)據(jù)StringsqlInsert1="insertintousersvalues(100001,\"zhangsan\",\"zs\",\"123321\",\"*********\",\"2017-07-03\",\"2017-07-0315:12:45\",\"2017-07-03\",\"2017-07-0315:12:45\")";StringsqlInsert2="insertintousersvalues(100002,\"lisi\",\"ls\",\"123456\",\"*********\",\"2017-07-03\",\"2017-07-0315:12:45\",\"2017-07-03\",\"2017-07-0315:12:45\")";StringsqlInsert3="insertintousersvalues(100003,\"wangwu\",\"ww\",\"654321\",\"*********\",\"2017-07-03\",\"2017-07-0315:12:45\",\"2017-07-03\",\"2017-07-0315:12:45\")";StringsqlInsert4="insertintousersvalues(100004,\"zhaoliu\",\"zs\",\"123654\",\"*********\",\"2017-07-03\",\"2017-07-0315:12:45\",\"2017-07-03\",\"2017-07-0315:12:45\")";//查詢數(shù)據(jù)StringquerySql="selectid,name,short_namefromuserswhereid>?";Connectionconn=null;Statementst=null;PreparedStatementps=null;ResultSetrs=null;try{//使用DriverManager類獲取一個(gè)數(shù)據(jù)庫(kù)連接conn=DriverManager.getConnection(url,user,pwd);//獲取Statement對(duì)象st=conn.createStatement();//如果表存在,則將表刪除任務(wù)12-3PreparedStatement接口和ResultSet接口的使用st.execute(sqlDel);//創(chuàng)建表st.execute(sqlCreate);//插入預(yù)埋數(shù)據(jù)st.execute(sqlInsert1);st.execute(sqlInsert2);st.execute(sqlInsert3);st.execute(sqlInsert4);

//創(chuàng)建PreparedStatement對(duì)象ps=conn.prepareStatement(querySql);//填充參數(shù)ps.setInt(1,100002);//進(jìn)行查詢r(jià)s=ps.executeQuery();

//按行讀取數(shù)據(jù)while(rs.next()){System.out.println(rs.getString(1)+""+rs.getString(3)+""+rs.getString(2));}}catch(SQLExceptione){e.printStackTrace();}finally{//關(guān)閉資源if(null!=rs){try{rs.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=ps){try{ps.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=st){try{st.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=conn){try{conn.close();}catch(SQLExceptione){e.printStackTrace();}}}}}任務(wù)12-3PreparedStatement接口和ResultSet接口的使用運(yùn)行結(jié)果如圖12-9所示。目錄導(dǎo)航12.1

JDBC12.3測(cè)試12.2日志12.4事務(wù)12.5簡(jiǎn)易網(wǎng)上銀行系統(tǒng)12.6單元小結(jié)12.2日志日志是記錄程序運(yùn)行信息的文本。與飛機(jī)的黑匣子和航海日志一樣,可以通過(guò)程序運(yùn)行的日志信息判斷程序的運(yùn)行情況。特別是在遇到異常時(shí),因?yàn)槌绦虿渴鹪诜?wù)器上,不像在本地一樣可以通過(guò)運(yùn)行發(fā)現(xiàn)問(wèn)題,日志就成了至關(guān)重要的查錯(cuò)手段。目前使用的日志中,Log4j是比較穩(wěn)定且常用的日志之一,它是一個(gè)Apache開(kāi)源的項(xiàng)目。通過(guò)使用Log4j,我們可以控制日志信息輸送的目的地是控制臺(tái)、文件、GUI組件,甚至是套接口服務(wù)器、網(wǎng)絡(luò)終端的事件記錄器、UNIXSyslog守護(hù)進(jìn)程等;也可以控制每一條日志的輸出格式;通過(guò)定義每一條日志信息的級(jí)別,能夠更加細(xì)致地控制日志的生成過(guò)程。Log4j最大的特點(diǎn)之一就是可以通過(guò)配置修改日志輸出的級(jí)別而不需要修改任何代碼。Log4j概述01OPTION12.2日志Log4j的級(jí)別02OPTIONLog4j的日志級(jí)別一般分為5種,分別是DEBUG、INFO、WARN、ERROR和FATAL。日志的級(jí)別是為了協(xié)助相關(guān)人員快速查詢對(duì)應(yīng)的問(wèn)題而設(shè)定的。Log4j建議只使用4個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是ERROR、WARN、INFO、DEBUG。FATAL級(jí)別表明每個(gè)嚴(yán)重的錯(cuò)誤事件都會(huì)導(dǎo)致應(yīng)用程序的退出。FATAL級(jí)別05WARN級(jí)別表明會(huì)出現(xiàn)潛在錯(cuò)誤。一般此類日志出現(xiàn)得比較少,也比較少用。WARN級(jí)別03INFO級(jí)別用于在粗粒度級(jí)別上突出強(qiáng)調(diào)應(yīng)用程序的運(yùn)行過(guò)程。INFO級(jí)別02DEBUG級(jí)別的日志提供了應(yīng)用程序的細(xì)粒度信息,這對(duì)于應(yīng)用程序的調(diào)試是非常有用的,能夠幫助開(kāi)發(fā)者判斷程序是否符合預(yù)期。DEBUG級(jí)別01ERROR級(jí)別表明雖然發(fā)生錯(cuò)誤事件,但仍然不影響系統(tǒng)的繼續(xù)運(yùn)行。ERROR級(jí)別04目錄導(dǎo)航12.1

JDBC12.3測(cè)試12.2日志12.4事務(wù)12.5簡(jiǎn)易網(wǎng)上銀行系統(tǒng)12.6單元小結(jié)12.3.1JUnit簡(jiǎn)介JUnit是一個(gè)開(kāi)源的Java測(cè)試框架,用于編寫和運(yùn)行可重復(fù)的測(cè)試。它是用于單元測(cè)試框架體系xUnit的一個(gè)實(shí)例(用于Java語(yǔ)言),包含以下特性。

用于測(cè)試期望結(jié)果的斷言(Assertion)功能。

用于共享測(cè)試數(shù)據(jù)的測(cè)試工具。

用于方便組織和運(yùn)行測(cè)試套件的框架。

支持圖形和文本界面的測(cè)試運(yùn)行器。JUnit屬于白盒測(cè)試框架,程序員知道軟件是如何實(shí)現(xiàn)相關(guān)功能的。12.3.2功能測(cè)試及斷言JUnit的強(qiáng)大之處在于它可以對(duì)測(cè)試期望結(jié)果進(jìn)行斷言,這使得測(cè)試任務(wù)可以自動(dòng)運(yùn)行、自行驗(yàn)證,它會(huì)告訴我們測(cè)試是否通過(guò),而無(wú)須開(kāi)發(fā)者和維護(hù)者判斷結(jié)果是否正確。

使用JUnit進(jìn)行單元測(cè)試需要導(dǎo)入測(cè)試必需的JAR包,讀者可自行下載或者使用源代碼中提供的JAR包,其導(dǎo)入方式同JDBC驅(qū)動(dòng)包的導(dǎo)入方式一樣。任務(wù)12-4簡(jiǎn)單的JUnit測(cè)試任務(wù)文件JunitDemo.javapublicclassJunitDemo{publicintaddDemo(intx,inty){returnx+y;}publicintminus(intx,inty){if(x<=y){return0;}returnx-y;}publicintmulti(intx,inty){returnx*y;}publicintdevide(intx,inty){if(y==0){thrownewIllegalArgumentException("IllegalArgument:y="+y);}returnx/y;}}12.3.2功能測(cè)試及斷言文件JunitDemoTest.javapublicclassJunitDemoTest{privatestaticJunitDemojunit=newJunitDemo();@TestpublicvoidtestAddDemo(){System.out.println("addDemo開(kāi)始測(cè)試:");Assert.assertEquals(junit.addDemo(10,3),13);System.out.println("測(cè)試通過(guò)!");}@TestpublicvoidtestMinus(){System.out.println("minus開(kāi)始測(cè)試:");Assert.assertEquals(junit.minus(15,2),13);System.out.println("測(cè)試通過(guò)!");}@TestpublicvoidtestMulti(){System.out.println("multi開(kāi)始測(cè)試:");Assert.assertEquals(junit.multi(15,2),30);System.out.println("測(cè)試通過(guò)!");}@TestpublicvoidtestDevide(){System.out.println("devide開(kāi)始測(cè)試:");Assert.assertEquals(junit.devide(15,3),5);System.out.println("測(cè)試通過(guò)!");}}運(yùn)行結(jié)果如圖12-10所示。12.3.2功能測(cè)試及斷言為了直觀地查看測(cè)試是否成功,Eclipse提供了“JUnit”選項(xiàng)卡,專門用于查看測(cè)試方法是否正確運(yùn)行,如圖所示。為了便于測(cè)試,JUnit提供了豐富的注解,包括@BeforeClass、@Before、@After和@AfterClass等。其中@BeforeClass和@AfterClass是當(dāng)類開(kāi)始運(yùn)行時(shí)執(zhí)行的初始化模塊和資源釋放模塊,它們?cè)陬悎?zhí)行時(shí)只運(yùn)行一次。@Before、@After與@BeforeClass、@AfterClass不同的地方是這兩個(gè)注解在每一個(gè)方法運(yùn)行的時(shí)候都會(huì)執(zhí)行。如果一次測(cè)試同時(shí)運(yùn)行了3個(gè)測(cè)試方法,那么@Before和@After注解注釋的方法會(huì)分別執(zhí)行3次。任務(wù)12-5JUnit的注解文件JunitDemoTest2.javapublicclassJunitDemoTest2{privatestaticJunitDemojunit=newJunitDemo();@BeforeClasspublicstaticvoidinit(){System.out.println("開(kāi)始運(yùn)行JUnit測(cè)試任務(wù):");System.out.println("*****************************");}@AfterClasspublicstaticvoiddestroy(){System.out.println("*****************************");System.out.println("完成一次JUnit測(cè)試任務(wù)");}@BeforepublicvoidbeginTest(){System.out.println("****開(kāi)始運(yùn)行一個(gè)新的測(cè)試方法****");}@AfterpublicvoidendTest(){System.out.println("****結(jié)束一個(gè)測(cè)試方法的運(yùn)行****");}@TestpublicvoidtestAddDemo(){System.out.println("addDemo開(kāi)始測(cè)試:");Assert.assertEquals(junit.addDemo(10,3),13);System.out.println("測(cè)試通過(guò)!");}

@TestpublicvoidtestMinus(){System.out.println("minus開(kāi)始測(cè)試:");Assert.assertEquals(junit.minus(15,2),13);System.out.println("測(cè)試通過(guò)!");}@TestpublicvoidtestMulti(){System.out.println("multi開(kāi)始測(cè)試:");Assert.assertEquals(junit.multi(15,2),30);System.out.println("測(cè)試通過(guò)!");}@TestpublicvoidtestDevide(){System.out.println("devide開(kāi)始測(cè)試:");Assert.assertEqualss(junit.devide(15,3),5);System.out.println("測(cè)試通過(guò)!");}}任務(wù)12-5JUnit的注解運(yùn)行結(jié)果如圖12-12和圖12-13所示。有些讀者在運(yùn)行該任務(wù)時(shí),會(huì)遇到JUnit選項(xiàng)卡拋出initializationError錯(cuò)誤的情況,這是沒(méi)有導(dǎo)入hamcrest-core-1.3.jar這個(gè)JAR包導(dǎo)致的,如圖12-14所示。導(dǎo)入它后運(yùn)行正常。圖12-12運(yùn)行結(jié)果圖12-13運(yùn)行結(jié)果圖12-14initializationError錯(cuò)誤目錄導(dǎo)航12.1

JDBC12.3測(cè)試12.2日志12.4事務(wù)12.5簡(jiǎn)易網(wǎng)上銀行系統(tǒng)12.6單元小結(jié)12.4事務(wù)一個(gè)邏輯工作單元如果要成為事務(wù),必須滿足所謂的ACID屬性,即原子性(Atomic)、一致性(Consistent)、隔離性(Insulation)和持久性(Duration)。01OPTION事務(wù)的特性事務(wù)必須是原子工作單元,對(duì)于其數(shù)據(jù)修改,要么全都執(zhí)行,要么全都不執(zhí)行。如果系統(tǒng)只執(zhí)行這些操作的一個(gè)子集,就會(huì)破壞事務(wù)的總體目標(biāo)。01一致性是指事務(wù)在完成時(shí),必須使所有的數(shù)據(jù)都保持一致?tīng)顟B(tài)。在相關(guān)數(shù)據(jù)庫(kù)中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。02隔離性要求由并發(fā)事務(wù)所做的修改必須與任何其他并發(fā)事務(wù)所做的修改相互隔離。事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務(wù)修改它之前的狀態(tài),要么是另一并發(fā)事務(wù)修改它之后的狀態(tài)。事務(wù)不會(huì)查看中間狀態(tài)的數(shù)據(jù),這稱為隔離性。03持久性是指事務(wù)完成之后,它對(duì)于系統(tǒng)的影響是永久的,即使出現(xiàn)致命的系統(tǒng)故障也將一直保持。04原子性一致性隔離性持久性12.4事務(wù)為模擬事務(wù)模型,我們使用轉(zhuǎn)賬模型。假設(shè)有兩個(gè)賬戶——張三賬戶和李四賬戶,張三賬戶向李四賬戶轉(zhuǎn)賬500元,則只有在張三賬戶余額減少500元且李四賬戶余額增加500元時(shí),才認(rèn)為轉(zhuǎn)賬成功,具體實(shí)現(xiàn)如任務(wù)12-6所示。02OPTION事務(wù)的具體應(yīng)用任務(wù)12-6本地事務(wù)文件TransferDemo.javapackagechapter12.transactiondemo;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassTransferDemo{//定義一個(gè)Connection對(duì)象privateConnectionconn=null;privateStatementst=null;publicstaticvoidmain(String[]args){//創(chuàng)建事務(wù)模型TransferDemotd=newTransferDemo();//創(chuàng)建相關(guān)表并初始化數(shù)據(jù)td.createTableAndInsert();//查看賬戶及余額td.getAccountBalance();//調(diào)用轉(zhuǎn)賬模型td.transferDemo();//查看賬戶及余額td.getAccountBalance();//釋放資源td.destroy();}//轉(zhuǎn)賬事務(wù)模型publicvoidtransferDemo(){//假設(shè)張三向李四轉(zhuǎn)賬500元,只有在張三賬戶減少500元,//并且李四賬戶增加500元時(shí)轉(zhuǎn)賬成功。更新語(yǔ)句如下:StringsqlZS="updateaccountaseta.balance=a.balance-500wherea.account='6225001013452310'";StringsqlLS="updateaccountbsetb.balance=b.balance+500whereb.account='6225001013455700'";//執(zhí)行轉(zhuǎn)賬操作try{System.out.println("進(jìn)入轉(zhuǎn)賬流程:");st.execute(sqlZS);//手動(dòng)拋出一個(gè)異常Stringstr=null;str=str.substring(str.indexOf("_"));st.execute(sqlLS);mit();//轉(zhuǎn)賬成功,則提交事務(wù)System.out.println("轉(zhuǎn)賬成功!");}任務(wù)12-6本地事務(wù)catch(SQLExceptione){try{conn.rollback();//一旦產(chǎn)生異常,則回滾數(shù)據(jù)庫(kù)}catch(SQLExceptione1){e1.printStackTrace();}e.printStackTrace();}catch(Exceptione1){e1.printStackTrace();}}//獲取當(dāng)前賬戶余額情況publicvoidgetAccountBalance(){Connectionconn1=null;//查看兩者賬戶的余額StringsqlQuery="selecta.owner,a.balancefromaccountawherea.accountin('6225001013455700','6225001013452310')";//創(chuàng)建ResultSet對(duì)象查看詳情//查詢兩者賬戶余額情況PreparedStatementps=null;ResultSetrs=null;try{//獲取一個(gè)新的數(shù)據(jù)庫(kù)連接,并且將自動(dòng)提交設(shè)置為falseconn1=getConnection();conn1.setAutoCommit(false);ps=conn1.prepareStatement(sqlQuery);rs=ps.executeQuery();//獲取查詢結(jié)果while(rs.next()){System.out.println("賬戶:"+rs.getString("owner")+";余額:"+rs.getString("balance"));}}任務(wù)12-6本地事務(wù)catch(SQLExceptione){e.printStackTrace();}catch(Exceptione1){e1.printStackTrace();}finally{//代碼片段處理結(jié)束,無(wú)論執(zhí)行成功還是失敗,都釋放數(shù)據(jù)庫(kù)資源if(null!=rs){try{rs.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=ps){try{ps.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!=conn1){try{conn1.close();}catch(SQLExceptione){e.printStackTrace();}}}}//創(chuàng)建一個(gè)賬戶表,并插入兩條數(shù)據(jù)以供使用publicvoidcreateTableAndInsert(){System.out.println("進(jìn)入表創(chuàng)建及數(shù)據(jù)初始化步驟:");//如果存在賬戶表,則刪除

StringsqlDel="droptableifexistsaccount";//創(chuàng)建賬戶表accountStringsqlCreate="createtableaccount(accountvarchar(20)primarykey,"+"ownervarchar(40),balanceint,input_datevarchar(10),input_timevarchar(19),"+"last_update_datevarchar(10),last_update_timevarchar(19))";//插入一條數(shù)據(jù)zhangsanStringsqlInsertZS="INSERTINTO`jdbc`.`account`(`account`,`owner`,`balance`,`input_date`,"+"`input_time`,`last_update_date`,`last_update_time`)VALUES('6225001013452310',"+"'zhangsan','5000','2017-07-01','2017-07-0110:32:12','2017-07-01',"+"'2017-07-0110:32:12')";//插入一條數(shù)據(jù)lisiStringsqlInserLS="INSERTINTO`jdbc`.`account`(`account`,`owner`,`balance`,`input_date`,"+"`input_time`,`last_update_date`,`last_update_time`)VALUES('6225001013455700',"+"'lisi','3000','2017-07-01','2017-07-0110:32:12','2017-07-01',"+"'2017-07-0110:32:12')";任務(wù)12-6本地事務(wù)try{//使用JDBC數(shù)據(jù)庫(kù)st.execute("usejdbc");//如果表存在,則刪除st.execute(sqlDel);//創(chuàng)建表st.execute(sqlCreate);//插入數(shù)據(jù)st.execute(sqlInsertZS);st.execute(sqlInserLS);mit();}catch(SQLExceptione){//如果產(chǎn)生錯(cuò)誤,則回滾try{conn.rollback();}catch(SQLExceptione1){e1.printStackTrace();}e.printStackTrace();}System.out.println("表及數(shù)據(jù)初始化工作完成!");}//構(gòu)造方法publicTransferDemo(){//初始化數(shù)據(jù)庫(kù)連接System.out.println("數(shù)據(jù)庫(kù)連接初始化開(kāi)始:");init();System.out.println("數(shù)據(jù)庫(kù)連接初始化結(jié)束!");}

//初始化方法,用于初始化數(shù)據(jù)庫(kù)連接publicvoidinit(){//如果數(shù)據(jù)庫(kù)連接已經(jīng)被初始化了,則直接返回if(null!=conn){if(null==st){//如果Statement對(duì)象沒(méi)有被創(chuàng)建,則創(chuàng)建try{//創(chuàng)建Statement對(duì)象

st=conn.createStatement();}catch(SQLExceptione){e.printStackTrace();}}return;}任務(wù)12-6本地事務(wù)//若數(shù)據(jù)庫(kù)連接未被初始化,進(jìn)行初始化try{//初始化數(shù)據(jù)庫(kù)連接conn=getConnection();conn.setAutoCommit(false);//初始化Statement連接st=conn.createStatement();}catch(Exceptione){e.printStackTrace();}}//銷毀方法,用于關(guān)閉數(shù)據(jù)庫(kù)連接,釋放資源publicvoiddestroy(){//如果Statement連接沒(méi)有被關(guān)閉,則關(guān)閉if(null!=st){try{st.close();}catch(SQLExceptione){e.printStackTrace();}}//如果數(shù)據(jù)庫(kù)的Connection連接沒(méi)有被關(guān)閉,則關(guān)閉if(null!=conn){try{conn.close();}catch(SQLExceptione){e.printStackTrace();}}}//獲取數(shù)據(jù)庫(kù)連接publicConnectiongetConnection()throwsException{//數(shù)據(jù)庫(kù)驅(qū)動(dòng)的URL,其模式是:jdbc:MySQL://[ip]:[port]/[databaseName][?參數(shù)名1][=參數(shù)值1][&參數(shù)名2][=參數(shù)值2]...Stringurl="jdbc:MySQL://localhost:3306/jdbc?characterEncoding=utf8&useSSL=true";//此處使用root用戶進(jìn)行連接Stringuser="root";//數(shù)據(jù)庫(kù)的密碼Stringpwd="123456";//數(shù)據(jù)庫(kù)連接對(duì)象Connectionconn=null;try{//使用DriverManager類獲取一個(gè)數(shù)據(jù)庫(kù)連接conn=DriverManager.getConnection(url,user,pwd);//返回?cái)?shù)據(jù)庫(kù)連接returnconn;}catch(SQLExceptione){e.printStackTrace();}returnnull;}}任務(wù)12-6本地事務(wù)運(yùn)行結(jié)果如圖12-15所示。12.4事務(wù)從運(yùn)行結(jié)果可以看出,事務(wù)是正常執(zhí)行完成的。為了模擬出錯(cuò)的情況,在轉(zhuǎn)賬步驟還未提交前手動(dòng)拋出一個(gè)錯(cuò)誤,并查看運(yùn)行結(jié)果,如下所示://轉(zhuǎn)賬事務(wù)模型publicvoidtransferDemo(){//假設(shè)張三向李四轉(zhuǎn)賬500元,只有在張三賬戶減少500元,//并且李四賬戶增加500元時(shí)轉(zhuǎn)賬成功。更新語(yǔ)句如下:StringsqlZS="updateaccountaseta.balance=a.balance-500wherea.account='6225001013452310'";StringsqlLS="updateaccountbsetb.balance=b.balance+500whereb.account='6225001013455700'";//執(zhí)行轉(zhuǎn)賬操作try{System.out.println("進(jìn)入轉(zhuǎn)賬流程:");st.execute(sqlZS);//手動(dòng)拋出一個(gè)異常Stringstr=null;str=str.substring(str.indexOf("_"));st.execute(sqlLS);mit();//轉(zhuǎn)賬成功,則提交事務(wù)System.out.println("轉(zhuǎn)賬成功!");}任務(wù)12-6本地事務(wù)catch(SQLExceptione){try{//一旦產(chǎn)生異常,則回滾數(shù)據(jù)庫(kù)conn.rollback();}catch(SQLExceptione1){e1.printStackTrace();}e.printStackTrace();}catch(Exceptione1){e1.printStackTrace();}}為了驗(yàn)證事務(wù)的有效性,在轉(zhuǎn)賬方法中手動(dòng)拋出一個(gè)空指針異常,程序的運(yùn)行結(jié)果如圖12-16所示。目錄導(dǎo)航12.1

JDBC12.3測(cè)試12.2日志12.4事務(wù)12.5簡(jiǎn)易網(wǎng)上銀行系統(tǒng)12.6單元小結(jié)12.5.1基礎(chǔ)項(xiàng)目搭建Tomcat最初是由Sun公司的軟件架構(gòu)師詹姆斯·鄧肯·戴維森開(kāi)發(fā)的,后來(lái)他將其變?yōu)殚_(kāi)源項(xiàng)目,并由Sun公司貢獻(xiàn)給Apache軟件基金會(huì)。它是一個(gè)免費(fèi)的、開(kāi)源的Web應(yīng)用服務(wù)器,屬于輕量級(jí)應(yīng)用服務(wù)器,在中小型系統(tǒng)和并發(fā)訪問(wèn)用戶不是很多的場(chǎng)合下被普遍使用,是開(kāi)發(fā)和調(diào)試JSP程序的首選。Tomcat是免安裝的,只需要在Tomcat官網(wǎng)下載對(duì)應(yīng)的ZIP包,解壓到本地目錄并添加到Eclipse中即可。讀者可以在Tomcat官網(wǎng)下載最新版本的TomcatZIP包,下載后解壓到固定目錄下;打開(kāi)Eclipse開(kāi)發(fā)工具,選擇工具欄上的“Window”→“Preferences”,如圖12-17所示。TomcatWeb服務(wù)器01OPTION12.5.1基礎(chǔ)項(xiàng)目搭建在彈出

的“Preferences”窗口中

,首

先找到“Server”,

然后

選擇其

下的“RuntimeEnvironment”選項(xiàng)并單擊;彈出服務(wù)器配置對(duì)話框,選擇“ApacheTomcatv8.5”,如圖所示。單擊“Next”按鈕,會(huì)彈出具體的服務(wù)器配置對(duì)話框,如圖12-19所示。首先單擊“Browse”按鈕,打開(kāi)“選擇文件夾”對(duì)話框;在路徑中搜索選擇Tomcat解壓路徑并確認(rèn)選擇,最后單擊“Finish”按鈕,完成Tomcat的配置工作。12.5.1基礎(chǔ)項(xiàng)目搭建完成配置之后,在Eclipse工具的“Servers”選項(xiàng)卡中添加服務(wù)器,如圖12-20所示。在彈出的對(duì)話框中選擇配置好的服務(wù)器,最后單擊“Finish”按鈕完成添加。完成添加之后,就可以看到“Servers”選項(xiàng)卡中有了一個(gè)Tomcat服務(wù)器的標(biāo)識(shí),如圖12-21所示。12.5.1基礎(chǔ)項(xiàng)目搭建至此,Tomcat的準(zhǔn)備工作就完成了。需要注意Tomcat一些的配置,例如監(jiān)聽(tīng)端口號(hào)等,因?yàn)門omcat默認(rèn)使用8080端口,而這個(gè)端口可能會(huì)被Oracle數(shù)據(jù)服務(wù)器占用。所以,如果讀者使用的是Oracle數(shù)據(jù)庫(kù),可以將Tomcat的端口修改成8081。具體修改在“Package”下的“Servers”中進(jìn)行,其修改方式如圖12-22所示。配置完成后,單擊“啟動(dòng)”按鈕,啟動(dòng)Tomcat服務(wù)器。無(wú)報(bào)錯(cuò)啟動(dòng)完成后,在瀏覽器地址欄中輸入http://localhost:8080并按【Enter】鍵訪問(wèn)Tomcat服務(wù)器,顯示頁(yè)面如圖12-23所示,表示服務(wù)器已經(jīng)正確配置。12.5.1基礎(chǔ)項(xiàng)目搭建Maven項(xiàng)目對(duì)象模型(ProjectObjectModel,POM)可以通過(guò)一小段描述信息來(lái)管理項(xiàng)目的構(gòu)建,是管理報(bào)告和文檔的軟件項(xiàng)目管理工具。Maven會(huì)自動(dòng)管理JAR包,只需要知道JAR包的位置即可。如需要相應(yīng)的JAR包信息,可以在MVNREPOSITORY網(wǎng)站中查找對(duì)應(yīng)的JAR包,其使用方式如圖12-24和圖12-25所示。Maven02OPTION12.5.1基礎(chǔ)項(xiàng)目搭建Maven項(xiàng)目對(duì)象模型(ProjectObjectModel,POM)可以通過(guò)一小段描述信息來(lái)管理項(xiàng)目的構(gòu)建,是管理報(bào)告和文檔的軟件項(xiàng)目管理工具。Maven會(huì)自動(dòng)管理JAR包,只需要知道JAR包的位置即可。如需要相應(yīng)的JAR包信息,可以在MVNREPOSITORY網(wǎng)站中查找對(duì)應(yīng)的JAR包,其使用方式如圖12-24和圖12-25所示。Maven02OPTION12.5.1基礎(chǔ)項(xiàng)目搭建12.5.1基礎(chǔ)項(xiàng)目搭建先創(chuàng)建一個(gè)Maven的Webapp項(xiàng)目,其步驟如圖12-26~圖12-29所示。完成配置之后,項(xiàng)目的框架如圖12-30所示。12.5.1基礎(chǔ)項(xiàng)目搭建創(chuàng)建完成之后,進(jìn)行相應(yīng)的配置即可使用該項(xiàng)目進(jìn)行開(kāi)發(fā)。配置pom.xml,完成項(xiàng)目的JAR包導(dǎo)入,其配置如下:<projectxmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.lw</groupId><artifactId>simplebank</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>simplebankMavenWebapp</name><url></url>

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format><spring.version>4.3.9.RELEASE</spring.version><mybatis.version>3.1.1</mybatis.version><mybatisspring.version>1.1.1</mybatisspring.version></properties>12.5.1基礎(chǔ)項(xiàng)目搭建<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-Webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatisspring.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>6.0.6</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version></version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>3.0-alpha-1</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>jsptags</groupId><artifactId>pager-taglib</artifactId><version>2.0</version><scope>provided</scope></dependency>12.5.1基礎(chǔ)項(xiàng)目搭建<dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.10</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.10</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.1.41</version></dependency><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.9.13</version></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.5</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.7.4</version></dependency>12.5.1基礎(chǔ)項(xiàng)目搭建<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.7.4</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.7.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>1.3.2</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.2.1</version></dependency></dependencies><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>2.2</version><configuration><version>3.0</version><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin></plugins>12.5.1基礎(chǔ)項(xiàng)目搭建<resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources><finalName>simple-bank</finalName></build></project><mirror><id>alimaven</id><name>aliyunmaven</name><url>/nexus/content/groups/public/</url><mirrorOf>central</mirrorOf></mirror>這里,本地的Maven鏡像使用的是阿里巴巴提供的Maven倉(cāng)庫(kù),該項(xiàng)配置在Maven的settings.xml中添加即可,如下所示:12.5.1基礎(chǔ)項(xiàng)目搭建log4j.rootLogger=info,console,debug,app,error###console###log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target=System.outlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=%d%p[%C:%L]-%m%n###debug###log4j.appender.debu

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論