Java程序員面試分類模擬14_第1頁
Java程序員面試分類模擬14_第2頁
Java程序員面試分類模擬14_第3頁
Java程序員面試分類模擬14_第4頁
Java程序員面試分類模擬14_第5頁
已閱讀5頁,還剩41頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Java程序員面試分類模擬14論述題1.

Struts1與Struts2有哪些區別正確答案:Strut1框架由AetionForm和JavaBean組成,其中AetionForm用于封裝用戶(江南博哥)的請求參數,封裝成ActionForm對象,該對象被ActionServlet轉發給Action,Action根據ActionFrom里面的請求參數處理用戶的請求。Struts2框架的基礎是核心控制器FilterDispatcher,它包含了框架內部的控制流程和處理機制。業務控制器Action和業務邏輯組件是需要用戶自己來實現的。開發人員在開發Action和業務邏輯組件的同時,還需要編寫相關的配置文件,以供核心控制器FiherDispatcher來使用。

Struts1與Struts2都是MVC的Web框架,盡管二者都叫Struts,但也存在著很多不一致的地方。具體而言,主要表現在以下方面:

1)風險控制方面。Struts1是老牌框架,應用廣泛,有很好的群眾基礎,開發風險很小,成本更低。Struts2雖然基于Struct1,但是相對不成熟,而且未知的風險和變化很多,受眾并不多。所以,使用Struts2開發項目的風險更大,成本更高。

2)Action實現類方面。Struts1要求Action類繼承一個抽象基類,而Struts2中Action類既可以實現一個Action接口,也可以實現其他接口,使可選和定制的服務成為可能。同時,Struts2提供了一個ActionSupport基類去實現常用的接口。

3)線程模式方面。Struts1Action是單例模式并且必須是線程安全的,因為僅有Action的一個實例來處理所有請求。而Struts2Action對象為每一個請求產生一個實例,因此不存在線程安全的問題。

4)Servlet依賴方面。Struts1Action依賴于ServletAPI,因為Struts1Action的execute()方法中有HttpServletRequest和HttpServletResponse方法。Struts2Action不再依賴于ServletAPI,因為Struts2的Action是由POJO(PlainOldJavaObjects,簡單的Java對象)組成,在Struts2中,Servlet上下文以簡單Map的形式表現出來,這使得Action可以進行獨立的測試,當然,如果Action需要直接訪問HttpServletRequest和HttpServletResponse參數,Struts2Action仍然可以訪問它們。但是,大部分時候,Action都無需直接訪問HttpServetRequest和HttpServletResponse,從而給了開發人員更多選擇。

5)可測性方面。測試Struts1Action的一個主要問題是execute()方法依賴于ServletAPI,這使得Action的測試要依賴于Web容器。為了脫離Web容器測試Struts1的Action,必須借助于第三方擴展:StrutsTestCase,該擴展包包含了系列的Mock對象(模擬了HttpservetRequest和HttpServletResponse對象),從而可以脫離Web容器測試Struts1的Action類。Struts2Action可以通過初始化、設置屬性、調用方法來測試。

6)封裝請求參數。Struts1使用ActionForm對象封裝用戶的請求參數,所有AetionForm必須繼承一個基類——ActionForm。普通的JavaBean不能用作ActionForm,因此,開發人員必須創建大量的ActionForm類封裝用戶請求參數。雖然Struts1提供了動態ActionForm來簡化ActionForm的開發,但依然需要在配置文件中定義ActionForm。而Struts2直接使用Action屬性來封裝用戶請求屬性,避免了開發人員需要大量開發ActionForm類的煩瑣。實際上,這些屬性還可以是包含子屬性的Rich對象類型。如果開發人員依然“懷念”Struts1ActionForm的模式,Struts2提供了ModelDriven模式,可以讓開發人員使用單獨的Model對象來封裝用戶請求參數。但該Model對象無需繼承任何Struts2基類,是一個POJO,從而降低了代碼污染。

7)表達式語言方面。Struts1整合了JSP標準標簽庫(JSPStandardTagLibrary,JSTL),因此可以使用JSTL表達式語言。Struts2可以使用JSTL,但它整合了一種更強大和靈活的表達式語言——對象圖的符號語言(ObjectGraphNotationLanguage,OGNL),因此,Struts2下的表達式語言功能更加強大。

8)綁定值到視圖。Struts1使用標準JSP機制把對象綁定到視圖頁面,而Struts2使用“ValueStack”技術,使標簽庫能夠訪問值,而不需要把對象和視圖頁面綁定在一起。

9)類型轉換。Struts1ActionForm屬性通常都是String類型。Struts1使用Commons-Beanutils進行類型轉換,每個類一個轉換器,轉換器是不可配置的;Struts2使用OGNL進行類型轉換,支持基本數據類型和常用對象之間的轉換。

10)數據校驗。Struts1與Strut2都支持通過validate()方法的手動驗證,不同的是,Struts1支持在ActionForm重寫validate()方法中手動校驗,或者通過整合Commonsalidator框架來完成數據校驗,而Struts2支持通過重寫validate()方法進行校驗,也支持整合XWork校驗框架進行校驗。

11)Action執行控制。Struts1支持每一個模塊對應一個請求處理(即生命周期的概念),但是模塊中的所有Action必須共享相同的生命周期。Struts2支持通過攔截器堆棧(InterceptorStacks)為每一個Action創建不同的生命周期。開發人員可以根據需要創建相應堆棧,以便和不同的Action一起使用。

12)捕獲輸入。Struts1使用ActionForm對象捕獲輸入,所有ActionForm必須繼承自一個框架依賴的基類。因為其他JavaBean不能用作ActionForm,開發人員經常創建多余的類捕獲輸入。而Struts2直接使用Action屬性作為輸入屬性,消除了對第二個輸入對象的需求。

2.

什么是IoC正確答案:控制反轉(InverseofControl,IoC)有時也被稱為依賴注入,是一種降低對象之間耦合關系的設計思想。一般而言,在分層體系結構中,都是上層調用下層的接口,上層依賴于下層的執行,即調用者依賴于被調用者。而通過IoC方式,使得上層不再依賴于下層的接口,即通過采用一定的機制來選擇不同的下層實現,完成控制反轉,使得由調用者來決定被調用者。IoC通過注入一個實例化的對象來達到解耦和的目的。使用這種方法后,對象不會被顯式地調用,而是根據需求通過IoC容器(例如Spring)來提供。

