學(xué)習(xí)最快的方式看代碼是一個(gè)很好的方法,到springside網(wǎng)站下栽springside-2.0-RC1-allinone.zip,看最簡單的例子helloword,
包結(jié)構(gòu)很清晰,典型的mvc三層架構(gòu),model、service、web.

    看一眼mode.User.java,數(shù)據(jù)庫的實(shí)體bean,沒什么可說的。

    第二眼service.UserManager.java,心里想肯定是邏輯層中的Dao對(duì)數(shù)據(jù)庫的操作,增加、讀取、更新和刪除,editpus完后出乎我的意料
之外,里面沒有方法的實(shí)現(xiàn)
/**
 * 用戶管理業(yè)務(wù)類.
 * <p/>
 * 繼承于HibernateEntityDao,不需任何代碼即擁有默認(rèn)的對(duì)User對(duì)象的CRUD函數(shù). 如果想了解不繼承于EntityDao,自行編寫CRUD的寫法, 參考{@link UserManagerNativeVersion}.
 *
 * @author calvin
 * @see HibernateEntityDao
 * @see org.springside.core.dao.HibernateGenericDao
 * @see UserManagerNativeVersion
 */
public class UserManager extends HibernateEntityDao<User> {
 // ....CRUD以外的其它商業(yè)方法

這里面出現(xiàn)了CRUD看完了才知道就是增加、讀取、更新和刪除幾個(gè)單詞的首字母簡寫 即Create,Read,Update,Delete四個(gè)單詞的縮寫。是數(shù)據(jù)庫操作的基本功,往往是程序員的入門級(jí)課程之一,也是最無聊的工作,在ROR中,這種工作被簡化了好多,很多很牛的Java程序員也自己寫了機(jī)器人去完成這些工作,這里的HibernateEntityDao<User>
肯定就是機(jī)器人了.
    下面看機(jī)器人HibernateEntityDAO,查springside參考手冊(cè)知道它已存在默認(rèn)的CRUD函數(shù),子類只要用泛型語法聲明自己管理的Entity類型即可,如果你的Manager是簡單的CRUD類,沒有其他的商業(yè)方法,那就恭喜了,上面的代碼就是全部。
    SpringSide是如何對(duì)進(jìn)行Hibernate封裝的呢?看相關(guān)文檔如下:
SpringSide對(duì)Hibernate做了三層封裝:

第一層:HibernateGenericDao,基于spring的HibernateDaoSupport,但加入了分頁函數(shù)與各種Finder函數(shù),并使用泛型避免了返回值強(qiáng)制類型轉(zhuǎn)換。

第二層:HibernateEntityDao,基于HibernateGenericDao,用泛型聲明Dao所管理的Entity類,默認(rèn)擁有該entity的CRUD方法。

第三層:HibernateExtendDao,基于HibernateEntityDao,主要擴(kuò)展各種選擇性的功能。

關(guān)于三個(gè)類的詳細(xì)注解請(qǐng)看JavaDoc,大致描述如下:

1 HibernateGenericDao
   在Spring HibernateDaoSupport基礎(chǔ)上封裝的DAO,功能如下:

   1.應(yīng)用泛型:使得find(), get() 這些函數(shù)不再返回Object,而是返回T,不再需要強(qiáng)制類型轉(zhuǎn)換。

   2.提供各種finder的簡便函數(shù)
      應(yīng)用了JDK5可變參數(shù)的hsql查詢函數(shù):List find(String hql, Object... values),支持find(hql),find(hql, param1); find(hql,param1,param2);find(hql,new Object[] {param1,param2}) 四種接口。

      簡單查詢的簡化函數(shù):findBy(Class entityClass,String name,Object value) ,findUniqueBy(Class entityClass,String name, Object value),findByLike(Class entityClass,String name,Object value)

   3.獲得設(shè)置好的Query和Criteria:createQuery(String hql,Object... values)  和 createCriteria(Class<T> entityClass,Criterion... criterions)

