實(shí)例介紹Struts+Spring+Hibernate開(kāi)發(fā)
一 介紹
本文并不想介紹Struts,Spring,Hibernate的原理系統(tǒng)架構(gòu)等,本文地目的是通過(guò)一個(gè)較復(fù)雜地實(shí)例介紹如何整合Struts,Spring,Hibernate,網(wǎng)上現(xiàn)有的例子雖然也能達(dá)到目的,但功能都比較單一,復(fù)雜的例子時(shí)會(huì)有意想不到的麻煩。本文對(duì)讀者假設(shè)已經(jīng)具備了以上框架的基礎(chǔ)知識(shí)。以及那些已經(jīng)了解Struts,Spring,Hibernate的基本概念,但是還沒(méi)有親身在較復(fù)雜的項(xiàng)目中體驗(yàn)Struts+Spring+Hibernate的開(kāi)發(fā)人員。
1 Struts
雖然不打算過(guò)多介紹Struts的原理,但是大概介紹一下還是有必要的。Struts本身就是 MVC 在這里負(fù)責(zé)將用戶數(shù)據(jù)傳人業(yè)務(wù)層,以及 將業(yè)務(wù)層處理的結(jié)果返回給用戶,此系統(tǒng)屬于較簡(jiǎn)單WEB應(yīng)用,采用了OpenSessionInView模式處理LazyLoad問(wèn)題,這樣我們可以在用戶視圖中使用 get,set方法來(lái)方便地獲取關(guān)聯(lián)對(duì)象。為了處理龐大的Action和ActionForm問(wèn)題,在此我門準(zhǔn)備使用DynaActionForm (DynaValidatorForm)和DispatchAction以及 動(dòng)態(tài)驗(yàn)證框架 來(lái)解決。及使用Tile來(lái)解決框架問(wèn)題 。使用自定義標(biāo)簽處理分頁(yè)和身份驗(yàn)證問(wèn)題。
2 Spring
Spring Framework最得以出名的是與Hibernate的無(wú)縫鏈接,雖然Spring 對(duì)Hibernate提供了90%以上的封裝,使我們不必去關(guān)心Session 的建立,關(guān)閉,以及事務(wù)使我們能夠?qū)P牡年P(guān)注業(yè)務(wù)邏輯。但是一些特殊情況如 有時(shí)需要Query以及Criteria 對(duì)象,分頁(yè)等,Spring不能給我們提供支持,總不能每次都在你的DAO上寫個(gè)HibernateCallBackup()吧?Spring的作用不是把Hibernate再封裝一層,而是讓你接觸不到Hibernate的API,而是幫助你管理好Session和Transaction。
在這里解決方法是:首先 寫一個(gè)IBase 的接口,和一個(gè)BaseDao的實(shí)現(xiàn)。在實(shí)現(xiàn)中仿照HibernateTemplate,將其功能一一實(shí)現(xiàn),同時(shí)考慮到Spring 未能支持的地方,我們不得已只好自己來(lái)管理Session,因此加入public Session openSession(),public Query getQuery(String sql),public Criteria getCriteria(Class clazz),以及分頁(yè)的方法。 然后為每一個(gè)Entity 都建立繼承于以上類的IEntity,與EntityDao。這里可以根據(jù)需求對(duì)Entity加入特殊的方法實(shí)現(xiàn),如 在 StudentsDao.java 中加入類似用戶身份驗(yàn)證等。以上就是數(shù)據(jù)訪問(wèn)層。接下來(lái)在Service層中通過(guò)對(duì)dao的引用完成業(yè)務(wù)邏輯方法。在下面的例子中我們分別為學(xué)生模塊,教師模塊,管理員模塊構(gòu)建Service層,StudentsServiceImpl,TeachersServiceImpl,AdminServiceImpl。
3 Hibernate
有了Spring的封裝,我們要對(duì)Hibernate做的就是正確實(shí)現(xiàn)對(duì)象關(guān)系的映射。由于此處處于系統(tǒng)的最底層,準(zhǔn)確無(wú)誤的實(shí)現(xiàn)對(duì)象之間的關(guān)聯(lián)關(guān)系映射將起著至關(guān)重要的作用。
總之,理解了Struts,Spring,Hibernate地原理以及之間的關(guān)系之后,剩下的工作就如同在以Spring為核心的Struts為表現(xiàn)的框架中堆積木。
下圖可以更好的幫助我們理解Struts,Spring,Hibernate之間的關(guān)系。
pic1.JPG
二 案例簡(jiǎn)述:
設(shè)計(jì)思路主要源于 大學(xué)選修課,該系統(tǒng)可以方便處理學(xué)生在課程選報(bào),學(xué)分查詢,成績(jī)查詢,以及 成績(jī)發(fā)布等。
系統(tǒng)以班級(jí)為核心,一門課程可以對(duì)應(yīng)多個(gè)班級(jí),一名教師也可以帶不同的班級(jí),學(xué)生可以選報(bào)不同課程所對(duì)應(yīng)的班級(jí),班級(jí)自身有目前人數(shù),和最大人數(shù),以及上課時(shí)間,上課地點(diǎn)的屬性。
學(xué)生在選報(bào)班級(jí)之后,班級(jí)的人數(shù)會(huì)自動(dòng)加一,直到等于最大人數(shù)時(shí),其他學(xué)生將會(huì)有人數(shù)已滿的錯(cuò)誤提示。同理如果學(xué)生選擇了同一課程的不同班級(jí),也將收到錯(cuò)誤提示。學(xué)生有密碼,系別,學(xué)分,地址,電話等屬性。
教師在系統(tǒng)中主要負(fù)責(zé)成績(jī)發(fā)布,教師可以對(duì)其所帶的班級(jí)的學(xué)生的成績(jī)修改,系統(tǒng)會(huì)以成績(jī)是否大于等于60來(lái)判斷學(xué)生是否通過(guò)考試,如果通過(guò)會(huì)將該課程的學(xué)分累加到學(xué)生學(xué)分,同樣如果教師二次修改了成績(jī),而且小于60,系統(tǒng)會(huì)在學(xué)生學(xué)分上扣掉該課程的分?jǐn)?shù)。
課程在系統(tǒng)中具體體現(xiàn)為班級(jí),自身帶有學(xué)分屬性。
系有編號(hào),名稱的屬性,同時(shí)可以作為聯(lián)系教師,課程,學(xué)生的橋梁。
功能模塊
l 身份驗(yàn)證模塊: 根據(jù)用戶名,密碼,用戶類別 轉(zhuǎn)發(fā)用戶到不同的模塊。
l 學(xué)生模塊: 查看課程,查看班級(jí),選報(bào)課程,查看己選課程,成績(jī)查詢。
l 教師模塊: 錄入成績(jī)
l 管理員模塊:對(duì)學(xué)生,教師,課程,班級(jí),系 增,刪,查,改。
三 具體實(shí)踐
代碼下載
http://m.tkk7.com/Files/limq/StudentManger.rar
1 對(duì)象關(guān)系映射:
首先,將庫(kù)表映射為數(shù)據(jù)模型(SQL在源碼中查看),轉(zhuǎn)換后的數(shù)據(jù)模型如下圖:
pic2.jpg
由此我們可以看出一下關(guān)聯(lián)關(guān)系:
1 Students 和 Contact(聯(lián)系方式)一對(duì)一關(guān)系。
2 Students 和 History(選課歷史) 一對(duì)多關(guān)系
3 Students 和 Classes 多對(duì)多關(guān)系。
4 Classes 和 Classes_info 一對(duì)多關(guān)系。
5 Classes 和 Teachers 多對(duì)一關(guān)系。
6 Classes 和 Courses 多對(duì)一關(guān)系。
7 Course 和 Department(系) 多對(duì)一關(guān)系。
8 Teachers 和 Department 多對(duì)一關(guān)系。
9 Students 和 Department 多對(duì)一關(guān)系。
在Hibernate中將以上關(guān)系一一映射,如Students 和 History 一對(duì)多關(guān)系
Students.cfg.xm.:
1
6
7
9 set>
10
同樣在History.cfg.xml中加入:
1
4 many-to-one>
5
用過(guò)MyEclipse開(kāi)發(fā)Hibernate的就知道,MyEclipse會(huì)幫助我們生成持久對(duì)象和抽象對(duì)象,我們要在 Students.java 中加入對(duì)History的引用
private Set history=new HashSet();
public Set getHistory() {
return history;
}
public void setHistory(Set history) {
this.history = history;
}
同時(shí),在AbstractHistory.java 中刪除student_id 以及對(duì)應(yīng)的get,set 方法,History.java 中加入
private Students student;
public Students getStudent() {
return student;
}
public void setStudent(Students student) {
this.student = student;
}
具體內(nèi)容請(qǐng)查看 源代碼。
2 DAO 數(shù)據(jù)訪問(wèn)層
首先,編寫IBaseDao與BaseDao,其中IBaseDao代碼如下:
1 package limq.hibernate.dao;
2
3 import java.util.Collection;
4 import java.util.List;
5 import net.sf.hibernate.Criteria;
6 import net.sf.hibernate.Query;
7 import net.sf.hibernate.Session;
8 import limq.exception.DaoException;
9
10 public interface IBaseDao {
11
12 public Session openSession();
13
14 public int getTotalCount( String hql) throws Exception;
15
16 public Query getQuery(String sql) throws Exception;
17
18 public Criteria getCriteria(Class clazz) throws Exception;
19
20 public int getTotalPage(int totalCount,int pageSize);
21
22 public void create(Object entity);
23
24 public void update(Object entity);
25
26 public void delete(Object entity) throws DaoException;
27
28 public void deleteAll(Class clazz) throws DaoException;
29
30 public void deleteAll(Collection entities) throws DaoException;
31
32 public Object loadByKey(Class clazz, String keyName, Object keyValue);
33
34 public List find(String queryString) throws DaoException;
35
36 public List find(String queryString, Object param) throws DaoException;
37
38 public List find(String queryString, Object[] params) throws DaoException;
39
40 }
41
BaseDao繼承org.springframework.orm.hibernate.support.HibernateDaoSupport
實(shí)現(xiàn)以上的 定義的方法
如:
1 public void create(Object entity) {
2 try {
3 getHibernateTemplate().save(entity);
4
5 } catch (Exception e) {
6 log.error("保存 " + entity.getClass().getName() + " 實(shí)例到數(shù)據(jù)庫(kù)失敗", e);
7
8 }
9 }
10 /**
11 * 獲得session
12 */
13 public Session openSession() {
14 return SessionFactoryUtils.getSession(getSessionFactory(), false);
15 }
16
17 /**
18 * 獲得Query對(duì)象
19 */
20 public Query getQuery(String sql) throws Exception{
21 Session session = this.openSession();
22 Query query = session.createQuery(sql);
23 return query;
24 }
25 /**
26 * 獲得Criteria對(duì)象
27 */
28 public Criteria getCriteria(Class clazz) throws Exception{
29
30 Session session=this.openSession();
31 Criteria criteria = session.createCriteria(clazz);
32 return criteria;
33 }
34
可以看到,這里即充分利用了Spring對(duì)Hibernate的支持,還彌補(bǔ)了Spring的不足。最后分別為每個(gè)持久對(duì)象建立Interface,以及DAO,使其分別繼承IBaseDao與BaseDao。
如IDepartment,DepartmentDao
1 public interface IDepartment extends IBaseDao {}
2
3 public class DepartmentDao extends BaseDao implements IBaseDao {}
4
3 Service 層
在這里需要認(rèn)真思考每個(gè)業(yè)務(wù)邏輯所能用到的持久層對(duì)象和DAO,還要完成配置Spring框架, 首先我一起看看applications-service.xml
1 xml version="1.0" encoding="UTF-8"?>
2 DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
3 "http://www.springframework.org/dtd/spring-beans.dtd">
4
5
6
7 com.mysql.jdbc.Drivervalue>
8 property>
9
10 jdbc:mysql://localhost:3306/Studentvalue>
11 property>
12
13 rootvalue>
14 property>
15
16 value>
17 property>
18 bean>
19
20
21
22 property>
23
24
-
25
- [轉(zhuǎn)]4個(gè)有用的filter
-
JSP中的全文檢索
- JAVA中的時(shí)間操作
- Ant應(yīng)用(1)
- 對(duì)于moxie的"WebWork教程"補(bǔ)充 - [類型轉(zhuǎn)化]
- J2EE學(xué)習(xí)經(jīng)驗(yàn)和流程
- 我眼中的Spring
- 類似QQ的同名用戶登錄問(wèn)題的解決
- TOMCAT完全攻略
-
90
-
101
-
112
-
123
-
134
-
145
<%=his.getClasses().getId()%>td>
28 | <%=his.getCourseName()%>td>
29 | <%=his.getEnrolTime()%>td>
30 | <%=his.getScore()%>td>
31 | <%=his.getMarking()%>td>
32 tr>
33 <%
34 }
35 %>
36 table>
37 |
posted on 2005-11-13 08:14 辰 閱讀(1111) 評(píng)論(1) 編輯 收藏 所屬分類: J2ee 評(píng)論# re: 實(shí)例介紹Struts+Spring+Hibernate開(kāi)發(fā) 回復(fù) 更多評(píng)論頁(yè)面都亂套了,沒(méi)法看啊
2008-02-13 15:38 | 到此一游
|
|