采用IoC機制能夠提高系統的可擴展性,如果對象之間通過顯式調用進行交互會導致調用者與被調用者存在著非常緊密的聯系,其中一方的改動將會導致程序出現很大的改動,例如,要為一家賣茶的商店提供一套管理系統,在這家商店剛開業時只賣綠茶(GreenTea),隨著規模的擴大或者根據具體銷售量,未來可能會隨時改變茶的類型,例如紅茶(BlackTea)等,傳統的實現方法會針對茶抽象化一個基類,綠茶類只需要繼承自該基類即可,如圖所示。

賣茶系統類圖(一)

采用該實現方法后,在需要使用GreenTea時只需要執行以下代碼即可:AhstractTeat=newGreenTea(),當然,這種方法是可以滿足當前設計要求的。但是該方法的可擴展性不好,存在著不恰當的地方,例如,商家發現綠茶的銷售并不好,決定開始銷售紅茶(BlackTea)時,那么只需要實現一個BlackTea類,并且讓這個類繼承自AhstractTea即可。但是,系統中所有用到AbstractTeat=newGreenTea()的地方都需要被改為AbstractTeat=newBlackTea(),而這種創建對象實例的方法往往會導致程序的改動量非常大。

那么怎樣才能增強系統的可擴展性呢?——設計模式,此時可以使用設計模式中的工廠模式來把創建對象的行為包裝起來,實現方法如圖所示。

賣茶系統類圖(二)

通過以上方法,可以把創建對象的過程委托給TeaFatory來完成,在需要使用Tea對象時只需要調用Factory類的getTea方法即可,具體創建對象的邏輯在TeaFactory中來實現,那么當商家需要把綠茶替換為紅茶時,系統中只需要改動TeaFaetory中創建對象的邏輯即可,采用了工廠模式后,只需要在一個地方做改動就可以滿足要求,這樣就增強了系統的可擴展性。

雖然說采用工廠設計模式后增強了系統的可擴展性,但是從本質上來講,工廠模式只不過是把程序中會變動的邏輯移動到工廠類里面了,當系統中的類較多時,在系統擴展時需要經常改動工廠類中的代碼。而采用IoC設計思想后,程序將會有更好的可擴展性,下面主要介紹Spring框架在采用IoC后的實現方法,如圖所示。

賣茶系統類圖(三)

Spring容器將會根據配置文件來創建調用者對象(Sale),同時把被調用的對象(AbstractTea的子類)的實例化對象通過構造函數或set()方法的形式注入到調用者對象中。

首先,創建名為SpringConfig.xml的文件。

<beans>

<beanid="sale"class="Sale"singleton="false">

<constrctor-arg>

<refbean="tea"/>

</constrctor-arg>

</bean>

<beanid="tea"class="BlueTea"singleton="false">

</beans>

在實現Sale類時,需要按照如下方式實現。

classSale{

privateAhstractTeat;

publicSale(AbstractTeat){

this.t=t;

}

//其他方法就可以使用t了

當Spring容器創建Sale對象時,根據配置文件SpringConfig.xml就會創建一個BlueTea的對象,作為Sale構造函數的參數。當需要把BlueTea改為BlackTea時,只需要修改上述配置文件,而不需要修改代碼。

在需要Sale時,可以通過如下方式來創建Sale對象:

ApplicationContextxtx=newFileSystemXmlApplicationContext("SpringConfig.xml");

Sales=(Sale)ctx.getBean("sale");

上例中,Spring采用IoC的方式來實現把實例化的對象注入到開發人員自定義的對象中,具有較強的可擴展性。

具體而言,IoC主要有以下兩個方面的優點:

1)通過IoC容器,開發人員不需要關注對象如何被創建的,同時增加新類也非常方便,只需要修改配置文件即可實現對象的“熱插拔”。

2)IoC容器可以通過配置文件來確定需要注入的實例化對象,因此非常便于進行單元測試。

盡管如此,IoC也有自身的缺點,具體表現為以下兩點:

1)對象是通過反射機制實例化出來的,因此會對系統的性能有一定的影響。

2)創建對象的流程變得比較復雜。

3.

什么是AOP正確答案:面向切面編程(Aspect-OrientedProgramming,AOP)是對面向對象開發的一種補充,它允許開發人員在不改變原來模型的基礎上動態地修改模型以滿足新的需求,例如,開發人員可以在不改變原來業務邏輯模型的基礎上可以動態地增加日志、安全或異常處理的功能。

下面介紹一個在Spring中使用AOP編程的簡單例子。

1)創建一個接口以及實現這個接口的類。TestAOPIn.java文件的內容如下所示。

publicinterfaceTestAOPIn{

publicvoiddoSomething();

}

TestAOPImpl.java文件的內容如下所示。

publicclassTestAOPImplimplementsTestAOPIn{

publicvoiddoSomething(){

System.out.println("TestAOPImpl:doSomething");

}

}

2)配置SpringConfig.xml,使得這個類的實例化對象可以被注入到使用這個對象的Test類中。

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""/dtd/

spring-beans.dtd">

<beans>

<beanid="testAOPBean"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="target">

<beanclass="testAOPIn"singleton="false"/>

</property>

</bean>

</beans>

3)在完成配置文件后,編寫如下測試代碼。

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.FileSystemXmlApplicationContext;

publicclassTest{

publicstaticvoidmain(String[]args){

ApplicationContextetx=newFileSystemXmlApplicationContext("SpringConfig.xml");

TestAOPInt=(TestAOPIn)ctx.getBean("testAOPBean");

t.doSomething();

}

}

程序運行結果為:

TestAOPImpl:doSomething

編寫完這個模塊后,開發人員需要增加對doSomething()方法調用的跟蹤,也就是說,要跟蹤該方法何時被調用以及調用何時結束等內容。當然,使用傳統的方法也可以實現該功能,但卻會產生額外的開銷,即需要修改已存在的模塊。此時可以采用AOP的方式來實現這個功能。它在不修改原有模塊的前提下可以完成相同的功能。

publicclassTestAOPImplimplementsTestAOPIn{

publicvoiddoSomething(){

System.out.println("beginCalldoSomething");

System.out.println("TestAOPImpl:doSomething");

System.out.println("endCalldoSomething");

}

}

其實現原理如圖所示。

AOP實現原理圖

為此需要提供用來跟蹤函數調用的類。traceBeforeCall.java文件的內容如下所示:

publicclasstraceBeforeCallimplementsMethodBeforeAdviee{

publicvoidbeforeCall(Methodarg0,Object[]arg1,Objectarg2)throwsThrowable{

System.out.println("beginCalldoSomething");

}

}

