邊城愚人

          如果我不在邊城,我一定是在前往邊城的路上。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            31 隨筆 :: 0 文章 :: 96 評論 :: 0 Trackbacks

          當你偶然路過這里時,我假定你已經很明白 java 中范型和 DAO 模式了。當然,我也會順便嘮叨幾句范型和 DAO 模式,只是它們不會這篇隨筆的重點。我早先在 DW 上看到一篇蠻不錯的文章 不要重復 DAOHibernate Spring AOP 構建泛型類型安全的 DAO ,它也促使我在一個實驗工程中使用了范型化的 DAO 模式。前幾天看到的另一篇文章 Generic Data Access Objects 使我重新想起了這檔事。以前的代碼不可追,索性就重做了一個 sample 實現范型化的 DAO 。坦白的講,和上面的兩篇文章相比,這篇隨筆并沒有太多新內容,如果你愿意的話,你可以只看上面的兩篇文章而關掉這個頁面。

          先說說范型。自從 java5 引入范型后,它就成為我代碼中不可少的一部分。在沒有范型以前,強制轉換充斥于文件的各個角落,不單代碼不易于閱讀,時不時的會出現轉換異常。就像你所經歷的,對于集合類中的對象,如果顯示聲明的話,安全性和閱讀性都大大提高。總之啦,范型是個很有用的東西。

          ?????? 再說說 DAO 模式。 Java EE 中,最經典的架構模式就是三層架構或多層架構。而數據持久化層,流行的就是 DAO 模式。盡管很多人批評這種 貧血模型 OO ,但使用上的方便使得 DAO 模式很受程序員喜愛。想一想 Spring 框架吧,支持 DAO 模式的典型框架,數據與操作的分離,使得 IOC AOP 等技術靈活的運轉起來。說到底,理論和實踐并不是完全統一的,為了滿足實際的需要,有時不得不做些折衷。

          好了,該說說我做的一個小例子。其實范型化的 DAO 就是給出一個抽象的 DAO 及其實現,實現的內容就是基本的 CRUD 操作。閑言少敘,開始我的代碼。

          范型的 DAO 接口,包含基本的 CRUD 操作。 GenericDAO 的實現,通過 Spring 模板實現了 CRUD 操作。

          import ?java.util. * ;
          import ?java.io. * ;

          public ? interface ?GenericDAO < T,?PK? extends ?Serializable > ? {

          ????T?findById(PK?id
          );

          ????List
          < T > ?findAll();

          ????
          void ?insert(T?entity);
          ????
          ????
          void ?update(T?entity);

          ????
          void ?delete(T?entity);
          }
          ??????
          ?package?org.prague.dao.hibernate;

          import?java.util.*;
          import?java.io.*;
          import?org.hibernate.Session;
          import?org.hibernate.SessionFactory;
          import?org.springframework.orm.hibernate3.HibernateTemplate;
          import?org.prague.dao.GenericDAO;
          import?java.lang.reflect.*;

          public?abstract?class?GenericHibernateDAO<T,?PK?extends?Serializable>
          ????????
          implements?GenericDAO<T,?PK>?{

          ????
          private?HibernateTemplate?hibernateTemplate;
          ????
          private?Class<T>?type;
          ????
          ????
          public?GenericHibernateDAO(){
          ????????
          this.type?=?(Class<T>)((ParameterizedType)(this.getClass().getGenericSuperclass()))
          ????????????????????????????.getActualTypeArguments()[
          0];
          ????}

          ????
          ????
          public?void?setSessionFactory(SessionFactory?sessionFactory){
          ????????
          this.hibernateTemplate?=?new?HibernateTemplate(sessionFactory);
          ????}

          ????
          ????
          public?void?delete(T?entity)?{
          ????????
          this.hibernateTemplate.delete(entity);
          ????}

          ????
          ????

          ????
          public?List<T>?findAll()?{
          ????????String?hql?
          =?"from?"+this.type.getSimpleName();
          ????????
          return?(List<T>)this.hibernateTemplate.find(hql);
          ????}


          ????
          public?T?findById(PK?id)?{
          ????????
          return?(T)this.hibernateTemplate.get(type,?id);
          ????}


          ????
          public?void?insert(T?entity)?{
          ????????
          this.hibernateTemplate.save(entity);
          ????}


          ????
          public?void?update(T?entity)?{
          ????????
          this.hibernateTemplate.update(entity);
          ????}

          ????
          ????
          protected?Session?getSession(){
          ????????
          return?this.hibernateTemplate.getSessionFactory().getCurrentSession();
          ????}

          ????
          ????
          protected?HibernateTemplate?getHibernateTemplate(){
          ????????
          return?this.hibernateTemplate;
          ????}

          ????
          }
          ??????

          如果不用Spring的話,Hibernate也能輕松的實現這些操作。但坦白的講,這些操作并不實用。對于不同的實體,可能不會調用這些操作或是調用的操作不完全相同。比如說,對于查詢數據表中的數據列表,可能的情況是要求查詢條件中按照某些字段排序。如果想給出一個通用的實現方法,接口中不可避免的要包含查詢條件,比如說包含一個Hibernate中的條件查詢對象。但這樣話,就需要在Service層構造查詢條件,還不如直接寫個方法來的實在。
          ???

          下面就是一個具體的DAO及實現。

          import?org.prague.domain.*;

          public?interface?AccountDAO?extends?GenericDAO<Account,Long>{
          ????
          public?Account?findByNameAndPwd(String?name,String?pwd);
          }


          package?org.prague.dao.hibernate;

          import?java.util.List;

          import?org.prague.dao.AccountDAO;
          import?org.prague.domain.Account;
          import?org.springframework.orm.hibernate3.HibernateCallback;
          import?org.springframework.orm.hibernate3.HibernateTemplate;

          public?class?AccountHibernateDAO?extends?GenericHibernateDAO<Account,Long>?implements
          ????????AccountDAO?
          {

          ????
          public?Account?findByNameAndPwd(final?String?name,?final?String?pwd)?{
          ????????
          final?String?hql??=?"from?Account?where?name=:name?and?pwd=:pwd";
          ????????
          /*
          ????????List<Account>?list?=?(List<Account>)this.getHibernateTemplate().executeFind(new?HibernateCallback(){
          ????????????public?Object?doInHibernate(Session?s)?throws?HibernateException,?SQLException?{
          ????????????????return?s.createQuery(hql).setString("name",?name).setString("pwd",?pwd).list();
          ????????????}
          ????????});
          ????????
          */

          ????????List
          <Account>?list?=?(List<Account>)this.getHibernateTemplate().findByNamedParam(hql,?
          ????????????????
          new?String[]{"name","pwd"},?new?String[]{name,pwd});
          ????????
          if(list!=null?&&?!list.isEmpty()){
          ????????????
          return?list.get(0);
          ????????}

          ????????
          return?null;
          ????}

          }

          ???????當然少不了實體bean了,盡管它很簡單。

          package?org.prague.domain;

          import?java.io.Serializable;

          public?abstract?class?AbstractDomain<PK?extends?Serializable>{
          ????
          protected?PK?id;

          ????
          ????
          public?PK?getId()?{
          ????????
          return?id;
          ????}


          ????
          public?void?setId(PK?id)?{
          ????????
          this.id?=?id;
          ????}


          }


          package?org.prague.domain;

          public?class?Account?extends?AbstractDomain<Long>{
          ????
          private?String?name;
          ????
          private?String?pwd;
          ????
          ????
          public?String?getName()?{
          ????????
          return?name;
          ????}

          ????
          public?void?setName(String?name)?{
          ????????
          this.name?=?name;
          ????}

          ????
          public?String?getPwd()?{
          ????????
          return?pwd;
          ????}

          ????
          public?void?setPwd(String?pwd)?{
          ????????
          this.pwd?=?pwd;
          ????}

          ????@Override
          ????
          public?String?toString()?{
          ????????
          return?"Account:?id="+this.id+"?name="+this.name+"?pwd="+this.pwd+"\n";
          ????}

          ????
          }

          ???????想要程序運行起來,還需要配置文件的作用,這里列出Account對應的Hibernate映射文件和Spring配置文件。由于該Sample沒有Service層的概念,因此DAO需要聲明性事務的作用。

          <?xml?version='1.0'?encoding='UTF-8'?>
          <!DOCTYPE?hibernate-mapping?PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"?
          ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >

          <hibernate-mapping?package="org.prague.domain">
          ????
          <class?name="Account"?table="Account">
          ????????
          <id?name="id"?column="id"?type="java.lang.Long">
          ????????????
          <generator?class="identity"></generator>
          ????????
          </id>
          ????????
          <property?name="name"?column="name"></property>
          ????????
          <property?name="pwd"?column="pwd"></property>
          ????
          </class>
          </hibernate-mapping>

          ?

          <?xml?version="1.0"?encoding="UTF-8"?>
          <!DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?"http://www.springframework.org/dtd/spring-beans.dtd">
          <beans?default-lazy-init="true">

          ????
          <bean?id="sessionFactory"
          ????????class
          ="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
          ????????
          <property?name="configLocation">
          ????????????
          <value>classpath:hibernate.cfg.xml</value>
          ????????
          </property>
          ????
          </bean>

          ????
          <bean?name="transactionManager"
          ????????class
          ="org.springframework.orm.hibernate3.HibernateTransactionManager">
          ????????
          <property?name="sessionFactory">
          ????????????
          <ref?bean="sessionFactory"?/>
          ????????
          </property>
          ????
          </bean>

          ????
          <bean?id="baseTransactionProxy"
          ????????class
          ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
          ????????abstract
          ="true">
          ????????
          <property?name="transactionManager"?ref="transactionManager"?/>
          ????????
          <property?name="transactionAttributes">
          ????????????
          <props>
          ????????????????
          <prop?key="get*">PROPAGATION_REQUIRED,readOnly</prop>
          ????????????????
          <prop?key="*">PROPAGATION_REQUIRED</prop>
          ????????????
          </props>
          ????????
          </property>
          ????
          </bean>

          ????
          <bean?id="accountDAO"?parent="baseTransactionProxy">
          ????????
          <property?name="target">
          ????????????
          <bean?class="org.prague.dao.hibernate.AccountHibernateDAO">
          ????????????????
          <property?name="sessionFactory">
          ????????????????????
          <ref?bean="sessionFactory"?/>
          ????????????????
          </property>
          ????????????
          </bean>
          ????????
          </property>
          ????
          </bean>
          </beans>

          ???????再多說幾句吧。我以前寫過一個程序,在GenericDAO中給出了更多的方法,比如:

          public?List<T>?findListBy(String?expression);
          ????
          public?void?deleteBy(String?expression);
          ????
          public?void?updateBy(String?expression);

          ??? 我的想法和做法是不言而喻的。當時想通過在GenericDAO中聲明這樣的公共方法,簡化DAO中操作。那是我還不是很清楚Hibernate中的Creteria,就實現一個類似于Hibernate Creteria包的東西,通過在Service層中構造Creteria對象并得到一個拼接后的hql語句,然后調用上面的這幾個方法。通過上面的幾個方法,基本上滿足了DAO層的操作。但問題是,我不得不在Service層構建CreteriaService因此顯得臃腫異常,而DAO層就單薄得很。好好的想一想,這樣的結果不過是變相的將DAO層和Service層合并了。依我的想法,刻意的追求公共數據庫操作并不一定實用。即便是這個例子,如果不使用Hibernate框架,而是使用JDBCIbatis等,GenericDAO 中的方法是很難以通用的方式實現的。你不得不做的就是,每個繼承自 GenericDAODAO,都需要單獨的實現基本的CRUD操作。??

          ?

          posted on 2007-04-17 08:55 kafka0102 閱讀(3600) 評論(7)  編輯  收藏 所屬分類: Pattern

          評論

          # re: 要范型,要DAO,更要范型DAO[未登錄] 2007-04-17 09:07 Matthew
          朋友,把排版重搞一下吧!  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO 2007-04-17 09:20 kafka0102
          都要瘋掉了。昨晚第一遍寫的時候,直接在編輯器里做,結果添加代碼框出不來,IE死掉了。第二遍在word里寫,結果發表時不能連接服務器。好吧,一大早來做,結果從word到編輯器轉換時,格式都亂了。就這樣了,沒心情再改了。  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO 2007-04-17 10:32 CrossAge
          這樣子做,還有必要搞DAO這一層么?
          目的就是為了節省CRUD的代碼量?  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO 2007-04-18 08:40 開源英漢機器翻譯
          開源英漢機器翻譯C#.NET項目 www.liebiao.net

          我們邀請你 技術交流  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO[未登錄] 2007-04-27 13:20 Diego
          樓主,你博客上的的代碼折疊功能是用什么工具生成的?我問了好幾個人都不知道,我也想要這個功能  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO 2007-05-03 22:06 kafka0102
          發表文章時,代碼不是直接貼進去的,而是選擇編輯器中的“代碼”選項(應該在編輯菜單的最后一個位置),然后根據彈出來的對話框進行操作就行了。  回復  更多評論
            

          # re: 要范型,要DAO,更要范型DAO 2008-10-31 11:14 天山劍
          需要一個范型dao,

          上面的有問題,測試不了

          有沒有測通的

          請高手指點

          QQ:328152797

            回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 景宁| 鹤岗市| 乌海市| 皋兰县| 英山县| 临澧县| 迁安市| 炉霍县| 怀化市| 昌邑市| 辽源市| 乐东| 罗田县| 宣城市| 宜君县| 分宜县| 滦平县| 溆浦县| 德令哈市| 邵东县| 吴忠市| 太原市| 清流县| 湖口县| 通城县| 商丘市| 长寿区| 仁化县| 盐源县| 新龙县| 宣恩县| 巨野县| 当阳市| 汝阳县| 天台县| 乌拉特前旗| 武鸣县| 炉霍县| 海林市| 古交市| 青川县|