风继续吹----对一些ORM框架的使用心得(2)

如今到处的谈论着OOP,我想这个世界原本是很复杂的!
我们把职责单一到一个类去,维护一个类固然简单了,但是随着而来的关系却很让人头痛.

Hibernate是一个优秀的ORM工具.可以让这个框架为你做很多事.他们说可以把对象到数据库的映射工作量大大降低,实体之间的关系可以非常简单地进行配置.

但是我发现正如<<Joel说软件>>,被包装和抽象的东西约多,我们的应对意外的能力就约低了.

在hibernate的配置文件了,如果你要配置一个组有很多用户.可能config如下:

 <bag name="Users" table="OrgUsers" lazy="false" inverse="false"  >
            
<key column="Org_ID" />
            
<many-to-many class="QPG.Support.Data.User, Support.Data" column="User_ID" />
          
</bag>
          
<bag name="ACL" table="AccessRights" lazy="true">
             
<key column="Org_ID" />
             
<one-to-many class="QPG.Support.Data.AccessToResource, Support.Data"  />
              
</bag>

随着业务的发展,将来很可能就比较多事情了....

在我们的事件中,总结了一个集中处理一对多的思想:
1) 把关系集中到一个表,用Catalog区分是什么关系,比如GroupUsers就是一个组到多个用户的那种关系.
2) 这个关系实体数据就由hibernate替我们自动保存了;
3) 使用OneToMany<T1,T2>来获取关系数据,比如new OneToMany<Group,User>(theGroup,theUserArray)

下面就看看我们的通用DAO吧:



namespace QPG.Support.DataAccessService{
    
using System;
    
using System.Collections;
    
using QPG.Support.Data;
    
using Castle.Services.Transaction;
    
using Castle.Facilities.NHibernateIntegration;
    
using NHibernate;
    
public class DAO<T> where T : BasicData {
        
protected readonly ISessionManager _sessManager;
        
protected  NHibernateGenericDao _dao;
        
public DAO(ISessionManager sm, string dbtag)
        
{
            _sessManager
=sm;
            _dao 
= new NHibernateGenericDao(sm);
            _dao.SessionFactoryAlias 
= dbtag;
        }

        
public DAO(ISessionManager sm)
        
{
            _sessManager 
= sm;
            _dao 
= new NHibernateGenericDao(sm);
            _dao.SessionFactoryAlias 
= GLOBAL.BASIC_DB_TAG;
        }


        
public T[] getEntites(string wherehql) {

            Array temp 
= _dao.FindAllWithCustomQuery("from " + typeof(T) + " where " + wherehql);
            
if (temp == null || temp.Length == 0return new T[0];
            T[] rt 
= new T[temp.Length];
            temp.CopyTo(rt,
0);
            
return rt;
        }

        
public T[] getEntites(IQuery q)// 危险,小心使用,用于从关系表中返回对应实体
        {
             IList list 
= q.List();
            T[] rt 
= new T[list.Count];
            list.CopyTo(rt, 
0);
            
return rt;
      
        }

        
public T[] getEntites(ICriteria criteria)// 危险,小心使用,用于从关系表中返回对应实体
        {
            IList list 
= criteria.List();
            T[] rt 
= new T[list.Count];
            list.CopyTo(rt, 
0);
            
return rt;

        }


        
public T getEntityByID(string id)
        
{
                  
return _dao.FindById(typeof(T),id)as T;
        }

        
public T getEntityByCode(string code)
        
{
            
return getEntites("IndexCode='" + code + "'")[0];
        }

        
public T getEntityLikedCode(string code)
        
{
            
return getEntites("IndexCode like '" + code + "%'")[0];
        }

        
public T[] findAll()
        
{
            
return _dao.FindAll(typeof(T)) as T[];
        }

  
        [Transaction]
        
public virtual void save(T data) {
              _dao.Save(data);
        }

        [Transaction]
        
public virtual void save(T[] data) {
          
foreach(T r in data)
                _dao.Save(r);
        }

        [Transaction]
        
public virtual void delete(T entity) {
             _dao.Delete(entity);
        }

        [Transaction]
        
public virtual void deleteAll() {
         _dao.DeleteAll(
typeof(T));//如果存在关系,这个操作就会发生异常!
        }


        [Transaction]
        
public  virtual void saveOneToManyData< T2>(string catalog, OneToMany<T, T2> rel,
             DAO
<OneToManyData> oneToManyDao,
            ISessionManager sessManager, 
string dbTag)
       
            where T2 : BasicData
        
{
            
using (NHibernate.ISession s = sessManager.OpenSession(dbTag))
            
{
                OneToManyData[] old 
= oneToManyDao.getEntites("FromID='" + rel.Master.ID + "'");
                
foreach (OneToManyData d in old) oneToManyDao.delete(d);
                s.Flush();
                
foreach (T2 r in rel.Assistants)
                
{
                    OneToManyData data 
= new OneToManyData();
                    data.Catalog 
= catalog;
                    data.FromID 
= rel.Master.ID;
                    data.ToID 
= r.ID;
                    oneToManyDao.save(data);
                }

                s.Flush();
            }


        }

        [Transaction]
        
public virtual void deleteOneToManyData<T2>(string catalog, string mid,
             DAO
<OneToManyData> oneToManyDao,
            ISessionManager sessManager, 
string dbTag)
            where T2 : IndexData
        
{
            
            
using (NHibernate.ISession s = sessManager.OpenSession(GLOBAL.BASIC_DB_TAG))
            
{
                
string hql = "Catalog='" + catalog + "' and " + "FromID='" + mid + "'";
                OneToManyData[] data 
= oneToManyDao.getEntites(hql);
                
foreach (OneToManyData d in data) oneToManyDao.delete(d);
                s.Flush();

            }

        }

        [Transaction(TransactionMode.NotSupported)]
        
public virtual OneToMany<T, T2> loadOneToMany<T2>(string catalog, string master_id, 
            DAO
<T2> sdao, DAO<OneToManyData> oneToManyDao,
             ISessionManager sessManager, 
string dbTag)
           
            where T2 : IndexData
        
{
            OneToMany
<T, T2> rel = null;
            
string[] wantIDs = null;
            ICriteria c;
            
using (NHibernate.ISession s = sessManager.OpenSession(GLOBAL.BASIC_DB_TAG))
            
{
                c 
= s.CreateCriteria(typeof(OneToManyData));
                c.Add(
new NHibernate.Expression.EqExpression("Catalog", catalog));
                c.Add(
new NHibernate.Expression.EqExpression("FromID", master_id));
                OneToManyData[] many 
= oneToManyDao.getEntites(c);
                wantIDs 
= new string[many.Length];
                
for (int i = 0; i < many.Length; i++) wantIDs[i] = many[i].ToID;
            }

            
using (NHibernate.ISession s = sessManager.OpenSession(dbTag))
            
{

                T root 
= this.getEntityByID(master_id);
                   
                c 
= s.CreateCriteria(typeof(T2));
                c.Add(
new NHibernate.Expression.InExpression("ID", wantIDs));
                rel 
= new OneToMany<T, T2>(root, sdao.getEntites(c));
            }

            
return rel;
        }

    
    }

}

注意:BasicData里只有ID这个所有实体都要的属性而已.

alex 4-10





 

posted @ 2006-04-10 18:17  成为-行动-拥有(BeDoHave)  阅读(3439)  评论(5编辑  收藏  举报