traceEndCall.java文件的內容如下所示:

importjava.lang.reflect.Method;

importorg.springframework.aop.AfterReturningAdvice;

publicclasstraceEndCallimplementsAflerRetumingAdvice{

publicvoidafterCall(Objectarg0,Methodarg1,Object[]arg2,Objectarg3)throwsThrowable{

System.out.println("endCalldoSomething");

}

}

只需在配置文件中配置在調用doSomething()方法之前需要調用traceBeforeCall類的beforeCall()方法以及在調用doSomething()方法之后需要調用traceEndCall類的afterCall()方法,Spring容器就會根據配置文件在調用doSomething()方法前后自動調用相應的方法,通過在beforeCall()方法和afterCall()方法中添加跟蹤的代碼就可以滿足對doSomething()方法調用的跟蹤要求,同時還不需要更改原來已實現的代碼模塊。

4.

什么是Spring框架正確答案:Spring是一個J2EE的框架,這個框架提供了對輕量級IoC的良好支持,同時也提供了對AOP技術非常好的封裝。相比其他框架,Spring框架的設計更加模塊化,框架內的每個模塊都能完成特定的工作,而且各個模塊可以獨立地運行,不會相互牽制。因此,在使用Spring框架時,開發人員可以使用整個框架,也可以只使用框架內的一部分模塊,例如可以只使用SpringAOP模塊來實現日志管理功能,而不需要使用其他模塊。

Spring框架主要由7個模塊組成,它們分別是SpringAOP、SpringORM、SpringDAO、SpringWeb、SpringContext、SpringWebMVC、SpringCore等。Spring框架圖如圖所示。

Spring框架圖

下表詳細介紹了各個模塊的作用。Spring框架的7個模塊的作用模塊描述SpringAOP采用了面向切面編程的思想,使Spring框架管理的對象支持AOP,同時這個模塊也提供了事務管理,可以不依賴具體的EJB組件,就可以將事務管理集成到應用程序中SpringORM提供了對現有ORM框架的支持,例如Hibernate、JDO等SpringDAO提供了對數據訪問對象(DataAccessObject,DAO)模式和JDBC的支持。DAO可以實現把業務邏輯與數據庫訪問的代碼實現分離,從而降低代碼的耦合度。通過對JDBC的抽象,簡化了開發工作,同時簡化了對異常的處理(可以很好地處理不同數據庫廠商拋出的異常)SpringWeb提供了Servlet監聽器的Context和Web應用的上下文。同時還集成了一些現有的Web框架,例如StructsSpringContext擴展核心容器,提供了Spring上下文環境,給開發人員提供了很多非常有用的服務,例如國際化、E-mail和JNDI訪問等SpringWebMVC提供了一個構建Web應用程序的MVC的實現SpringCoreSpring框架的核心容器,它提供了Spring框架的基本功能。這個模塊中最主要的一個組件為BeanFactory,它使用工廠模式來創建所需的對象。同時BeanFactory使用IOC思想,通過讀取XML文件的方式來實例化對象,可以說BeanFactory提供了組件生命周期的管理,組件的創建、裝配、銷毀等功能

Spring在J2EE中到底扮演著怎樣的角色?在哪些地方可以使用Spring?

Spring的工作原理如圖所示,可以看出,Spring有著非常廣泛的用途,不僅可以在Web容器中用來管理Web服務器端的模塊,例如Servlet,還可以用來管理用于訪問數據庫的Hibernate。由于Spring在管理BusinessObject(業務對象)和DAO時使用了IoC和AOP的思想,因此這些被Spring管理的對象都可以脫離EJB容器單獨運行和測試。在需要被Spring容器管理時,只需要增加配置文件,Spring框架就會根據配置文件與相應的機制實現對這些對象的管理。

Spring的工作原理

除此之外,使用Spring還有如下好處:

1)在使用J2EE開發多層應用程序時,Spring有效地管理了中間層的代碼,由于Spring采用了控制反轉和面向切面編程的思想,因此這些代碼非常容易進行單獨測試。

2)使用Spring有助于開發人員培養一個良好的編程習慣:面向接口編程而不是面向類編程。面向接口編程使得程序有更好的可擴展性。

3)Spring對數據的存取提供了一個一致的框架(不論是使用JDBC還是O/R映射的框架,例如Hibernate或JDO)。

4)Spring通過支持不同的事務處理API(如JTA、JDBC、Hibernate等)的方法對事務的管理提供了一致的抽象方法。

5)使用Spring框架編寫的大部分業務對象不需要依賴Spring。

5.

什么是Hibernate正確答案:Hibernate是一個開放源代碼的對象關系映射(ObjectRelationMapping,ORM,一種用來完成對象模型到關系模型的映射技術)框架,它不僅可以運行在J2EE容器中,也可以在J2EE容器外運行。它對JDBC進行了非常輕量級的對象封裝,所以任何可以使用JDBC的地方都可以用Hibernate來替代。Hibernate實現了Java對象與關系數據庫記錄的映射關系,簡化了開發人員訪問數據庫的流程,極大地提高了軟件的開發效率。

Hibernate主要提供了5個核心接口,分別為Session、SessionFactory、Transaction、Query和Configuration。通過使用這些接口不僅可以完成對數據庫的訪問(例如查詢、插入、更新與刪除等),而且還可以實現對事務的控制。Hibernate的結構圖如圖所示。

Hibernate結構圖

