代码改变世界

Spring.net Dao的改进——使用属性类描述实体数据源

2009-10-23 16:44  莫耶  阅读(3001)  评论(9编辑  收藏  举报

近一年时间没有写blog了,由于各种忙——是时候更新一下了。

重新审视了一翻以前写的东西,发现问题不少,以 .net企业级架构实战之5——基于接口的访问层实现 为例,就一般的访问层对象而言,功能大致相同,每一个都存在Save(),Update(),Delete(),LoadFromId(),SearchByWhere()等功能,在DaoTemplate模板类已经实现泛型化的基础上,如此实现各个Dao实在冗余啰嗦。

每个Dao最大的差异,在于这一片断:

private const string TableName = "TB_USER_MAIN";           //表名
private const string PrimaryKey = "Id";                 //主键

 它们被这样使用:

/// <summary>
        
/// 分页
        
/// </summary>

        public DataTable GetPagerByStoreProc(string Columns,int pageSize, int pageIdx
            , 
string OrderColumn, bool orderType, string condition)
        
{
            
return DaoTemplate.GetPageEntitesByStoredProc
                (TableName, PrimaryKey, Columns, OrderColumn, pageSize, pageIdx, orderType, condition);
        }

 

说白了,Dao除了名字不一样,最大差异体现在 对应实体数据源信息上。实体数据源信息的差异,应该由实体来描述,而不是Dao, "omg,多么糟糕的设计!"。

改过来,为实体创建一个描述数据源信息的属性类,以元标记的方式标注,其余的工作,一个泛型的Dao足矣。

  • 描述数据源信息的TableInfoAttribute类:
TableInfoAttribute.cs
  •  设计这个泛型类Dao的接口,如IbandDaoSpring:
interface IbandDaoSpring
  •  找个实体类,给它加上TableInfo数据源信息元标记:
    TableInfo attribute on class
找个页面,测试一下:
DataTable dt =            BandDaoSpring.GetPagerByStoreProc<MEDIAAlbumRecommand>
            (
101"Id"false"1=1");


终于告别一大堆名字不一样的Dao了,统统删掉,这样能让配置文件buessineConfig.xml瘦下来不少,看着舒服。也许看官您会问:如果对于特定的实体要实现事务呢 ——确实,这个Dao只是把通用的部分提炼出来,如果是个性化的操作,还是要单独创建操作类的。比如事务,创建一个基于接口实现的类,加上Transaction元标记,最后,在配置文件中指派Spring.net的某个AOP Proxy对象,让它来帮助你实现事务(在此向以前读过在下糙文的读者致歉,在spring.net中,Transaction元标记只是标注事务的范围,而具体的实现是基于 接口 及 接口切面代理对象 共同完成的

  • 来个小示例吧,先从配置文件说起,在applicationContext.xml配置了这样一个拦截器:
<!--事务拦截器-->
    
<object id="TransactionInterceptor"             type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
        
<property name="TransactionManager" ref="HibernateTransactionManager" />
        
<property name="TransactionAttributeSource">
            
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data" />
        
</property>
    
</object>
  •  创建一个接口,描述某个有事务的类:
ImediaInterface
  •  实现它,标注声明性事务:
ImediaInterface实现
  •  在配置文件中,声明这个MediaTransaction对象,同时使用 ObjectNameAutoProxyCreator 代理来负责为它植入事务监听:
<!--事务-->
        
<object id="MediaTransaction" type="woodigg.DAO.MediaTransaction,woodigg.DAO" autowire="byName" />
        
<object name="autoProxyCreator"
                    type
="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
              
<property name="InterceptorNames" value="TransactionInterceptor"/>
              
<property name="ObjectNames">
                  
<list>                
                      
<idref local="MediaTransaction"/>
                  
</list>
              
</property>
        
</object>

       list中可以安放你需要植入事务拦截器的任何对象。

再次表示歉意!!