版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
第9章“清風書苑”系統(tǒng)及其注冊模塊的實現(xiàn)9.1“清風書苑”系統(tǒng)的功能與組成9.2“清風書苑”系統(tǒng)數(shù)據(jù)庫設計9.3JPA與Spring的整合9.4通用業(yè)務邏輯的實現(xiàn)9.5各實體業(yè)務邏輯的分析與實現(xiàn)9.6用戶注冊功能的實現(xiàn)方法9.7項目頁頭、頁尾及主頁的處理
9.1“清風書苑”系統(tǒng)的功能與組成
“清風書苑”系統(tǒng)是典型的電子商務網(wǎng)站系統(tǒng),包含一般電子商務網(wǎng)站所應有的用戶管理、商品管理、購物車管理和訂單管理等模塊。圖9-1為各個子功能之間的關系圖。圖9-1清風書苑Action關系圖“清風書苑”系統(tǒng)從Web頁面上來看由三部分組成:
(1)?Head.jsp:所有Web頁面的頁頭,主要功能為導航,包括登錄、注冊、首頁和購物車的頁面導航,如圖9-2所示。圖9-2Head.jsp頁面
(2)?Foot.jsp:所有Web頁面的頁尾,主要功能也為導航,包括網(wǎng)站具體事務(一般為電子商務網(wǎng)站購物中涉及的如配送、支付和訂單等事務)和相關鏈接導航,同時可以把網(wǎng)站聯(lián)系方式和版權(quán)標注在頁尾,如圖9-3所示。圖9-3Foot.jsp頁面
(3)功能模塊:所有功能模塊都可以通過頁頭和頁尾來實現(xiàn)各種導航。
①用戶登錄管理功能。用戶通過注冊頁面register.jsp(registerAction)完成注冊,通過登錄頁面login.jsp(loginAction)進入用戶管理界面user.jsp(user)。此界面包含以下功能:
修改密碼頁面updatePass.jsp(updatePassAction);
訂單查看頁面orderList.jsp(orderListAction),其中每個訂單的明細查看頁面為bookOrderSingle.jsp(orderSingleAction);
注銷頁面(loginOutAction)。②管理員登錄管理功能。管理員通過登錄頁面login.jsp(loginAction)進入用戶管理界面manager.jsp(manager)。此界面包含以下功能:
圖書添加頁面bookAdd.jsp(addBook);
圖書管理頁面bookManage.jsp(bookManagerAction),每行圖書列表簡單顯示圖書信息,可通過單擊圖書鏈接進入單本圖書的具體信息頁面singlebook.jsp(singleBookAction)。
圖書管理頁面的每行含有圖書顯示表單信息頁面bookUpdate.jsp(updateBook)和圖書更新頁面bookUpdate_ok.jsp(updateOKBook);
圖書管理頁面的每行含有圖書刪除頁面bookDelete.jsp(bookDelete);
注銷頁面(loginOutAction)。③圖書信息。主頁直接進入圖書列表頁面booklist.jsp(bookListAction),在booklist.jsp中通過循環(huán)的方式包含圖書列表中每本書的顯示頁面onebooklist.jsp。但為了能在圖書列表中顯示更多圖書(此頁面中圖書信息不全),可通過單擊圖書鏈接進入單本圖書具體信息頁面singlebook.jsp(singleBookAction)。④購物車功能。購物車頁面cart.jsp(cartAction)包含以下功能:
購物車更新圖書數(shù)量操作(updateAmount);
購物車刪除某本圖書操作(delete);
清空購物車操作(deleteall);
進入結(jié)算,生成訂單頁面bookOrder.jsp(orderAction)和單個訂單明細查看頁面bookOrderSingle.jsp(orderSingleAction)。
9.2“清風書苑”系統(tǒng)數(shù)據(jù)庫設計
9.2.1數(shù)據(jù)庫中各表的結(jié)構(gòu)
“清風書苑”系統(tǒng)的數(shù)據(jù)庫名為bookStore,包含四個相關數(shù)據(jù)庫,其結(jié)構(gòu)和字段信息分別如下:
(1)用戶信息表如圖9-4所示。圖9-4userinfo表
(2)訂單信息表如圖9-5所示。圖9-5ordertable表
(3)訂單項信息表如圖9-6所示。圖9-6orderlist表
(4)圖書信息表如圖9-7所示。圖9-7bookinfo表9.2.2數(shù)據(jù)表對應實體在JPA中的實現(xiàn)
1.?JPA環(huán)境的搭建
●?persistence-unit元素的name=“com”;
●?<propertyname="hibernate.connection.url"value="jdbc:mysql://localhost:3306/bookStore?useUnicode=true&characterEncoding=UTF-8"/>。
2.實體的實現(xiàn)
1)用戶信息實體
用戶信息實體中涉及一個權(quán)限枚舉類Limited.java,定義了用戶和管理員權(quán)限,讀者可根據(jù)實際項目自行定義不同權(quán)限。其代碼如下:
packagecom.bean.user;
publicenumLimited{
USER,MANAGER
}用戶信息實體的屬性定義如下:
packagecom.bean.user;
……//省略導入包定義
@Entity
publicclassUserInfoimplementsSerializable{
@Id@GeneratedValue privateIntegerid;
@Column(length=20,nullable=false)privateStringuserName;
@Column(length=20,nullable=false)privateStringpassword;
@Column(length=20,nullable=false)privateStringemail;
@Enumerated(EnumType.STRING) privateLimitedlimited=Limited.USER;
publicUserInfo(){ }
publicUserInfo(StringuserName,Stringpassword,Stringemail){
this.userName=userName;
this.password=password;
this.email=email;
}
……//省略get/set方法
}
2)訂單信息實體
訂單信息實體的屬性定義如下:
packagecom.bean.cart;
……//省略導入包定義
@Entity
@Table(name=“ordertable”)
publicclassOrderimplementsSerializable{
@Id@GeneratedValueprivateIntegerid;
@Column(nullable=false)privateIntegeruserID;
@Column(nullable=false)privateFloatorderPrice;
@Temporal(TemporalType.DATE)privateDatebuyDate=newDate();
publicOrder(){}
publicOrder(Integerid){this.id=id;}
……//省略get/set方法
}3)訂單項信息實體
訂單項信息實體的屬性定義如下:
packagecom.bean.cart;
……//省略導入包定義
@Entity
publicclassOrderListimplementsSerializable{
@Id@GeneratedValueprivateIntegerid;
@Column(nullable=false)privateIntegerorderID;
@Column(nullable=false)privateIntegerbookID;
@Column(nullable=false)privateIntegerbookAmount;
……//省略get/set方法
}4)圖書信息實體
圖書信息實體的屬性定義如下:
packagecom.bean.book;
……//省略導入包定義
@Entity
publicclassBookInfoimplementsSerializable{
@Id@GeneratedValueprivateIntegerid;
@Column(length=15,nullable=false)privateStringISBN;
@Column(length=50,nullable=false)privateStringbookName;
@Column(length=20,nullable=false)privateStringauthor;
@Column(length=10)privateStringbookType;
@Column(length=20,nullable=false)privateStringpublisher;
@Column(length=20)publicStringbookPic;
@Temporal(TemporalType.DATE)privateDatepublishDate;
@Column(length=200)privateStringdescription;
@Column(nullable=false)privateFloatmarketPrice;
@Column(nullable=false)privateFloatsellPrice;
@Column(nullable=false)privateBooleanvisible=true;
@Temporal(TemporalType.DATE)privateDatecreateDate=newDate();
@Column(nullable=false)privateIntegerclickCount=1;
@Column(nullable=false)privateIntegersellCount=0;
@Column(nullable=false)privateBooleancommend=false;
privateIntegeramount;//在購物車中使用的臨時數(shù)據(jù)
publicBookInfo(){}
publicBookInfo(Integerid){this.id=id;}
publicBookInfo(Stringisbn,Stringauthor,StringbookName,
Booleancommend,FloatmarketPrice,Stringpublisher,
FloatsellPrice,Booleanvisible){
ISBN=isbn;
this.author=author;
this.bookName=bookName;
mend=commend;
this.marketPrice=marketPrice;
this.publisher=publisher;
this.sellPrice=sellPrice;
this.visible=visible;
}
@Transient
publicFloatgetSavedPrice()
{returnmarketPrice-sellPrice;}
@Transient
publicFloatgetSinglePrice()
{returnsellPrice*amount;}
……//省略所有屬性的get/set方法
}
3.使用測試方法生成對應的數(shù)據(jù)表
使用UserTest.java測試類的testSave()方法來完成實體對應表結(jié)構(gòu)在數(shù)據(jù)庫bookStore的建立,分別可以生成如圖9-4、圖9-5、圖9-6和圖9-7所示的數(shù)據(jù)表結(jié)構(gòu)。
packagejunit.test;
……//省略導入包定義
publicclassUserTest{
@Test
publicvoidtestSave(){
EntityManagerFactoryfactory=Persistence.createEntityManagerFactory("com");
factory.close();
}}9.3JPA與Spring的整合
9.3.1Spring框架結(jié)構(gòu)
Spring是一個開源框架,是一個從實際開發(fā)中抽取出來的框架。因此,它完成了大量開發(fā)中的通用步驟,留給開發(fā)者的僅僅是與特定應用相關的部分,從而大大提高了企業(yè)應用的開發(fā)效率。
Spring為企業(yè)應用的開發(fā)提供了一個輕量級的解決方案。該方案包括基于依賴注入的核心機制(IOC),基于AOP的聲明式事務管理,與多種持久層技術(shù)以及優(yōu)秀的WebMVC框架等的整合。Spring不是用來取代已有的那些框架,而是以高度的開發(fā)性與它們無縫整合??梢哉f,Spring是企業(yè)應用開發(fā)的“一站式”選擇。Spring貫穿表現(xiàn)層、業(yè)務層和持久層??偨Y(jié)起來,Spring有如下優(yōu)點:
低侵入式設計,代碼污染極低;
獨立于各種應用服務器,基于Spring框架的應用,可以真正實現(xiàn)一次定義反復使用的宗旨;
Spring的IOC機制降低了業(yè)務對象替換的復雜性;
Spring的高度開放性,使得開發(fā)者可自由選用Spring框架的部分組件。
Spring框架由七個定義良好的模塊組成,構(gòu)建在核心容器之上,核心容器定義了創(chuàng)建、配置和管理bean的方式,如圖9-8所示。圖9-8Spring框架組件結(jié)構(gòu)圖每個模塊的功能如下:
核心容器:核心容器提供Spring框架的基本功能。核心容器的主要組件是BeanFactory,它是工廠模式的實現(xiàn)。BeanFactory使用控制反轉(zhuǎn)(IOC)模式將應用程序的配置和依賴性規(guī)范與實際的應用程序代碼分開。
Spring上下文:?Spring上下文是一個配置文件,向Spring框架提供上下文信息。Spring上下文包括的服務項目有JNDI、EJB、電子郵件、國際化、校驗和調(diào)度功能等。
SpringAOP:通過配置管理特性,SpringAOP模塊直接將面向方法的編程功能集成到了Spring框架中。所以,可以很容易使Spring框架管理的任何對象支持AOP。SpringAOP模塊為基于Spring的應用程序中的對象提供了事務管理服務。通過使用SpringAOP,不用依賴EJB組件,就可以將聲明性事務管理集成到應用程序中。
SpringDAO:JDBCDAO抽象層提供了有意義的異常層次結(jié)構(gòu),可用該結(jié)構(gòu)來管理異常處理和不同數(shù)據(jù)庫供應商拋出的錯誤消息。異常層次結(jié)構(gòu)簡化了錯誤處理,并且極大地降低了需要編寫異常代碼的數(shù)量(例如打開和關閉連接)。SpringDAO的面向JDBC的異常遵從通用的DAO異常層次結(jié)構(gòu)。
SpringORM:Spring框架插入了若干個ORM框架,從而提供了ORM的對象關系工具,其中包括JDO、Hibernate和iBatisSQLMap。所有這些都遵從Spring的通用事務和DAO異常層次結(jié)構(gòu)。
SpringWeb模塊:Web上下文模塊建立在應用程序上下文模塊之上,為基于Web的應用程序提供了上下文。所以,Spring框架支持與JakartaStruts的集成。Web模塊還簡化了處理多部分請求以及將請求參數(shù)綁定到域?qū)ο蟮墓ぷ鳌?/p>
SpringMVC框架:MVC框架是一個全功能的構(gòu)建Web應用程序的MVC實現(xiàn)。通過策略接口,MVC框架變成為高度可配置的,并容納了大量視圖技術(shù),其中包括JSP、Velocity、Tiles、iText和POI。
Spring框架的功能可以用在任何J2EE服務器中,大多數(shù)功能也適用于不受管理的環(huán)境。本應用實例選用Spring2.5版本,Spring2.5是對Spring2.0的增強,增加了一些新的特性。下面列舉出其中常用的新特性:
全面支持Java6和JavaEE5(JDBC4.0,JTA1.1,JavaMail1.4,JAX-WS2.0等);
全特性的注釋驅(qū)動依賴注入,包括對限定詞的支持;
支持基于CLASSPATH的組件掃描,可自動偵測有注釋的類;
支持AspectJ切點表達式中包含beanname切點的元素;
內(nèi)置AspectJ加載時編織,基于LoadTimeWeaver提?。?/p>
更多的XML配置文件的名字空間支持,比如context和JMS等,最大程度地提高了編寫的方便性;
全面修訂集成測試框架,支持JUnit4和TestNG。9.3.2Spring的IoC和AOP
1.?IoC
Spring的核心模塊為控制反轉(zhuǎn)(IoC,InversionofControl)容器,又稱為依賴注入(DI,DependencyInjection),主要解決的是組件的松耦合和可重用性。
控制反轉(zhuǎn)就是由容器控制對象之間的關系,而非傳統(tǒng)實現(xiàn)中由程序代碼之間操控??刂茩?quán)由應用程序轉(zhuǎn)移到了外部容器,這種控制權(quán)的轉(zhuǎn)移即所謂的反轉(zhuǎn)。
IoC實現(xiàn)模式的三個類型如下:
(1)服務需要實現(xiàn)專門的接口,通過接口,由對象提供這些服務,可以從對象查詢依賴性(例如,需要的附加服務)。
(2)通過JavaBean的屬性(例如setter方法)分配依賴性。
(3)依賴性以構(gòu)造函數(shù)的形式提供,不以JavaBean屬性的形式公開。
Spring框架的IoC容器采用類型(2)和類型(3)實現(xiàn)。
2.?AOP
Spring的另一個重要模塊是面向方法的編程(AOP)。它是一種編程技術(shù),允許程序員對橫切關注點或橫切典型的職責分界線行為(例如日志和事務管理)進行模塊化。AOP的核心構(gòu)造是方面,它可以將那些影響多個類的行為封裝到可重用的模塊中。
AOP和IOC是補充性的技術(shù),它們都運用模塊化方式解決企業(yè)應用程序開發(fā)中的復雜問題。在典型的面向?qū)ο箝_發(fā)方式中,可能要將日志記錄語句放在所有方法和Java類中才能實現(xiàn)日志功能。在AOP方式中,可以反過來將日志服務模塊化,并以聲明的方式將它們應用到需要日志的組件上。當然,其優(yōu)勢就是Java類不需要知道日志服務的存在,也不需要考慮相關的代碼。所以,用SpringAOP編寫的應用程序代碼是松散耦合的。
3.?Spring對DAO和ORM提供的支持
Spring對多種持久化服務都有良好的支持,比如DAO和ORM。
(1)?DAO(數(shù)據(jù)訪問對象)。Spring對DAO提供支持的主要目標是:以標準的方式使用JDBC、Hibernate、JPA。Spring使得開發(fā)人員可以在這些技術(shù)間方便的切換,而且不需要捕獲各種技術(shù)中特定的異常。
(2)?ORM(對象關系映射)。Spring2.5提供了與JPA、Hibernate和JDO等SQL映射的集成,Spring2.5之后的版本才提供JPA的支持,以幫助開發(fā)人員處理很多典型的JPA整合
問題。9.3.3JPA中整合Spring的實現(xiàn)
1.?Spring的下載和安裝
本書使用Spring2.5.4版本的標準。同其它框架的使用一樣,集成Spring框架時首先要把與應用相關的Spring支持包放入CLASSPATH環(huán)境下。下面講解Spring下載和添加到環(huán)境變量的步驟。
【步驟1】下載Spring2.5.4。
登錄站點,下載spring-framework-2.5.4-with-dependencies.zip包,該壓縮包不僅包含Spring的開發(fā)包,而且包含Spring編譯和運行所依賴的第三方類庫。
【步驟2】添加使用壓縮包。
解壓縮下載的壓縮包,把以下JAR文件復制到bookSite工程的WEB-INF/lib文件夾下:
支持Spring的JAR包:dist目錄下spring.jar;
支持AOP編程的JAR包:lib/Aspectj目錄下aspectjrt.jar和aspectjweaver.jar;
動態(tài)生成器解碼的JAR包:lib/cglib目錄下cglib-nodep-2.1_3.jar;
支持通過注解實現(xiàn)依賴注入的JAR包:lib/j2ee目錄下common-annotations.jar。
另外,本項目使用Apache開源的DBCP數(shù)據(jù)庫連接池技術(shù),因此還需選擇lib/Jakarta-commons目錄下的JAR包:
commons-dbcp.jar;
commons-pool.jar;
commons-logging.jar。
2.將Spring集成到JPA
加入Spring的支持包后,就可以把Spring框架集成到bookSite中的JPA框架,下面是集成的詳細步驟。
【步驟1】建立配置文件監(jiān)聽。
Spring管理的所有bean配置文件默認定義在src/applicationContext.xml中,但此文件可以定義為其它名字,只需在工程的web.xml添加如下配置:<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
【步驟2】建立Spring配置文件。
根據(jù)【步驟1】中定義的配置,在src目錄下建立文件beans.xml,其具體代碼如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
mlns:context="/schema/context"
xmlns:aop="/schema/aop"
mlns:tx="/schema/tx"xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans-2.5.xsd
/schema/context
/schema/context/spring-context-2.5.xsd
/schema/aop
/schema/aop/spring-aop-2.5.xsd
/schema/tx
/schema/tx/spring-tx-2.5.xsd">
<context:component-scanbase-package="com"/> ①
<context:property-placeholderlocation="classpath:perties"/> ②<!--定義數(shù)據(jù)源Bean,使用DBCP數(shù)據(jù)庫連接池技術(shù)-->
<beanid="dataSource"class="mons.dbcp.BasicDataSource"
destroy-method="close">
③
<propertyname="driverClassName"value="${driverClassName}"/>
<propertyname="url"value="${url}"/>
<propertyname="username"value="${username}"/>
<propertyname="password"value="${password}"/>
<propertyname="initialSize"value="${initialSize}"/>
<propertyname="maxActive"value="${maxActive}"/><propertyname="maxIdle"value="${maxIdle}"/>
<propertyname="minIdle"value="${minIdle}"/>
</bean>
<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">④
<propertyname="dataSource"ref="dataSource"/>⑤
<propertyname="persistenceXmlLocation"value="classpath:META-INF/persistence.xml"/>⑥<propertyname="loadTimeWeaver">
<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="entityManagerFactory"/>
</bean>⑦
<tx:annotation-driventransaction-manager="transactionManager"/>⑧
</beans>對以上配置代碼中的各代碼段進行解釋如下:
代碼①:base-package=“com”表示所有com包中的文件將納入spring容器的管理中。
代碼②:配置文件使用的參數(shù)定義文件為src/perties。
代碼③:定義數(shù)據(jù)源dataSource,使用DBCP數(shù)據(jù)庫連接池技術(shù),配置所有連接參數(shù)。
代碼④:定義JPA的entityManagerFactor。
代碼⑤:依賴注入entityManagerFactory所需的數(shù)據(jù)源dataSource。
代碼⑥:引入JPA的persistence.xml配置文件,定義JPA的entityManagerFactory屬性。
代碼⑦:配置JPA的局部事務管理器,使用JpaTransactionManager類,該類是針對采用JPA持久化連接的特定接口。
代碼⑧:使@transactional注釋起作用,凡使用此注釋的類自動納入事務管理器,無需在此配置文件中重復申明。
【步驟3】建立perties文件。
在具體代碼如下:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bookStore?useUnicode
=true&characterEncoding=UTF-8
username=root
password=123456
initialSize=1
maxActive=100
maxIdle=8
minIdle=1細心的讀者會發(fā)現(xiàn),這些值與JPA配置文件persistence.xml中設置的值重復。因此,在整合Spring之后,需要把persistence.xml文件中的以下代碼刪除:
<propertyname="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver"/>
<propertyname="hibernate.connection.url"value="jdbc:mysql://localhost:3306/bookStore?useUnicode=true&characterEncoding=UTF-8"/>
<propertyname="hibernate.connection.username"value="root"/>
<propertyname="hibernate.connection.password"value="123456"/>
【步驟4】JUnit測試Spring框架。
新建測試文件junit.test.UserSpringTest.java,添加springtest()測試函數(shù),驗證Spring框架與JPA框架的整合狀況。具體代碼如下:
@Test
publicvoidspringtest(){
ApplicationContextcxt=newClassPathXmlApplicationContext("beans.xml");
DataSource
dataSource=(DataSource)cxt.getBean("dataSource");
System.out.println(dataSource);
}
9.4通用業(yè)務邏輯的實現(xiàn)
9.4.1通用CRUD業(yè)務邏輯的實現(xiàn)
1.通用接口的定義
在接口DAO.java中定義了獲取數(shù)據(jù)表記錄總數(shù)、清除緩存數(shù)據(jù)、保存、更新、刪除、查找和對分頁數(shù)據(jù)處理的方法,對于沒有特殊處理邏輯的實體,這些方法足夠使用。
com.service.base.DAO.java代碼如下:packagecom.service.base;
importjava.util.LinkedHashMap;
importcom.utils.page.QueryResult;
publicinterfaceDAO{
//獲取記錄總數(shù)
public<T>longgetCount(Class<T>entityClass);
//清除一級緩存的數(shù)據(jù)
publicvoidclear();
//保存實體
publicvoidsave(Objectentity);
//更新實體publicvoidupdate(Objectentity);
//刪除實體1
public<T>voiddelete(Class<T>entityClass,Objectentityid);
//刪除實體2
public<T>voiddelete(Class<T>entityClass,Object[]entityids);
//根據(jù)主鍵獲取實體
public<T>Tfind(Class<T>entityClass,ObjectentityId);
//獲取分頁數(shù)據(jù)
public<T>QueryResult<T>getScrollData(Class<T>entityClass);public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,intmaxresult,Stringwherejpql,Object[]queryParams,LinkedHashMap<String,String>orderby);
public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,intmaxresult,Stringwherejpql,Object[]queryParams);
public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,intmaxresult,LinkedHashMap<String,String>orderby);
public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,intmaxresult);
}以上代碼中實現(xiàn)通用的處理為所有方法都不直接和具體實體類相關,而是使用泛型Class<T>entityClass來代表任一實體類,而取得具體實體類的實現(xiàn)方法在DaoSupport.java中使用getEntityName(Class<T>entityClass)方法來獲得,這樣實現(xiàn)不同實體CRUD操作共享通用代碼。
2.通用實現(xiàn)類的定義
DaoSupport.java實現(xiàn)接口DAO.java中定義的方法,并定義了一些輔助方法來幫助完成各方法的編碼。下面我們把DaoSupport.java的代碼分輔助方法和實現(xiàn)方法兩部分來講解。
1)輔助方法的實現(xiàn)
DaoSupport.java中為了使各實現(xiàn)方法的寫法更加簡略,定義了四個輔助方法:
(1)獲取當前操作實體的輔助函數(shù):protected<T>StringgetEntityName(Class<T>entityClass){
Stringentityname=entityClass.getSimpleName();
Entityentity=entityClass.getAnnotation(Entity.class);
if(()!=null&&!"".equals(())){
entityname=();}
returnentityname;
}(2)設置查詢語句變量參數(shù)的輔助函數(shù):
protectedvoidsetQueryParams(Queryquery,Object[]queryParams){
if(queryParams!=null&&queryParams.length>0){
for(inti=0;i<queryParams.length;i++){
query.setParameter(i+1,queryParams[i]);
}}}(3)設置查詢語句排序內(nèi)容的輔助函數(shù):
protectedStringbuildOrderby(LinkedHashMap<String,String>orderby){
StringBufferorderbyql=newStringBuffer("");
if(orderby!=null&&orderby.size()>0){
orderbyql.append("orderby");
for(Stringkey:orderby.keySet()){
orderbyql.append("o.").append(key).append("").append(orderby.get(key)).append(",");}
orderbyql.deleteCharAt(orderbyql.length()-1);
}
returnorderbyql.toString();}(4)設置查詢語句結(jié)果顯示域的輔助函數(shù):
protected<T>StringgetCountField(Class<T>clazz){
Stringout="o";
try{
PropertyDescriptor[]propertyDescriptors=Introspector.getBeanInfo(clazz).getPropertyDescriptors();
for(PropertyDescriptorpropertydesc:propertyDescriptors){
Methodmethod=propertydesc.getReadMethod();if(method!=null&&method.isAnnotationPresent(EmbeddedId.class)){
PropertyDescriptor[]ps=Introspector.getBeanInfo(propertydesc.getProperty-Type()).getPropertyDescriptors();
out="o."+propertydesc.getName()+"."+(!ps[1].getName().equals("class")?ps[1].getName():ps[0].getName());
break;}
}}catch(Exceptione){
e.printStackTrace();}
returnout;}
2)實現(xiàn)接口的方法
com.service.base.DaoSupport.java部分代碼如下:
packagecom.service.base;
……//省略導入包
@Transactional①
publicabstractclassDaoSupportimplementsDAO{
@PersistenceContextprotectedEntityManagerem;②
publicvoidclear(){
em.clear();}public<T>voiddelete(Class<T>entityClass,Objectentityid){
delete(entityClass,newObject[]{entityid});}
public<T>voiddelete(Class<T>entityClass,Object[]entityids){
for(Objectid:entityids){
em.remove(em.getReference(entityClass,id));
}}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)③public<T>Tfind(Class<T>entityClass,ObjectentityId){
returnem.find(entityClass,entityId);}
publicvoidsave(Objectentity){
em.persist(entity);}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)public<T>longgetCount(Class<T>entityClass){
return(Long)em.createQuery("selectcount("+getCountField(entityClass)+")from"+getEntityName(entityClass)+"o").getSingleResult();
}
publicvoidupdate(Objectentity){
em.merge(entity);}
……//省略getScrollData方法,在下面詳細介紹
……//省略其它4個輔助方法代碼
}
Propagation.MANDATORY:要求調(diào)用該方法的線程必須在一個已有的事務中執(zhí)行,否則拋出異常。
Propagation.NESTED:如果已處于事務中,則依然啟動新事務,方法嵌套在事務里執(zhí)行;如果不處于事務中,則創(chuàng)建一個新的事務,執(zhí)行該方法。
Propagation.NEVER:不允許調(diào)用該方法的線程處于事務環(huán)境中,否則拋出異常(與Propagation.MANDATORY相反)。
Propagation.NOT_SUPPORTED:如果調(diào)用該方法的線程處于事務中,則先暫停當前事務,然后執(zhí)行該方法。
Propagation.REQUIRED:要求在事務環(huán)境中執(zhí)行該方法,如果已處于事務中,則直接調(diào)用;如果不處于事務中,則啟用新的事務后執(zhí)行該方法;
Propagation.REQUIRES_NEW:不管是否存在事務,都創(chuàng)建一個新的事務,原來的事務暫停,新事務執(zhí)行完畢后繼續(xù)執(zhí)行原來的事務。
Propagation.SUPPORTS:如果當前執(zhí)行線程處于事務中,則使用當前事務,否則不使用事務。代碼②中使用了JPA框架注釋@PersistenceContext,它將實體與實體管理器關聯(lián)并自定義實體管理器的環(huán)境。在使用JPA持續(xù)性提供程序的應用程序中,可以使用EntityManager實例執(zhí)行所有持續(xù)性操作(創(chuàng)建、讀取、更新和刪除)。
在接口DAO.java中還定義了一系列的getScrollData()方法來實現(xiàn)數(shù)據(jù)的讀取,具體代碼如下:@SuppressWarnings("unchecked")
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,intmaxresult,Stringwherejpql,Object[]queryParams,LinkedHashMap<String,String>orderby){
④
QueryResultqr=newQueryResult<T>();
Stringentityname=getEntityName(entityClass);Queryquery=em.createQuery(“selectofrom”+entityname+“o”+(wherejpql==null?"":"where"+wherejpql)+buildOrderby(orderby));
setQueryParams(query,queryParams);//設置各個參數(shù)集
if(firstindex!=-1&&maxresult!=-1)
//設置當前頁的首記錄位置和每頁顯示記錄數(shù)
query.setFirstResult(firstindex).setMaxResults(maxresult);
qr.setResultlist(query.getResultList());
//設置返回結(jié)果集query=em.createQuery("selectcount("+getCountField(entityClass)+")from"+entityname+"o"+(wherejpql==null?"":"where"+wherejpql));
setQueryParams(query,queryParams);
qr.setTotalrecord((Long)query.getSingleResult()); //設置查詢結(jié)果記錄數(shù)
returnqr;
}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)public<T>QueryResult<T>getScrollData(Class<T>entityClass){ ⑤
returngetScrollData(entityClass,-1,-1);
}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
public<T>QueryResult<T>getScrollData(Class<T>entityClass,
intfirstindex,intmaxresult,LinkedHashMap<String,String>orderby){ ⑥
returngetScrollData(entityClass,firstindex,maxresult,null,null,orderby);
}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
public<T>QueryResult<T>getScrollData(Class<T>entityClass,
intfirstindex,intmaxresult,Stringwherejpql,Object[]queryParams){
⑦
returngetScrollData(entityClass,firstindex,maxresult,wherejpql,queryParams,null);
}
@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
public<T>QueryResult<T>getScrollData(Class<T>entityClass,intfirstindex,int
maxresult){⑧
returngetScrollData(entityClass,firstindex,maxresult,null,null,null);
}代碼④的實現(xiàn)過程見以上代碼的注釋,其中各參數(shù)的含
義為:
Class<T>entityClass:當前調(diào)用實體。
intfirstindex:當前頁的首記錄位置。
intmaxresult:每頁顯示記錄數(shù)。
Stringwherejpql:查詢條件字符串。
Object[]queryParams:查詢中使用的參數(shù)數(shù)組。
LinkedHashMap<String,String>orderby:查詢中排序條件的組合,如可定義如下代碼:
LinkedHashMap<String,String>orderby=new
LinkedHashMap<String,String>();
orderby.put(“createDate”,“desc”);
代碼④中使用了com.utils.page.QueryResult,這是分頁業(yè)務邏輯中定義的類,將在9.4.2節(jié)中詳細講解。9.4.2分頁業(yè)務邏輯的實現(xiàn)
1.實現(xiàn)邏輯類
1)查詢結(jié)果類
具體代碼如下:
packagecom.utils.page;
importjava.util.List;
publicclassQueryResult<T>{
privateList<T>resultlist;
privatelongtotalrecord;
……//省略get/set方法
}
2)在Web頁面中顯示頁面類
具體代碼如下:
packagecom.utils.page;
publicclassPageIndex{
privatelongstartindex;
privatelongendindex;
publicPageIndex(longstartindex,longendindex){
this.startindex=startindex;
this.endindex=endindex;}
……//省略get/set方法
}
3)設置索引頁面類
具體代碼如下:
packagecom.utils.page;
publicclassWebTool{
publicstaticPageIndexgetPageIndex(longviewpagecount,intcurrenPage,longtotalpage){
longstartpage=curren(viewpagecount%2==0?viewpagecount/2-1:viewpagecount/2);longendpage=currenPage+viewpagecount/2;
if(startpage<1){
startpage=1;
if(totalpage>=viewpagecount)endpage=viewpagecount;
elseendpage=totalpage;}
if(endpage>totalpage){
endpage=totalpage;
if((endviewpagecount)>0)startpage=endviewpagecount+1;
elsestartpage=1;}
returnnewPageIndex(startpage,endpage);
}}
(4)分頁每個頁面數(shù)據(jù)處理類
PageView.java為具體處理分頁相關變量的類,各變量的含義在代碼中已標明,請讀者仔細理解一下代碼中節(jié)選出的getXXX方法。packagecom.utils.page;
importjava.util.List;
publicclassPageView<T>
{privateintmaxresult=10; //每頁顯示數(shù)
privateintcurrentpage=1; //當前頁
privatelongtotalpage=1; //總頁數(shù)
privateList<T>records; //所有記錄
privatePageIndexpageindex; //頁數(shù)索引
privatelongtotalrecord; //總記錄數(shù)
privateintpageBarSize=3; //顯示索引頁面//構(gòu)造函數(shù),定義每頁顯示數(shù)和當前頁
publicPageView(intmaxresult,intcurrentpage)
{this.currentpage=currentpage;
this.maxresult=maxresult;
}
publicvoidsetQueryResult(QueryResult<T>qr)
{setTotalrecord(qr.getTotalrecord());
setRecords(qr.getResultlist());
}
publicvoidsetTotalrecord(longtotalrecord){
this.totalrecord=totalrecord;
//計算頁數(shù)
setTotalpage(this.totalrecord%this.maxresult==0?this.totalrecord/this.maxresult:this.totalrecord/this.maxresult+1);}
publicintgetFirstindex(){
return(getCurrentpage()-1)*this.maxresult;
}
publicvoidsetTotalpage(longtotalpage){
this.totalpage=totalpage;
this.pageindex=WebTool.getPageIndex(pageBarSize,currentpage,
totalpage);}
……//省略其它get/set方法
}
2.實現(xiàn)Web頁面
完成以上分頁邏輯的處理,在使用分頁功能的頁面中加入如下代碼即可實現(xiàn)當前數(shù)據(jù)集合的分頁功能:<s:beanname="org.apache.struts2.util.Counter"id="counter">
<s:paramname="first"value="#request.pageview.pageindex.startindex"/>
<s:paramname="last"value="#request.pageview.pageindex.endindex"/>
<s:ahref="XXX.action?page=1">首頁</s:a>
<s:iterator>
<s:iftest="#request.pageview.currentpage!=current-1">
<ahref='XXX.action?page=<s:property/>'><s:property/></a></s:if>
<s:else><fontcolor="black"><b><s:property/></b></font></s:else>
</s:iterator>
<ahref="XXX.action?page=${pageview.totalpage}">尾頁</a>|
當前第${pageview.currentpage}頁|共${pageview.totalpage}頁
</s:bean>
其中XXX.action中應該返回一個request級別的PageView類型變量,執(zhí)行頁面如圖9-9和圖9-10所示,由于pageBarSize=3,因此索引每次顯示3個索引鏈接。圖9-9分頁1圖9-10分頁2
9.5各實體業(yè)務邏輯的分析與實現(xiàn)
9.5.1各實體業(yè)務邏輯的分析
UserInfo實體:登錄業(yè)務和密碼更新業(yè)務;
OrderList實體:根據(jù)訂單號查找訂單項集合業(yè)務。
BookInfo實體和Order實體的業(yè)務邏輯都只涉及CRUD和分頁操作,因此只要繼承通用業(yè)務邏輯。9.5.2各實體業(yè)務邏輯的實現(xiàn)
1.各接口類的實現(xiàn)
以Order實體為例,其業(yè)務邏輯接口定義為:
packagecom.service.bean;
importcom.service.base.DAO;
publicinterfaceOrderServiceextendsDAO{}其它三個實體的業(yè)務邏輯接口定義都相同,只需把類名分別換成UserInfoService.java、BookInfoService.java、OrderListService.java。
另外,在UserInfoService.java中增加抽象方法:
publicUserInfologin(StringuserName,Stringpassword);
publicintupdatePassword(Integerid,Stringpassword,Stringnewpass);
在OrderListService.java中增加抽象方法:
publicList<OrderList>findOrder(IntegerorderID);
2.各實現(xiàn)類的實現(xiàn)
以Order實體為例,其業(yè)務邏輯實現(xiàn)類定義為:
packagecom.service.bean.impl;
……//省略導入包
@Service
@Transactional
publicclassOrderServiceBeanextendsDaoSupportimplementsOrderService{}以上代碼中兩個注解的含義如下:
@Transactional:定義事務管理器,詳見9.4.1節(jié)。
@Service:表示依賴注入,即把此業(yè)務類歸入Spring容器管理,相當于在beans.xml中進行如下bean的配置:
<beanid=“bookInfoServiceBean”class=“com.service.bean.impl.BookInfoServiceBean”/>
使用了@Service注釋后,可以不再為beans.xml配置對應的bean。另外,在UserInfoServiceBean.java中增加抽象方法:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年建筑施工合同執(zhí)行細則
- 勞務派遣補充合同范本2024年
- 2024專業(yè)版代理操盤合同
- 2024裝修協(xié)議合同范本
- 2024設備轉(zhuǎn)讓合同范本設備購買合同范本2
- 南京銀行學生貸款合同
- 城市軌道工程施工借款合同
- 2024蘇州市全日制勞動合同
- 2024小賣部承包合同
- 2024自費養(yǎng)老合同范文
- 2024年二手物品寄售合同
- 2023年遼陽宏偉區(qū)龍鼎山社區(qū)衛(wèi)生服務中心招聘工作人員考試真題
- 三年級數(shù)學(上)計算題專項練習附答案集錦
- 高一期中家長會班級基本情況打算和措施模板
- 歷史期中復習課件七年級上冊復習課件(部編版2024)
- 專題7.2 空間點、直線、平面之間的位置關系(舉一反三)(新高考專用)(學生版) 2025年高考數(shù)學一輪復習專練(新高考專用)
- 7.2.2 先天性行為和學習行為練習 同步練習
- 2024-2025學年八年級物理上冊 4.2光的反射說課稿(新版)新人教版
- 《現(xiàn)代管理原理》章節(jié)測試參考答案
- 電子元器件有效貯存期、超期復驗及裝機前的篩選要求
- 2024秋期國家開放大學??啤陡叩葦?shù)學基礎》一平臺在線形考(形考任務一至四)試題及答案
評論
0/150
提交評論