下表詳細介紹了各個模塊的作用。Hibernate模塊介紹接口名描述Session一個輕量級的非線程安全的對象,主要負責被持久化對象與數據庫的操作。可以使用SessionFaetory來創建一個Session,當對數據庫的所有操作都執行完成后,就可以關閉Session。Session在訪問數據庫時會建立與數據庫的連接,這個連接只有在需要時才會被建立SessionFactory負責初始化Hibernate。它可以被看作數據源的代理,可以用來創建Session對象。此外,SessionFactory是線程安全的,因此可以被多個線程同時訪問。一般而言,SessionFactory會在Hibernate啟動時創建一次,因此,為了便于使用,SessionFactory應該用一個單例模式來實現Transaction負責事務相關的操作。它的主要方法有commit()和rollback(),其中commit()方法負責事務的提交,rollback()方法負責事務的回滾,可以通過Session的beginTrancation()方法來創建Query負責執行各種數據庫查詢。可以使用Hibernate查詢語言(HibernateQueryLanguage,HQL)或SQL語句兩種方式進行查詢(這兩種查詢方式非常類似,與SQL不同的是,HQL語言使用類和屬性而不是表與列名進行查詢)。可以通過Session的createQuery()方法來創建Query。此外,Hibernate還提供了另外一種查詢方式QBC(QueryByCriteria),其使用方法為:先使用Session實例的createCriteria()方法創建Criteria對象,接著使用工具類Restrictions的方法為Criteria對象設置查詢條件,同時還可以用Order工具類的方法沒置排序方式,最后用Projections工具類的方法進行統計和分組,使用Criteria對象的list()方法進行查詢并返回結果。需要注意的是,QBC是一種類型安全的面向對象的查詢方式Configuration用于讀取Hibernate配置文件,并生成SessionFaetory對象。其中配置文件主要有兩類:一類是hiber-nate.cfg.xml或perties;另一類是映射文件,例如***.hbm.xml。其中hibernate.cfg.xml或perties用來配置Hibernate服務的信息(例如連接數據庫使用的驅動類、數據庫連接的URL、數據庫的用戶名和密碼等信息)。如果同時提供了hibernate.cfg.xml和perties文件,那么hibernate.cfg.xml會覆蓋perties中的配置信息。映射文件(*.hbm.xml)用來配置java對象與關系數據庫記錄的映射關系。為了便于管理與維護,通常會給每個對象創建一個單獨的映射文件

Hibernate的使用過程如下:

1)應用程序通過Configuration類讀取配置文件并創建SessionFactory對象。

SessionFaetorysessionFaetory=newConfiguration().configure().buildSessionfactory();

2)通過SessionFactory生成一個Session對象。

Sessionsession=sessionFactory.openSession();

3)通過Session對象的beginTrancation()方法創建一個事務。

Transactiont=session.beginTransaction();接著可以通過Session對象的get()、load()、save()、update()、delete()和saveOrUpdate()等方法實現數據的加載、保存、更新和刪除等操作;也可以通過session生成一個Query對象,然后利用Query對象執行查詢操作;最后通過commit()方法或rollback()方法完成事務操作。

4)在完成所有持久化操作與事務操作后需要關閉Session與SessionFactory。

下面以訪問MySQL為例給出一個使用Hibernate的示例。

1)創建一個表。

createtableEmployee(

idintprimarykey,

nanlevarchar(20),

ageint

);

2)在Eclipse中創建一個工程,接著導入相關的類庫,例如Hibernate需要用到的類(hibernate3.jar),訪問數據庫的驅動包(mysql-connector-java-5.0.8-bin.jar)和操作XML文件用到的jar包等。接著創建一個持久化類。

publicclassEmployee{

privateIntegerid;

privateStringname;

privateIntegerage;

publicEmployee(){}

publicEmployee(Integerid,Stringname,Integerage){

this,id=id;

=name;

this.age=age;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

=name;

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

publicIntegergetId(){

returnid;

}

publicvoidsetId(Integerid){

this.id=id;

}

}

3)創建一個目錄hibernate,在這個目錄下創建兩個配置文件:hibernate.cfg.xml與employee.hdm.xml。其中,hibernate.cfg.xml文件的內容如下所示:

<?xmlversion='1.0'encoding='UTF-8'?>

<!DOCTYPEhibernate-configurationPUBLIC

"-//Hibernate/HibernateConfigurationDTD3.0//EN"

"/hibernate-configuration-3.0.dtd">

<!--GeneratedbyMyEclipseHibernateTools.-->

<hibernate-configuration>

<session-factory>

<propertyname="connection.username">user1</property>

<propertyname="connection.url">

jdbc:mysql://loealhost:3306/Test

</property>

<propertyname="dialect">

org.hibernate.dialect.MySQLDialect

</property>

<propertyname="file">MySQL5.1</property>

<propertyname="connection.password">pwd1</property>

<propertyname="connection.driver_class">

com.mysql.jdbc.Driver

</property>

<propertyname="show_sql">true</property>

<mappingresource="hibernate/employee.hdm.xml"/>

</session-factory>

</hibernate-configuration>

配置文件employee.hdm.xml中存放了訪問數據庫的基本信息,具體內容如下所示:

<?xmlversion="1.0"encoding="utf-8"?>

<!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"

"/hibernate-mapping-3.0.dtd">

<!--

MappingfileautogeneratedbyMyEclipse-HibernateTools

-->

<hibernate-mapping>

<classname="Employee"table="Employee">

<idname="id"type="java.lang.Integer">

<columnname="id"/>

<!--Hibernate可以實現自增-->

<generatorclass="increment"/>

</id>

<propertyname="name"type="java.lang.String">

<columnname="name"length="20"/>

</property>

<propertyname="age"type="java.lang.Integer">

<columnname="age"/>

</property>

</class>

</hibernate-mapping>

以上文件中存放了Java類與數據庫表的對應關系。

4)編寫訪問數據庫的代碼。

importjava.sql.SQLException;

importjava.util.List;

importorg.hibernate.Query;

importorg.hibernate.Session;

importorg.hibernate.SessionFactory;

importorg.hibernate.Transaction;

importorg.hibernate.cfg.Configuration;

publicclassTest{

publicstaticvoidmain(String[]args)throwsClassNotFoundException,SQLException{

Configurationconfig=newConfiguration().configure("/hibernate/hibernate.cfg.xml");

SessionFactorysessionFaetory=config.buildSessionFaetory();

Sessions=sessionFaetory.openSession();

Transactiontx=s.beginTransacfinn();

Employeee=HewEmployee();

e.setName("James");

e.setAge(25);

try{

s.save(e);

//保存持久類對象

mit();

//提交到數據庫

//從數據庫中查找剛才保存的數據

Queryq=s.createSQLQuery("select*fromEmployee").addEntity(Employee.class);

List<Employee>rs=q.list();

for(inti=0;i<rs.size();i++){

Employeee1=rs.get(i);

System.out.println("id:"+e1.getId()+"name:"+e1.getName()+"age:"+

e1.getAge());

}

s.close();

}

catch(Exceptione1)

e1.printStackTraee();

tx.rollback();

}

}

}

程序運行結果為:

Hibernate:selectmax(id)fromEmployee

Hibernate:insertintoEmployee(name,age,id)values(?,?,?)

Hibernate:select*fromEmployee

id:1name:Jamesage:25

需要注意的是,輸出結果的前三行是由Hibernate框架打印出的信息,最后一行數據為從數據庫中查找出的數據。

具體而言,使用Hibernate框架有諸多好處,主要表現為以下幾個方面。

1)提高開發效率。

