<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    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 閱讀(5454) 評(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è)置?
    主站蜘蛛池模板: 亚洲三级高清免费| 免费无码又爽又黄又刺激网站| 亚洲妇熟XXXX妇色黄| 国产成人亚洲精品狼色在线| 亚洲国产日韩在线观频| 成人亚洲网站www在线观看| 亚洲色偷偷色噜噜狠狠99| 91亚洲性爱在线视频| 亚洲国产人成在线观看| 亚洲三级视频在线观看| 亚洲大成色www永久网址| 亚洲中文字幕无码久久2020| 亚洲成a∨人片在无码2023| 亚洲丁香婷婷综合久久| 噜噜噜亚洲色成人网站| 永久免费观看黄网站| 毛片基地看看成人免费| 精品视频在线免费观看| 久久国产乱子伦免费精品| 四虎在线最新永久免费| 成年午夜视频免费观看视频| 日韩伦理片电影在线免费观看| 亚洲av无码天堂一区二区三区| 亚洲偷自拍拍综合网| 国产精品亚洲成在人线| 亚洲精品一卡2卡3卡三卡四卡| 亚洲国产精品日韩在线观看 | 无码日韩精品一区二区三区免费 | 国产av无码专区亚洲av毛片搜| 青青草国产免费国产是公开| 精品多毛少妇人妻AV免费久久| 久久精品国产免费| 国产香蕉免费精品视频| 国产日产成人免费视频在线观看| 亚洲国产人成中文幕一级二级| 久久久久久久久亚洲| 精品亚洲AV无码一区二区三区| 国产成人亚洲精品91专区高清 | 亚洲精品在线网站| 亚洲AV无码AV日韩AV网站| 一级有奶水毛片免费看|