近一年时间没有写blog了,由于各种忙——是时候更新一下了。
重新审视了一翻以前写的东西,发现问题不少,以 .net企业级架构实战之5——基于接口的访问层实现 为例,就一般的访问层对象而言,功能大致相同,每一个都存在Save(),Update(),Delete(),LoadFromId(),SearchByWhere()等功能,在DaoTemplate模板类已经实现泛型化的基础上,如此实现各个Dao实在冗余啰嗦。
每个Dao最大的差异,在于这一片断:
private const string TableName = "TB_USER_MAIN"; //表名
private const string PrimaryKey = "Id"; //主键
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);
}
/// 分页
/// </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>
(10, 1, "Id", false, "1=1");
(10, 1, "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>
<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>
<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中可以安放你需要植入事务拦截器的任何对象。
再次表示歉意!!