2)使得開發可以完全采用面向對象的思想,不需要關心數據庫的關系模型。

3)使用Hibernate開發的系統有很好的可移植性,可以很容易地實現不同數據庫之間的移植而不需要關系不同數據庫SQL語句的差異。

4)支持透明持久化,Hibernate的API沒有侵入性,當保存一個對象時,這個對象不需要繼承Hibernate中的任何類和實現任何接口。

雖然如此,但Hibernate只適用于針對單一對象簡單的增、刪、查、改,而對于批量的修改/刪除的場合,則不適用,這也是OR框架的弱點,所以,當要使用數據庫的特定優化機制時,不適合使用Hibernate。

引申:

1.在使用Hibernate時如何提高性能?

使用Hibernate時,有多種方法可以用來提高性能,具體內容如下所示。

1)延遲加載。當Hibernate從數據庫獲取某一個對象數據、獲取某一個對象的集合屬性值時或者獲取某一個對象所關聯的另一個對象時,并不會立即從數據庫中把數據加載到對象中,而是通過建立一個代理對象,把這個對象的屬性都設置為默認值,只有當這些數據在被使用時才會從數據庫中去加載對應的數據,使用這種方法有助于提高Hibernate的性能。

2)緩存技術。Hibernate中提供了一級緩存與二級緩存,合理的利用緩存也有助于提高系統的性能,為了避免不合理的利用緩存導致內存的過度消耗降低系統的性能,可以通過合理配置緩存的參數(例如配置緩存可以加載數據的個數)來避免這個問題。

3)優化查詢語句。通過優化查詢語句來提高系統的性能。

2.Hibernate中怎樣實現類之間的關系?(例如一對多、多對多關系)

類之間的關系主要體現在表之間的關系,它們都是對對象進行操作,程序中把所有表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-to-man),來進行配置。

6.

什么是Hibernate的二級緩存正確答案:緩存的目的是為了通過減少應用程序對物理數據源訪問的次數來提高程序運行的效率,原理則是把當前或接下來一段時間可能會用到的數據保存到內存中,在使用時直接從內存中讀取,而不是從硬盤中去讀取,簡單來說,緩存就是數據庫中數據在內存中的“臨時容器”。

在Hibernate中,緩存用來把從數據庫中查詢出來的和使用過的對象保存在內存中,以便在后期需要用到這個對象時可以直接從緩存中來獲取這個對象(只有當該對象在緩存中不存在時才會去數據庫中查詢)。顯然,由于避免了因大量發送SQL語句到數據庫查詢導致的性能損耗,緩存機制可以顯著提高程序的運行效率。

在Hibernate中有一級緩存與二級緩存的概念,一級緩存由Session來管理,二級緩存由SessionFactory來管理。在使用時,二級緩存是可有可無的,但一級緩存是必不可少的。

一級緩存使用的場合如下:當使用Session查詢數據時,首先會在該Session內部查找該對象是否存在,若存在,則直接返回,否則,就到數據庫中去查詢,并將查詢的結果緩存起來以便后期使用。一級緩存的缺點就是當使用Session來表示一次會話時,它的生命周期較短,而且它是線程不安全的,不能被多個線程共享,因此,在實際使用時,對效率的提升不是非常明顯。

鑒于以上原因,二級緩存的概念被引入了。二級緩存用來為Hibernate配置一種全局的緩存,以便實現多個線程與事務共享。在使用了二級緩存機制后,當查詢數據時,會首先在內部緩存巾去查找,如果不存在,接著在二級緩存中查找,最后才去數據庫中查找。與一級緩存相比,二級緩存是獨立于Hibernte的軟件部件,屬于第三方的產品,常見的產品有。EhCache、OSCache和JbossCache等,Hibernate3以后默認使用的產品為EhCache。在使用時,可以根據需求通過配置二級緩存插件來實現二級緩存功能,Hibernate為了集成這些插件,提供了org.hibernate.cache.CacheProvider接口來充當緩存插件與Hibernate之間的適配器。當然,二級緩存除了以內存作為存儲介質外,還可以選用硬盤等外部存儲設備。

合理地使用Hibernate的二級緩存機制有助于提高系統的運行效率,但如果使用得不合理,不僅不會提高效率,反而有可能會降低系統的性能。

二級緩存一般適用于以下幾種情況:

1)數據量較小。如果數據量太大,緩存太多,會消耗大量內存,造成內存資源短缺,從而降低系統的性能。

2)對數據的修改較少。如果進行大量的修改,就需要頻繁地對緩存中數據與數據庫中的數據進行同步,而這也會影響系統的性能。

3)不會被大量的應用共享的數據。如果數據被大量線程或事務共享,多線程訪問時的同步機制也會影響系統的性能。

4)不是很重要的數據。如果查詢的數據非常重要(例如財務數據),對數據的正確性要求非常高,最好不要使用二級緩存。

7.

Hibernate中session的update()和saveOrUpdate()、load()和get()有什么區別正確答案:Hibernate的對象有3種狀態,分別為:瞬時態(Transient)、持久態(Persistent)和脫管態(Detached)。處于持久態的對象也被稱為PO(PersistenceObject),瞬時對象和脫管對象也被稱為VO(ValueObject)。

saveOrUpdate()方法同時包含了save()和update()方法的功能。Hibernate會根據對象的狀態來確定是調用save()方法還是調用update()方法:若對象是持久化對象,則不進行任何操作,直接返回;若傳入的對象與session中的另一個對象有相同的標識符,則拋出一個異常;若對象的標識符屬性(用來唯一確定一個對象)在數據庫中不存在或者是一個臨時值,則調用save()方法把它保存到數據庫中,否則,調用update()方法更新對象的值到數據庫中。鑒于此,在使用時,若能確定對象的狀態,則最好不要調用saveOrUpdate()方法,這樣有助于提高效率,例如,如果能夠確定這個對象所對應的值在數據庫中肯定不存在,那么就可以直接調用save()方法。

get()方法與load()方法都是用來通過從數據庫中加載所需的數據來創建一個持久化的對象,它們主要有以下幾個不同點:

1)如果數據庫中不存在該對象,load()方法會拋出一個ObjectNotFoundException異常,而get()方法則會返回null。

2)get()方法首先查詢Session內部緩存,若不存在,則接著查詢二級緩存,最后查詢數據庫;而load()方法在創建時會首先查詢Session內部緩存,如果不存在,就創建代理對象,實際使用數據時才查詢二級緩存和數據庫,因此load()方法支持延遲加載(對象中的屬性在使用時才會加載,而不是在創建對象時就加載所有屬性)。

