posts - 32, comments - 153, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          使用AOP實(shí)現(xiàn)類型安全的泛型DAO

          Posted on 2006-11-26 21:08 Zou Ang 閱讀(5442) 評(píng)論(8)  編輯  收藏 所屬分類:

          由于要求在項(xiàng)目中使用泛型的DAO,所以上網(wǎng)Google了一下,找到了IBM的一篇文章。文章講得不錯(cuò),但是有些地方不清楚,如果完全按照那篇文章可能還會(huì)遇到一些困難。所以寫了這篇文章,解釋如何在項(xiàng)目中加入泛型的DAO實(shí)現(xiàn)。

          首先是總的類關(guān)系的UML圖:

          然后是在配置文件中的關(guān)系圖:??

          其中,IStaffDao是我們自己定義的接口,這個(gè)接口類似:

          public ? interface ?IStaffDAO? extends ?GenericDao < Staff,?Integer > {?

          public ?List?listAll();?

          public ?Staff?getByLogonAndId(String?logon,?Integer?id);?

          // more??

          }
          ?

          ?

          GenericDao<T , PK extends Serilizable> 是泛型的 Dao 接口:

          /**
          ?*?2006-11-22
          ?*?范型DAO接口
          ?*?
          @author ?Zou?Ang
          ?*?Contact?<a?href?="mailto:richardeee@gmail.com">Zou?Ang</a>
          ?
          */

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

          ????
          /**
          ?????*?保存一個(gè)對(duì)象到數(shù)據(jù)庫(kù)
          ?????*?
          @param ?newInstance?需要保存的對(duì)象
          ?????*?
          @return
          ?????
          */

          ????PK?create(T?newInstance);
          ????
          /**
          ?????*?從數(shù)據(jù)庫(kù)讀取一個(gè)對(duì)象
          ?????*?
          @param ?id?主鍵
          ?????*?
          @return
          ?????
          */

          ????T?read(PK?id);
          ????
          ????
          /**
          ?????*?更新一個(gè)對(duì)象
          ?????*?
          @param ?transientObject?被更新的對(duì)象
          ?????
          */

          ????
          void ?update(T?transientObject);
          ????
          ????
          /**
          ?????*?刪除一個(gè)對(duì)象
          ?????*?
          @param ?transientObject?被刪除的對(duì)象
          ?????
          */

          ????
          void ?delete(T?transientObject);
          }

          GenericDaoHibernateImpl GenericDao 接口的泛型實(shí)現(xiàn) :


          /**
          ?*?2006-11-22
          ?*?范型DAO實(shí)現(xiàn)
          ?*?
          @author ?Zou?Ang
          ?*?Contact?<a?href?="mailto:richardeee@gmail.com">Zou?Ang</a>
          ?
          */

          public ? class ?GenericDaoHibernateImpl < T,PK? extends ?Serializable > ?
          ????
          extends ?HibernateDaoSupport?
          ????????
          implements ?GenericDao < T,?PK > ?,FinderExecutor {
          ????
          ????
          private ?Class < T > ?type;
          ????
          private ?FinderNamingStrategy?namingStrategy? = ? new ?SimpleFinderNamingStrategy();? // ?Default.?Can?override?in?config
          ???? private ?FinderArgumentTypeFactory?argumentTypeFactory? = ? new ?SimpleFinderArgumentTypeFactory();? // ?Default.?Can?override?in?config
          ????
          ????
          public ?GenericDaoHibernateImpl(Class < T > ?type) {
          ????????
          this .type? = ?type;
          ????}


          ????
          /* ?(non-Javadoc)
          ?????*?@see?com.gdnfha.atcs.common.service.dao.GenericDao#create(java.lang.Object)
          ?????
          */

          ????
          public ?PK?create(T?newInstance)? {
          ????????
          return ?(PK)getHibernateTemplate().save(newInstance);
          ????}


          ????
          /* ?(non-Javadoc)
          ?????*?@see?com.gdnfha.atcs.common.service.dao.GenericDao#delete(java.lang.Object)
          ?????
          */

          ????
          public ? void ?delete(T?transientObject)? {
          ????????getHibernateTemplate().delete(transientObject);
          ????}


          ????
          /* ?(non-Javadoc)
          ?????*?@see?com.gdnfha.atcs.common.service.dao.GenericDao#read(java.io.Serializable)
          ?????
          */

          ????
          public ?T?read(PK?id)? {
          ????????
          return ?(T)getHibernateTemplate().get(type,?id);
          ????}


          ????
          /* ?(non-Javadoc)
          ?????*?@see?com.gdnfha.atcs.common.service.dao.GenericDao#update(java.lang.Object)
          ?????
          */

          ????
          public ? void ?update(T?transientObject)? {
          ????????getHibernateTemplate().update(transientObject);
          ????}


          ????
          public ?List < T > ?executeFinder(Method?method,? final ?Object[]?queryArgs)
          ????
          {
          ????????
          final ?Query?namedQuery? = ?prepareQuery(method,?queryArgs);
          ????????
          return ?(List < T > )?namedQuery.list();
          ????}


          ????
          public ?Iterator < T > ?iterateFinder(Method?method,? final ?Object[]?queryArgs)
          ????
          {
          ????????
          final ?Query?namedQuery? = ?prepareQuery(method,?queryArgs);
          ????????
          return ?(Iterator < T > )?namedQuery.iterate();
          ????}

          ????
          ????
          private ?Query?prepareQuery(Method?method,?Object[]?queryArgs)
          ????
          {
          ????????
          final ?String?queryName? = ?getNamingStrategy().queryNameFromMethod(type,?method);
          ????????
          final ?Query?namedQuery? = ?getSession().getNamedQuery(queryName);
          ????????String[]?namedParameters?
          = ?namedQuery.getNamedParameters();
          ????????
          if (namedParameters.length == 0 )
          ????????
          {
          ????????????setPositionalParams(queryArgs,?namedQuery);
          ????????}
          ? else ? {
          ????????????setNamedParams(namedParameters,?queryArgs,?namedQuery);
          ????????}

          ????????
          return ?namedQuery;
          ????}


          ????
          private ? void ?setPositionalParams(Object[]?queryArgs,?Query?namedQuery)
          ????
          {
          ????????
          // ?Set?parameter.?Use?custom?Hibernate?Type?if?necessary
          ???????? if (queryArgs != null )
          ????????
          {
          ????????????
          for ( int ?i? = ? 0 ;?i? < ?queryArgs.length;?i ++ )
          ????????????
          {
          ????????????????Object?arg?
          = ?queryArgs[i];
          ????????????????Type?argType?
          = ?getArgumentTypeFactory().getArgumentType(arg);
          ????????????????
          if (argType? != ? null )
          ????????????????
          {
          ????????????????????namedQuery.setParameter(i,?arg,?argType);
          ????????????????}

          ????????????????
          else
          ????????????????
          {
          ????????????????????namedQuery.setParameter(i,?arg);
          ????????????????}

          ????????????}

          ????????}

          ????}


          ????
          private ? void ?setNamedParams(String[]?namedParameters,?Object[]?queryArgs,?Query?namedQuery)
          ????
          {
          ????????
          // ?Set?parameter.?Use?custom?Hibernate?Type?if?necessary
          ???????? if (queryArgs != null )
          ????????
          {
          ????????????
          for ( int ?i? = ? 0 ;?i? < ?queryArgs.length;?i ++ )
          ????????????
          {
          ????????????????Object?arg?
          = ?queryArgs[i];
          ????????????????Type?argType?
          = ?getArgumentTypeFactory().getArgumentType(arg);
          ????????????????
          if (argType? != ? null )
          ????????????????
          {
          ????????????????????namedQuery.setParameter(namedParameters[i],?arg,?argType);
          ????????????????}

          ????????????????
          else
          ????????????????
          {
          ????????????????????
          if (arg? instanceof ?Collection)? {
          ????????????????????????namedQuery.setParameterList(namedParameters[i],?(Collection)?arg);
          ????????????????????}

          ????????????????????
          else
          ????????????????????
          {
          ????????????????????????namedQuery.setParameter(namedParameters[i],?arg);
          ????????????????????}

          ????????????????}

          ????????????}

          ????????}

          ????}

          ????
          ????
          public ?FinderNamingStrategy?getNamingStrategy()
          ????
          {
          ????????
          return ?namingStrategy;
          ????}


          ????
          public ? void ?setNamingStrategy(FinderNamingStrategy?namingStrategy)
          ????
          {
          ????????
          this .namingStrategy? = ?namingStrategy;
          ????}


          ????
          public ?FinderArgumentTypeFactory?getArgumentTypeFactory()
          ????
          {
          ????????
          return ?argumentTypeFactory;
          ????}


          ????
          public ? void ?setArgumentTypeFactory(FinderArgumentTypeFactory?argumentTypeFactory)
          ????
          {
          ????????
          this .argumentTypeFactory? = ?argumentTypeFactory;
          ????}


          }


          FinderNamingStrategy 是查找方法的命名規(guī)范:

          public ? interface ?FinderNamingStrategy
          {
          ????
          public ?String?queryNameFromMethod(Class?findTargetType,?Method?finderMethod);
          }


          目前有兩個(gè)命名查找策略,使用的是

          Simple 的,也就是直接是 < 類型名 >.< 方法名 > 的形式。

          public ? class ?SimpleFinderNamingStrategy? implements ?FinderNamingStrategy
          {
          ????
          public ?String?queryNameFromMethod(Class?findTargetType,?Method?finderMethod)
          ????
          {
          ????????
          return ?findTargetType.getSimpleName()? + ? " . " ? + ?finderMethod.getName();
          ????}

          }

          FinderArgumentTypeFactory 目前還沒(méi)有什么作用,主要是返回自定義的 Hibernate 類型:

          ?

          public ? class ?SimpleFinderArgumentTypeFactory? implements ?FinderArgumentTypeFactory
          {
          ????
          public ?Type?getArgumentType(Object?arg)
          ????
          {
          // ????????if(arg?instanceof?Enum)
          // ????????{
          // ????????????return?getEnumType(arg.getClass());
          // ????????}
          // ????????else
          // ????????{
          ???????????? return ? null ;
          // ????????}
          ????}


          // ????private?Type?getEnumType(Class<??extends?Object>?argClass)
          // ????{
          // ????????Properties?p?=?new?Properties();
          // ????????p.setProperty("enumClassName",?argClass.getName());
          // ????????Type?enumType?=?TypeFactory.heuristicType("org.hibernate.demo.EnumUserType",?p);
          // ????????return?enumType;
          // ????}
          }

          ?

          FinderIntroductionAdvisor FinderIntroductionInterceptor:

          ?

          public ? class ?FinderIntroductionAdvisor? extends ?DefaultIntroductionAdvisor
          {
          ????
          public ?FinderIntroductionAdvisor()
          ????
          {
          ????????
          super ( new ?FinderIntroductionInterceptor());
          ????}

          }

          public ? class ?FinderIntroductionInterceptor? implements ?IntroductionInterceptor
          {

          ????
          public ?Object?invoke(MethodInvocation?methodInvocation)? throws ?Throwable
          ????
          {

          ????????FinderExecutor?executor?
          = ?(FinderExecutor)?methodInvocation.getThis();

          ????????String?methodName?
          = ?methodInvocation.getMethod().getName();
          ????????
          if (methodName.startsWith( " get " )? || ?methodName.startsWith( " list " ))
          ????????
          {
          ????????????Object[]?arguments?
          = ?methodInvocation.getArguments();
          ????????????
          return ?executor.executeFinder(methodInvocation.getMethod(),?arguments);
          ????????}

          ????????
          else ? if (methodName.startsWith( " iterate " ))
          ????????
          {
          ????????????Object[]?arguments?
          = ?methodInvocation.getArguments();
          ????????????
          return ?executor.iterateFinder(methodInvocation.getMethod(),?arguments);
          ????????}

          // ????????else?if(methodName.startsWith("scroll"))
          // ????????{
          // ????????????Object[]?arguments?=?methodInvocation.getArguments();
          // ????????????return?executor.scrollFinder(methodInvocation.getMethod(),?arguments);
          // ????????}
          ???????? else
          ????????
          {
          ????????????
          return ?methodInvocation.proceed();
          ????????}

          ????}


          ????
          public ? boolean ?implementsInterface(Class?intf)
          ????
          {
          ????????
          return ?intf.isInterface()? && ?FinderExecutor. class .isAssignableFrom(intf);
          ????}

          }


          然后就到了配置文件了:

          ?????? <!-- ??Start?:范型DAO配置?? --> ?
          ?????
          < ?bean?? id? ="abstractDaoTarget" ?
          ????????class?
          ="com.gdnfha.atcs.common.service.dao.hibernate.GenericDaoHibernateImpl" ?
          ????????abstract?
          ="true" ? > ?
          ?????????
          < ?property?? name? ="sessionFactory" ? > ?
          ?????????????
          < ?ref?? local? ="sessionFactory" ??? /> ?
          ?????????
          </ ?property? > ?
          ?????????
          < ?property?? name? ="namingStrategy" ? > ?
          ?????????????
          < ?ref?? bean? ="simpleFinderNamingStratrgy" ??? /> ?
          ?????????
          </ ?property? > ?
          ?????
          </ ?bean? > ?
          ?
          ?????
          < ?bean?? id? ="abstractDao" ?
          ????????class?
          ="org.springframework.aop.framework.ProxyFactoryBean" ?
          ????????abstract?
          ="true" ? > ?
          ?????????
          < ?property?? name? ="interceptorNames" ? > ?
          ?????????????
          < ?list? > ?
          ?????????????????
          < ?value? > ?finderIntroductionAdvisor? </ ?value? > ?
          ?????????????
          </ ?list? > ?
          ?????????
          </ ?property? > ?
          ?????
          </ ?bean? > ?
          ?
          ?????
          < ?bean?? id? ="finderIntroductionAdvisor" ?
          ????????class?
          ="com.gdnfha.atcs.common.service.dao.finder.FinderIntroductionAdvisor" ??? /> ?
          ?
          ?????
          < ?bean?? id? ="namingStrategy" ?
          ????????class?
          ="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" ? > ?
          ?????????
          < ?property?? name? ="staticField" ? > ?
          ?????????????
          < ?value? > ?org.hibernate.cfg.ImprovedNamingStrategy.INSTANCE? </ ?value? > ?
          ?????????
          </ ?property? > ?
          ?????
          </ ?bean? > ?
          ?
          ?????
          < ?bean?? id? ="extendedFinderNamingStrategy" ?
          ????????class?
          ="com.gdnfha.atcs.common.service.dao.finder.impl.ExtendedFinderNamingStrategy" ??? /> ?
          ????????
          ?????
          < ?bean?? id? ="simpleFinderNamingStratrgy" ??class? ="com.gdnfha.atcs.common.service.dao.finder.impl.SimpleFinderNamingStrategy" ? /> ?
          ??????
          <!-- ??End:?范型DAO配置?? --> ?
          ?
          ?????
          <!-- ??Start:?測(cè)試范型DAO?? --> ?
          ??
          ?????
          < ?bean?? id? ="staffDao" ??parent? ="abstractDao" ? > ?
          ?????????
          < ?property?? name? ="proxyInterfaces" ? > ?
          ?????????????
          < ?value? > ?com.gdnfha.atcs.maintain.service.dao.IStaffDAO????? </ ?value? > ?
          ?????????
          </ ?property? > ?
          ?????????
          < ?property?? name? ="target" ? > ?
          ?????????????
          < ?bean?? parent? ="abstractDaoTarget" ? > ?
          ?????????????????
          < ?constructor-arg? > ?
          ?????????????????????
          < ?value? > ?com.gdnfha.atcs.common.pojo.Staff? </ ?value? > ?
          ?????????????????
          </ ?constructor-arg? > ?
          ?????????????
          </ ?bean? > ?
          ?????????
          </ ?property? > ?
          ?????
          </ ?bean? > ?
          ?
          ?????
          <!-- ???End:測(cè)試范型DAO?? --> ?


          還要在Staff.hbm.xml中配置:

          < ?query?? name? ="Staff.getByLogonAndId" ? > ??
          ????????
          <![CDATA[ ?select?s?from?Staff?s?where?s.staffLogon?=???and?s.staffId?=???? ]]> ??
          </ ?query? > ?

          這里要特別注意<query></query>這個(gè)要寫在<class></class>的外面,否則會(huì)提示Mapping Exception:No Named Query

          好了,大公告成了!現(xiàn)在可以跟以前一樣使用

          appContext.getBean("staffDao"); 這樣進(jìn)行測(cè)試了

          staffDao.read(new Integer(1));

          staffDao.getByLogonAndId("abc",new Integer(2));


          評(píng)論

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-11-27 10:18 by Nicholas Ding
          原文的翻譯在 http://www.nirvanastudio.org/java/dont-repeat-the-dao.html

          摟主有沒(méi)有道德啊,抄別人的代碼還不忘把Author改成自己。

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-11-27 11:03 by Zou Ang[匿名]
          這篇文章是我寫的啊,圖也是我畫的啊,我用在項(xiàng)目里,叫別人有問(wèn)題來(lái)找我有什么不對(duì)

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-11-27 11:20 by
          哇~~~你們組也搞這個(gè)??不會(huì)延期得更厲害么?

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-11-27 11:52 by Zou Ang[匿名]
          好,為了尊重他人的勞動(dòng)成果,我把原作者加上

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-12-07 15:52 by zhongbai
          按以上的配置,事務(wù)要怎樣處理呢?
          按常規(guī)方法配置事務(wù)后,引介攔截器 FinderIntroductionInterceptor 會(huì)出錯(cuò),因?yàn)榕渲檬聞?wù)后 攔截到的已不是 FinderExecutor 接口的實(shí)現(xiàn)了,而是其包裝器,所以會(huì)報(bào)告錯(cuò)誤,不知道你們是怎么處理的呀??

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-12-08 06:24 by Zou Ang
          要在DAO層加上事務(wù)么?為什么不直接在Business Logic層加事務(wù)呢

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2006-12-08 19:32 by zhongbai
          是的,正如你所說(shuō),我把事務(wù)配置在了業(yè)務(wù)邏輯層,但是Spring啟動(dòng)時(shí)報(bào)告數(shù)據(jù)源Bean循環(huán)引用的問(wèn)題,不知道您在使用中是否遇到該問(wèn)題?是如何解決的呢?
          http://www.javaeye.com/topic/38166 有我對(duì)該問(wèn)題的詳細(xì)描述,希望你能不吝指點(diǎn)。

          # re: 使用AOP實(shí)現(xiàn)類型安全的泛型DAO  回復(fù)  更多評(píng)論   

          2008-04-03 10:27 by 海狼
          請(qǐng)問(wèn)大俠們,使用這個(gè)Dao,的那個(gè)方法實(shí)現(xiàn)分頁(yè)呀?在映射文件里面怎么設(shè)置?
          主站蜘蛛池模板: 和田县| 丹棱县| 五寨县| 托里县| 上杭县| 江口县| 独山县| 靖安县| 桐乡市| 廊坊市| 察哈| 措美县| 罗山县| 南昌县| 铜川市| 乐安县| 通海县| 孙吴县| 纳雍县| 广宗县| 勃利县| 惠水县| 区。| 稷山县| 宣城市| 东莞市| 永福县| 蓝田县| 和田县| 伊通| 承德市| 新源县| 大姚县| 永宁县| 贵州省| 香港| 克什克腾旗| 芜湖市| 房产| 南漳县| 徐汇区|