      Spring并沒有很好的接口封裝支持firstResult, maxResult, fetchsize,cache,cacheRegion 等多個(gè)查詢參數(shù),所以springside寧愿返回已設(shè)置好查詢條件的Query和Criteria,讓大家繼續(xù)剩下的參數(shù)設(shè)置,最后再執(zhí)行l(wèi)ist(),注意那幾個(gè)參數(shù)可以連續(xù)設(shè)置的,如:

createQuery(hql,param1).setFirstResult(10).setMaxResult(20).llist();
   4.分頁函數(shù):Page pagedQuery(Criteria criteria, int pageNo, int pageSize) 和Page pagedQuery(String hql, int pageNo, int pageSize, Object... args)

      Page是SpringSide自行封裝的一個(gè)典型Page類,pagedQuery與hibernate自身分頁查詢的差別是先運(yùn)行一次count,獲得符合條件的總記錄數(shù)。

      如果查詢不需要總記錄數(shù),用普通的hibernate API,加上setFirstResult(),setMaxResult()就解決,不需要pagedQuery()。

   5.判別對(duì)象屬性在數(shù)據(jù)庫中唯一的函數(shù):isUnique(Class<T> entityClass,Object entity,String names)。

2. HibernateEntityDao
    所有UserManager, ProductManager之類只管理一類對(duì)象的Manager類的基類,只需要在類定義處聲明Entity類型即可

public class BookManager extends HibernateEntityDao<Book> {
}
  通過<Book>的定義,避免了HibernateGenericDao類各方法中必有的Class entityClass參數(shù)。

  如果需要操作其他的Entity,比如BookManager可能需要處理Category(圖書目錄),可以注入CategoryManager。無需擔(dān)心事務(wù)的問題,JavaEE的默認(rèn)事務(wù)模型已能很好處理。

  如果沒有對(duì)應(yīng)的CategoryManager,或者各種原因不想注入的話,可以使用BookManager繼承自HibernateGenericDao的帶entityClass參數(shù)的函數(shù)來操作Category的增刪改,如Category category= this.get(Category.class, 1);

3. HibernateExtendDao
      此類演示SpringSide 所作的一些擴(kuò)展,大家可以按照自己的需要進(jìn)行修改和擴(kuò)展。

     1. 支持對(duì)象不能被直接刪除,只能設(shè)置狀態(tài)列為無效。
        接口UndeleteableEntityOperation,定義了要支持此功能必須實(shí)現(xiàn)的函數(shù)。

        可以有接口(UndeletableEntity)和annotation(@Undeletable)兩種形式來定義無效列,annotation列形式還可以定義標(biāo)識(shí)對(duì)象已刪除的狀態(tài)屬性的名稱,用接口則必須實(shí)現(xiàn)setStatus()接口,在里面操作實(shí)際的狀態(tài)屬性。

        兩種方式的異同見侵入,非侵入?Interface vs Annotation。

      2. 重載save(),在保存前先調(diào)用onValid() 函數(shù)
      3. 增加find(Map map) 接口
       默認(rèn)查找與map中全部條件相同的entity。

       條件的比較運(yùn)算符默認(rèn)為相同,用戶也可以為屬性名加上like_,largerthen_ 這樣的前綴,則使用相應(yīng)的運(yùn)算符作比較(未完成) 
第三眼 看web.UserAction.java,心想應(yīng)該和struts里的acition一樣,editpuls完后得到
/**
 * 用戶管理Controller.
 * <p/>
 * 繼承于StrutsEntityAction,不需編碼就擁有默認(rèn)的對(duì)User對(duì)象的CRUD響應(yīng)函數(shù). 如果想了解不繼承于EntityAction,自行編寫CRUD的寫法, 參考{@link UserActionNativeVersion}.
 *
 * @author calvin
 * @see org.springside.core.web.StrutsEntityAction
 * @see org.springside.core.web.StrutsAction
 * @see UserActionNativeVersion
 */
public class UserAction extends StrutsEntityAction<User, UserManager> {

 @SuppressWarnings("unused")
 private UserManager userManager;    //看到serviceContext.xml中面有userManager應(yīng)該是spring的注入

 public void setUserManager(UserManager userManager) {
  this.userManager = userManager;
 }

第四眼 看了web.xml、struts-config.xml、applicationContext.xml、dataAccessContext.xml、serviceContext.xml 五個(gè)配置文件。
接下來調(diào)試程序,用運(yùn)成功。