3)get()方法永遠只返回實體類,而load()方法可以返回實體類的代理類實例。

4)get()方法和find()方法都是直接從數據庫中檢索,而load()方法的執行則比較復雜:首先查找Session的persistentContext中是否有緩存,若有,則直接返回;若沒有,則判斷是否是lazy。如果不是,直接訪問數據庫檢索,查到記錄返回,查不到拋出異常;若是lazy,則需要建立代理對象,對象的initialized屬性為false,target屬性為null。在訪問獲得的代理對象的屬性時檢索數據庫,若找到記錄,則把該記錄的對象復制到代理對象的target上,并將initialized置為true;若找不到,就拋出異常。

8.

Hibernate有哪些主鍵生成策略正確答案:Hibernate作為一種優秀的持久層框架,采用ORM方式,大大地簡化了對數據庫的操作。同時,Hibernate框架提供的主鍵生成策略,使開發人員可以通過在實體類的映射文件中設定關鍵字來告訴Hibernate要使用的主鍵生成方式,然后Hibernate會根據設定完成數據庫的主鍵控制。Hibernate中的主鍵生成策略主要有如下幾種:

1)Assigned。使用該方法時,主鍵不是由Hibernate生成的,而是由外部程序負責生成,所以無需Hibernate參與,但需要開發人員在調用save()方法之前來指定,否則調用save()方法會拋出異常。其缺點是在執行新增操作時需查詢數據庫判斷生成的主鍵是否已經存在,否則很容易產生主鍵沖突。

2)Hilo。該方法使用一個高/低位算法(High/LowAlgorithm)生成long、short或int類型的標識符。給定一個表和字段作為高位值的來源(默認的表是hibernate_unique_key,默認的字段是next_hi)。它將id的產生源分成兩部分:DB+內存,然后,按照算法結合在一起產生id值,從而可以在很少的連接次數內產生多條記錄,提高效率。

需要注意的是,該方法需要額外的數據庫表保存主鍵生成歷史狀態。Hilo能保證同一個數據庫中主鍵的唯一性,但不能保證多個數據庫之間主鍵的唯一性。

3)Seqhilo。與Hilo類似,Seqhilo是一種通過高/低位算法實現的主鍵生成機制,只是主鍵歷史狀態保存在Sequence中,適用于支持Sequence的數據庫,例如Oracle。

4)Increment。這種方式采用對主鍵自增的方式來生成新的主鍵。實現機制為:在當前應用實例中維持一個變量,以保存當前的最大值,之后每當需要生成主鍵時,便會將此值加1作為主鍵。該方式要求數據庫支持Sequence。

盡管該方式優點眾多,但問題也不少。首先,新增數據前需要先查詢一遍,這會影響系統的性能;其次,主鍵的類型只能是數值的int或long型;最后,會產生并發問題,即如果當前有多個實例訪問同一個數據庫,那么由于各個實例各自維護主鍵狀態,不同實例可能生成同樣的主鍵,從而造成主鍵重復異常。所以,該方法只適合單線程對數據庫的訪問方式,不適合在多進程并發更新數據庫的場合使用。因此,如果同一數據庫有多個實例訪問,最好不要使用這種方法。需要注意的是,該主鍵遞增的方式是由Hibernate來維護的。

5)Identity。這種方式采用數據庫提供的自增方式來生成新的主鍵,例如DB2、SQLServer、MySQL中的主鍵生成機制。該方式的特點是不需要Hibernate與開發人員的干涉,使用起來非常方便,但會給程序在不同數據庫的移植帶來嚴重不便。

6)Sequence。這種方式采用數據庫提供的Sequence(序列)機制生成主鍵。這就要求數據庫必須提供Sequence機制,例如Oracle就提供Sequence機制。其主要缺點是當程序在不同數據庫之間移植時,特別是從支持序列的數據庫移植到不支持序列的數據庫時,使用該方式會非常麻煩。

7)Native。在該方式中,由Hibernate根據底層數據庫自行選取Identity、Hilo、Sequence中的一種作為主鍵生成方式,例如,對于Oracle采用Sequence方式,對于MySQL和SQLServer采用Identity方式。該方式的一個主要優點就是靈活性更強,便于程序的移植。

8)UUID。uuid.hex由Hibernate基于128位唯一值產生算法生成16進制數值(編碼后以長度32位的字符串表示)作為主鍵。這種方式能夠保證在不同的環境下主鍵的一致性。

uuid.string與uuid.hex類似,只是生成的主鍵未進行編碼(長度16位)。在某些數據庫(例如PostgreSQL)中可能出現問題。

該方式能夠保證數據庫中的主鍵唯一性,但是在生成的主鍵占用比較多的存儲空間。

9)ForeignGUID。這種方式用于在一對一的關系中采用一種特殊的算法來生成主鍵,從而保證了主鍵的唯一性。

10)select。這種方式使用觸發器生成主鍵,主要用于早期的數據庫主鍵生成機制,現在使用得比較少。

9.

如何實現分頁機制正確答案:在交互式的應用程序中,當數據量很大時,如果一次性把所需數據全部從數據庫中查詢出來,不僅非常耗費時間,而且還會消耗大量的內存,導致用戶操作的延時,嚴重影響系統的可用性。因此,為了降低系統的響應時間,提高系統的性能,往往會使用分頁機制,即不是把用戶所需數據一次性全部查找出來,而是把數據分成很多的頁,每一頁只包含指定的記錄數,在查詢時根據需求每次只查找一頁或多頁的數據而不是所有數據。由于采用分頁機制使得查詢的結果集中數據量減少了,同時也降低了內存的消耗,因此可以顯著降低響應時間,有助于提高系統的可用性,增強用戶體驗。

下面主要介紹兩種分頁的實現方法。

(1)Hibernate自帶的分頁機制

Hibernate提供了一個支持跨系統的分頁機制,該機制保證無論底層是什么樣的數據庫都能使用統一的接口進行分頁操作。其用法如下:首先,通過Session對象獲取Query對象;其次,使用Query對象的setFirstResult()方法來設置要查詢的第一行數據;最后,用setMaxResults()方法來設置要查詢結果集的大小。

下列代碼的功能就是從第100條開始取出50條記錄:

Queryq=session_createQuery("fromStudentass");

q.setFirstResult(100);

q.setMaxResults(50);

Listl=q.list();

(2)用SQL語句來實現分頁

以MySQL為例,可以使用limit關鍵字來實現分頁。其用法如下:

select*fromtableNamewhere條件limitbegin,count

第一個參數(begin)代表查詢開始的地方,第二個參數(count)代表每頁顯示多少條數據。需要注意的是,第一頁用0表示,例如查詢語句select*fromemployeelimit0,2表示從表employee中第一行開始查找兩行數據。

10.

什么是SSH正確答案:SSH是Structs、Spring和Hibernate的首字母組合,它是一種比較流行的用來開發Web應用程序的開源框架,用于構建靈活、易于擴展的多層Web應用。

使用SSH框架開發的系統從職責上可以分為4層:表示層、業務邏輯層、數據持久化層和域模塊層,如圖所示。

SSH模塊圖

其中,Struts實現了MVC模式,它對Model、View和Controller的各個模塊都提供了支持。Struts框架使用JSP實現了視圖部分,模型部分則通過Hibernate框架提供的支持來實現數據的持久化,業務層則使用了Spring作為支持來管理對象。

接著,Spring把抽象出的模型用Java類來實現,同時為這些模型編寫對應的DAO接口,同時給出基于Hibernate的DAO的實現,即實現Java對象與關系數據庫之間數據的轉換。然后使用Spring來完成業務邏輯,來管理Hibernate與Struts對象。

采用SSH框架,不僅能實現視圖、控制器與模型的徹底分離,而且還能實現業務邏輯層與數據持久層的分離。無論前端如何變化,模型層只需很少的改動即可滿足要求;此外,數據庫的變化也不會對前端有所影響,從而大大提高了系統的可復用性、可擴展性與易維護性。而且由于不同層之間的低耦合度,使得團隊成員能夠并行開發,從而大大節省了時間,提高了應用的開發效率。

由于SSH提供了很多有用的框架,因此能顯著提高項目的開發效率。其主要優點如下:

1)Struts實現了MVC模式,這種模式的特點是對應用程序進行了很好的分層,使得開發人員只需要把開發重點放在業務邏輯的開發即可。不僅如此,Struts還提供了許多非常有用的標簽庫,這些標簽能夠顯著地提高開發人員的開發效率。

2)Spring可以用來管理對象。使用Spring的IoC容器,把對象之間的依賴關系交給Spring,降低組件之間的耦合性,讓開發人員更專注于業務邏輯的開發。Spring采用了IoC和AOP的思想,使得它具有很好的模塊化,程序與可以根據需求使用其中的一個模塊。Spring還提供了一些非常有用的功能,例如事務管理等。

3)Hibernate作為一個輕量級的持久性框架,實現了高效的對象關系映射,使得開發可以完全采用面向對象的思想,而不需要關心數據庫的關系模型。使用Hibernate開發的系統有很好的可移植性,可以很容易地實現不同數據庫之間的移植,而不需要關心不同數據庫SQL語句的差異。

11.

SQL語言的功能有哪些正確答案:SQL是結構化查詢語言(StructuredQueryLanguage)的縮寫,其功能包括數據查詢、數據操縱、數據定義和數據控制4個部分。

數據查詢是數據庫中最常見的操作,通過select語句可以得到所需的信息。SQL語言的數據操縱語句(DataManipulationLanguage,DML)主要包括插入數據、修改數據以及刪除數據3種語句。SQL語言使用數據定義語言(DataDefinitionLanguage,DDL)實現數據定義功能,可對數據庫用戶、基本表、視圖、索引進行定義與撤銷。數據控制語句(DataControlLanguage,DCL)用于對數據庫進行統一的控制管理,保證數據在多用戶共享的情況下能夠安全。

基本的SQL語句有select、insert、update、delete、create、drop、grant、revoke等。其具體使用方式見表。基本SQL語句的使用方式

關鍵字描述語法格式數據查詢select選擇符合條件的記錄select*fromtablewhere條件語句數據操縱insert插入一條記錄insertintotabIe(字段1,字段2...)values(值1,值2...)update更新語句updatetableset字段名=字段值where條件表達式delete刪除記錄Deletefromtablewhere條件表達式數據定義create數據表的建立createtabletablename(字段1,字段2...)drop數據表的刪除droptabletablename數據控制grant為用戶授予系統權限grant<系統權限>|<角色>[,<系統權限>|<角色>]…to<用戶名>|<角色>|public[,<用戶名>|<角色>]…[withadminoption]revoke收回系統權限revoke<系統權限>|<角色>[,<系統權限>|<角色>]…from<用戶名>|<角色>|public[,<用戶名>|<角色>]…

例如,設教務管理系統中有3個基本表:

學生信息表S(SNO,SNAME,AGE,SEX),其屬性分別表示學號、學生姓名、年齡和性別。

選課信息表SC(SNO,CNO,SCGRADE),其屬性分別表示學號、課程號和成績。

課程信息表C(CNO,CNAME,CTEACHER),其屬性分別表示課程號、課程名稱和任課老師姓名。

下面運用SQL語句進行相關操作。

1)把SC表中每門課程的平均成績插入到另外一個已經存在的表SC_C(CNO,CNAME,AVG_GRADE)中,其中AVG_GRADE表示每門課程的平均成績。

INSERTINTOSC_C(CNO,CNAME,AVG_GRADE)

SELECTSC.CNO,C.NAME,AVG(SCGRADE)FROMSC,CWHERESC.CNO=C.CNO

2)從SC表中把選何昊老師所授課程的女生的選課記錄刪除。

DELETEFROMSC.S.CWHERESC.SNO=S.SNOANDSC.CNO=C.CNOANDC.CTEACHER='何昊'

3)規定女生所選修何吳老師的課程的成績都應該在80分以上(含80分)。

ALERTTABLESC,S,C

ADDCONSTRAINTCRADECHECK(GRADE>=80)

WHERESC.CNO=C.CNOandSC.SNO=S.SNOANDC.CTEACHER='何昊'

4)找出沒有選修過何昊老師的課程的所有學生的姓名。

SELECTSNAMEFROMS

WHERENOTEXISTS(

SELECT*FROMSC.CWHERESC.CNO=C.CNOANDCNAME='何昊'ANDSC.SNO=S.SNO)

5)列出有兩門以上(含兩門)不及格課程(成績小于60)的學生的姓名及其平均成績。

SELECTS.SNO,S.SNAME,AVG_SCGRADE=AVG(SC.SCGRADE)

FROMS,SC,(

SELECTSNOFROMSCWHERESCGRADE<60GROUPBYSNO

HAVINGCOUNT(DISTINCTCNO)>=2)AWHERES.SNO=A.SNOANDSC.SNO=A.SNO

GROUPBYS.SNO,S.SNAME

6)列出既學過“1”號課程,又學過“2”號課程的所有學生的姓名。

SELECTS.SNO,S.SNAME

FROMS,(SELECTSC.SNOFROMSC,C

WHERESC.CNO=C.CNOANDC.CNAMEIN('1','2')

GROUPBYSNO

HAVINGCOUNT(DISTINCTCNO)=2

)SCWHERES.SNO=SC.SNO

7)列出“1”號課成績比“2”號同學該門課成績高的所有學生的學號。

SELECTS.SNO,S.SNAME

FROMS,(

SELECTSC1.SN0

FROMSCSC1,CC1,SCSC2,CC2

WHERESC1.CNO=C1.CN0ANDC1.NAME='1'

ANDSC2.CNO=C2.CN0ANDC2.NAME='2'

ANDSC1.SCGRADE>SC2.SCGRADE

)SCWHERES.SNO=SC.SN0

8)列出“1”號課成績比“2”號課成績高的所有學生的學號及其“1”號課和“2”號課的成績。

SELECTS.SNO,S.SNAME,SC.[1號課成績],SC.[2號課成績]

FROMS,(

SELECTSC1.SN0,[1號課成績]=SC1.SCGRADE,[2號課成績]=SC2.SCGRADE

FROMSCSC1.CC1,SCSC2,CC2

WHERESC1.CN0=C1.CN0ANDC1.NAME='1'

ANDSC2.CN0=C2.CN0ANDC2.NAME='2'

ANDSC1.SCGRADE>SC2.SCGRADE

)SCWHERES.SNO=SC.SNO

引申:delete與truncate命令有哪些區別?

相同點:都可以用來刪除一個表中的數據。

不同點:

1)truncate一是一個數據定義語言(DataDefinitionLanguage,DDL),它會被隱式地提交,一旦執行后將不能回滾。delete執行的過程是每次從表中刪除一行數據,同時將刪除的操作以日志的形式進行保存,以便將來進行回滾操作。

2)用delete操作后,被刪除的數據占用的存儲空間還在,還可以恢復。而用truncate操作刪除數據后,被刪除的數據會立即釋放占用的存儲空間,被刪除的數據是不能被恢復的。

3)truneate的執行速度比delete快。

常見筆試題:

Oracle數據庫的一個表中有若干條數據,其占用的存儲空間為10MB,如果用delete語句刪除表中的所有數據,此時該表所占存儲空間為多大?

答案:10MB。數據庫中delete操作類似于在Windows系統中把數據放到回收站,還可以恢復,因此它不會立即釋放所占的存儲空間。如果想在刪除數據后立即釋放存儲空間,可以使用truncate。

12.

內連接與外連接有什么區別正確答案:內連接,也被稱為自然連接,只有兩個表相匹配的行才能在結果集中出現。返回的結果集選取了兩個表中所有相匹配的數據,舍棄了不匹配的數據。由于內連接是從結果表中刪除與其他連接表中沒有匹配的所有行,所以內連接可能會造成信息的丟失。內連接的語法如下:

selectfieldlistfromtablel[inner]jointable2ontable1.column=table2.column

內連接是保證兩個表中的所有行都滿足連接條件,而外連接則不然。外連接不僅包含符合連接條件的行,而且還包括左表(左外連接時)、右表(右外連接時)或兩個邊接表(全外連接)中的所有數據行。SQL的外連接共有3種類型:左外連接(關鍵字為LEFI、OUTERJOIN)、右外連接(關鍵字為RIGHTOUTERJOIN)和全外連接(關鍵字為FULLOUTERJOIN)。外連接的用法和內連接一樣,只是將INNERJOIN關鍵字替換為相應的外連接關鍵字即可。

內連接只顯示符合連接條件的記錄,外連接除了顯示符合連接條件的記錄外,還顯示表中的記錄,例如,如果使用左外連接,還顯示左表中的記錄。

下面為學生表A和學生表B。表1為學生表A,表2為學生表B。表1學生表A學號姓名0001張三0002李四0003王五表2學生表B學號課程名0001數學0002英語0003數學0004計算機對表A和表B進行內連接后的結果見表3。表3內連接學號姓名課程名0001張三數學0002李四英語0003王五數學對表A和表B進行左外連接后的結果見表4。表4左外連接學號姓名課程名0001張三數學0002李四英語0003王五數學0004

計算機

13.

什么是事務正確答案:事務是數據庫中一個單獨的執行單元(Unit),它通常由高級數據庫操作語言(例如SQL)或編程語言(例如C++、Java等)編寫的用戶程序的執行所引起。當在數據庫中更改數據成功時,在事務中更改的數據便會提交,不再改變。否則,事務就取消或者回滾,更改無效。

以網上購物為例,其交易過程至少包括以下幾個步驟:

1)更新客戶所購商品的庫存信息。

2)保存客戶付款信息。

3)生成訂單并且保存到數據庫中。

4)更新用戶相關信息,例如購物數量等。

在正常情況下,這些操作都將順利進行,最終交易成功,與交易相關的所有數據庫信息也成功地更新。但是,如果遇到突然斷電或是其他意外情況,導致這一系列過程中任何一個環節出了差錯(例如在更新商品庫存信息時發生異常、顧客銀行賬戶余額不足等),都將導致整個交易過程失敗。而一旦交易失敗,數據庫中所有信息都必須保持交易前的狀態不變,例如最后一步更新用戶信息時失敗而導致交易失敗,那么必須保證這筆失敗的交易不影響數據庫的狀態,即原有的庫存信息沒有被更新、用戶也沒有付款、訂單也沒有生成。否則,數據庫的信息將會不一致,或者出現更為嚴重的不可預測的后果,數據庫事務正是用來保證這種情況下交易的平穩性和可預測性的技術。

事務必須滿足4個屬性,即原子性(atomicity)、一致性(consistency)、隔離性(isolation)、持久性(durability),即ACID4種屬性。

(1)原子性

事務是一個不可分割的整體,為了保證事務的總體目標,事務必須具有原子性,即當數據修改時,要么全執行,要么全不執行,即不允許事務部分地完成,避免了只執行這些操作的一部分而帶來的錯誤。原子性要求事務必須被完整執行。

(2)一致性

一個事務執行之前和執行之后,數據庫數據必須保持一致性狀態。數據庫的一致性狀態應該滿足模式鎖指定的約束,那么在完整執行該事務后數據庫仍然處于一致性狀態。為了維護所有數據的完整性,在關系型數據庫中,所有規則必

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論