Spiga

NHibernate2.1新特性之Tuplizers

2009-08-02 22:01 by 李永京, 3905 visits, 网摘, 收藏, 编辑

NHibernate2.1新特性之Tuplizers

本节内容

  • 什么是Tuplizers
  • 典型实例
    • 1.Domain
    • 2.代理标记proxy marker
    • 3.DataProxy
    • 4.实体初始化
    • 5.重写PocoEntityTuplizer
    • 6.实体拦截
    • 7.EntityFactory
    • 8.映射
    • 9.测试
  • 结语

什么是Tuplizers

Tuplizers?这个单词在英文字典里没有解释,和元组(tuple)这个单词有点相似,在NHibernate中应该翻译为元组片断,Tuplizers只在映射中提供,所以叫元组片段映射比较合适。

我们平时一般使用Domain Entity,然后使用<class>来映射,对Domain Entity操作。在NHibernate中,对于Domain Entity的Entity Mode为POCO类型,这时对应的tuplizer知道通过其构造方法来创建一个POCO,再通过其属性访问器来访问POCO属性。

Tuplizers,其完整命名空间是NHibernate.Tuple.Tuplizer,它就是根据给定的NHibernate.EntityMode,来复现片断数据。如果给定的片断数据被认为其是一种数据结构,"tuplizer"就是一个知道如何创建这样的数据结构,以及如何给这个数据结构赋值的东西。

在NHibernate中有NHibernate.Tuple.Entity.IEntityTuplizer和NHibernate.Tuple.Component.IComponentTuplizer两个接口,IEntityTuplizer负责管理上面提到的实体的契约,而IComponentTuplizer则是针对组件的。

下面从NHibernate源码中摘取一个典型的例子来说明Tuplizer的用法。

典型实例

我想映射一个接口,对这个接口按照POCO实体模型进行持久化操作。首先想到应该可以New出来这个接口,使用工厂可以产生出来。在初始化这个接口的时候要重写一些NHibernate默认的POCO行为,在对这个接口赋值的时候拦截一些操作,记录下这个接口。获取接口时候同样也需要拦截。

1.Domain

public interface IUser
{
    int Id { get; set; }
    string Name { get; set; }
}

我们需要映射这个接口,但是NHibernate只会去映射类,我们怎么去改写代码让NHibernate可以像类那样去映射接口呢?这就是Tuplizers的功能。

2.代理标记proxy marker

由于这里是特殊需要,我对其这个代理做个标记,如果某个实体可以转换为这个代理标记接口就说明是我重写定义的Domain,

/// <summary>
/// 代理标记
/// 对象实例是代理的一个实例
/// </summary>
public interface IProxyMarker
{
    DataProxyHandler DataHandler { get; }
}

3.DataProxy

利用Castle的拦截器IInterceptor接口对这个代理数据进行拦截,例如在获取这个代理数据的时候,让NHibernate按照POCO那样去把其数据保存到一个字典中。

/// <summary>
/// 利用Castle的拦截器,代理数据DataProxy
/// </summary>
public sealed class DataProxyHandler:IInterceptor
{
    private readonly Dictionary<string, object> data = new Dictionary<string, object>(50);
    private readonly string entityName;

    public DataProxyHandler(string entityName, object id)
    {
        this.entityName = entityName;
        data["Id"] = id;
    }

    public string EntityName
    {
        get { return entityName; }
    }

    public IDictionary<string, object> Data
    {
        get { return data; }
    }

    public void Intercept(IInvocation invocation)
    {
        invocation.ReturnValue = null;
        string methodName = invocation.Method.Name;

        if ("get_DataHandler".Equals(methodName))
        {
            invocation.ReturnValue = this;
        }
        else if (methodName.StartsWith("set_"))
        {
            string propertyName = methodName.Substring(4);
            data[propertyName] = invocation.Arguments[0];
        }
        else if (methodName.StartsWith("get_"))
        {
            string propertyName = methodName.Substring(4);
            object value;
            data.TryGetValue(propertyName, out value);
            invocation.ReturnValue = value;
        }
        else if ("ToString".Equals(methodName))
        {
            invocation.ReturnValue = EntityName + "#" + data["Id"];
        }
        else if ("GetHashCode".Equals(methodName))
        {
            invocation.ReturnValue = GetHashCode();
        } 
    }
}

4.实体初始化

在映射文件中定义<tuplizers>映射,NHibernate提供的IInstantiator接口实现负责初始化实体实例,这里就是使用Castle.DynamicProxy.ProxyGenerator的public object CreateInterfaceProxyWithoutTarget(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, params Castle.Core.Interceptor.IInterceptor[] interceptors )方法创建一个接口代理。

/// <summary>
/// 利用NH2.1新特性Tuplizers提供的IInstantiator接口实现负责初始化实体/组件实例
/// </summary>
public class EntityInstantiator : IInstantiator
{
    private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
    private readonly Type t;

    public EntityInstantiator(Type entityType)
    {
        t = entityType;
    }

    public object Instantiate()
    {
        return Instantiate(null);
    }

    public object Instantiate(object id)
    {
        return
            proxyGenerator.CreateInterfaceProxyWithoutTarget(t, new[] { typeof(IProxyMarker), t }, new DataProxyHandler(t.FullName, id));
    }
    /// <summary>
    /// 判断是否实例化
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public bool IsInstance(object obj)
    {
        try
        {
            return t.IsInstanceOfType(obj);
        }
        catch (Exception e)
        {
            throw new Exception("could not get handle to entity-name as interface : " + e);
        }
    }
}

5.重写PocoEntityTuplizer

这才是我们真正自定义的Tuplizer,在映射中使用,重写NHibernate提供的POCO的PocoEntityTuplizer的初始化方法,返回上面实体初始化类完成的创建一个接口代理。

/// <summary>
/// 重写PocoEntityTuplizer
/// </summary>
public class EntityTuplizer : PocoEntityTuplizer
{
    public EntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) : base(entityMetamodel, mappedEntity) { }

    protected override IInstantiator BuildInstantiator(PersistentClass persistentClass)
    {
        return new EntityInstantiator(persistentClass.MappedClass);
    }
}

6.实体拦截

NHibernate可以利用NHibernate.IInterceptor实现拦截这个实体:可以去拦截我们创建一个System.Type代理将出现无法预测的值,在这里我仅仅返回上面定义的IProxyMarker标记数据的实体名称,对于其他类型的实体则返回空值。

/// <summary>
/// 利用NHibernate.IInterceptor对这个实体实现拦截
/// </summary>
public class EntityNameInterceptor : EmptyInterceptor
{
    public override string GetEntityName(object entity)
    {
        return ExtractEntityName(entity) ?? base.GetEntityName(entity);
    }

    private static string ExtractEntityName(object entity)
    {
        // Our custom Proxy instances actually bundle their appropriate entity name, 
        //so we simply extract it from there if this represents one of our proxies; otherwise, we return null 
        var pm = entity as IProxyMarker;
        if (pm != null)
        {
            var myHandler = pm.DataHandler;
            return myHandler.EntityName;
        }
        return null;
    } 
}

7.EntityFactory

我们创建一个实体工厂,所谓工厂就是New出来实体的一个制造工厂。我们可以var user = entityFactory.NewEntity<IUser>()这样初始化一个实体。

public class EntityFactory
{
    private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();

    public T NewEntity<T>()
    {
        Type t = typeof(T);
        return
            (T)
            proxyGenerator.CreateInterfaceProxyWithoutTarget(t, new[] { typeof(IProxyMarker), t },
                                                             new DataProxyHandler(t.FullName, 0));
    }
}

上面那些部分相当于一个前奏,为使用tuplizer做准备,我们可以在映射中使用我们自定义的Tuplizer了。

8.映射

这时需要映射这个接口了,使用<tuplizer>映射,这个映射有两个属性,分别为class和entity-mode。在这个例子中我在IUser中按照POCO实体模型自定义EntityTuplizer实现来映射。

<class name="IUser">
    <tuplizer class="EntityTuplizer" entity-mode="poco"/>
    <id name="Id">
        <generator class="hilo"/>
    </id>
    <property name="Name"/>
</class>

9.测试

测试一下我们的结果吧。分别创建、查询、删除操作吧。

[Test] 
public void UserCrud()
{
    object savedId;
    var user = entityFactory.NewEntity<IUser>();
    user.Name = "李永京";

    using (var session = sessions.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        savedId = session.Save(user);
        tx.Commit();
    }

    using (var session = sessions.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        user = session.Get<IUser>(savedId);
        Assert.That(user, Is.Not.Null);
        Assert.That(user.Name, Is.EqualTo("李永京"));
        session.Delete(user);
        tx.Commit();
    }

    using (var session = sessions.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        user = session.Get<IUser>(savedId);
        Assert.That(user, Is.Null);
        tx.Commit();
    }
}

测试结果:

第一个Session:创建对象

Tuplizers测试

第二个Session:查询、删除对象

Tuplizers测试

第三个Session:验证对象

Tuplizers测试

结语

由于NHibernate资料很少,所以我从源码中找到这个例子稍微说明下,大家对Tuplizer有什么好的想法可以回复讨论下咯,我想这个功能的扩展就是如果NHibernate Domain与WPF结合,我需要在所有Domain中实现INotifyPropertyChanged接口,就需要重新实现DataProxyHandler。

NHibernate Q&A

希望本文对你有所帮助!

4
0
(请您对文章做出评价)
« 上一篇:这就是条件?记教育制度
» 下一篇:NHibernate2.1新特性之EntityMode.Map
Add your comment

60 条回复

  1. #1楼 任力      2009-08-02 22:05
    沙发~~
    永京的NHibernate系列哦
      回复  引用  查看    
  2. #2楼 Jeffrey Zhao      2009-08-02 22:08
    高级话题了啊,强大。李兄弟是博客园NHibernate第一人,呵呵。
      回复  引用  查看    
  3. #3楼[楼主] 李永京      2009-08-02 22:16
    @任力
    恩,是的哦,好久没有冒泡了。
      回复  引用  查看    
  4. #4楼[楼主] 李永京      2009-08-02 22:19
    @Jeffrey Zhao
    不会吧,不过博客园使用NHibernate的人的确不怎么多,资料也是很少,这方面实在欠缺了点。
      回复  引用  查看    
  5. #5楼 James.Ying      2009-08-02 22:24
    最近也在看NHibernate,2.1版本中多了2个类库,谢谢大哥的文章,太精彩了,支持一下
      回复  引用  查看    
  6. #6楼[楼主] 李永京      2009-08-02 22:28
    @James.Ying
    Tuplizer类库的确不知干什么的,花了很长时间才决定写下总结的。
      回复  引用  查看    
  7. #7楼 Clingingboy      2009-08-02 22:29
    继续:) 希望你写的比java社区讨论的hibernate还要好.
      回复  引用  查看    
  8. #8楼[楼主] 李永京      2009-08-02 22:33
    @Clingingboy
    恩恩,继续努力
      回复  引用  查看    
  9. #9楼 温景良(Jason)      2009-08-02 22:34
    NHibernate学习的经典之处
      回复  引用  查看    
  10. #10楼 kiler      2009-08-02 22:36
    学习中。
      回复  引用  查看    
  11. #11楼 Jeffrey Zhao      2009-08-02 22:44
    引用李永京:
    @Jeffrey Zhao
    不会吧,不过博客园使用NHibernate的人的确不怎么多,资料也是很少,这方面实在欠缺了点。

    整个.NET社区又有多少人用NH,又有多少人会像你一样认真搞一个东西的啊。
      回复  引用  查看    
  12. #12楼[楼主] 李永京      2009-08-02 23:14
    引用Jeffrey Zhao:
    整个.NET社区又有多少人用NH,又有多少人会像你一样认真搞一个东西的啊。

    博客园中还是有几位NHibernate高手的,呵呵
      回复  引用  查看    
  13. #13楼 Jeffrey Zhao      2009-08-02 23:20
    @李永京
    他们的博客是哪些啊?
      回复  引用  查看    
  14. #14楼[楼主] 李永京      2009-08-02 23:26
    @Jeffrey Zhao
    到社区看看应该就知道了...
      回复  引用  查看    
  15. #15楼 Jeffrey Zhao      2009-08-02 23:32
    @李永京
    好吧,那么以后有NH的问题就来找你们了,啊哈。
      回复  引用  查看    
  16. #16楼 yeml[未注册用户]2009-08-03 00:18
    你也可以问我的
    我用过:DBEntry,国产的,后来发现不太好用,然后用 ibatis,因为还是要自己写sql,所以又换了, 接下来改Dlinq,后来发现要。net3.0还是多少才能用,继续换。终于用nhibernate。
    但是发现nhibernate初始化的时候要花4秒--10秒左右,所以后面的代码又改成直接使用ado.net

    唉,真是折腾。到后面无意间想到一个办法,就是添加一个splash 界面,在这个过程中进行初始化。可惜了那一大堆的DbConnection DBCommand代码了,唉
    话说回来,nhibernate的一般配置和使用我还是挺熟的。
      回复  引用    
  17. #17楼 feilng[未注册用户]2009-08-03 00:20
    面向对象的问题就是类型系统不灵活
      回复  引用    
  18. #18楼 yeml[未注册用户]2009-08-03 00:29
    [SoapMethod("Login")]

    public SoapEnvelope Login(SoapEnvelope e)
    {
    bool loginOk = true;
    string sessionId = "yeml";
    if (loginOk)
    {
    //HttpContext.Current.Session["username"] = "yemingliang";
    //sessionId = HttpContext.Current.Session.SessionID;
    }

    SoapEnvelope se = new SoapEnvelope();
    se.SetBodyObject("okay");
    XmlElement headers = se.CreateHeader();
    //Create a header to place the transaction token.
    XmlNode sessionIdHeader = se.CreateElement("SessionId");

    //Convert the binary token into Base64 to send it as Xml content.
    sessionIdHeader.InnerText = sessionId;

    //Add the header to the Headers.
    headers.AppendChild(sessionIdHeader);
    return se;
    }

    请问有没有SoapService比较熟悉的,这段代理一启用Session,就会出错,请问怎么启用Session啊?难道我只能用个static 的Hashtable吗
      回复  引用    
  19. #19楼 Clingingboy      2009-08-03 00:37
    NH就整个一Hibernate,网上Hibernate资料有多少就不用说了吧.所以不缺资料,只缺转化的c#代码:)
    这么好的框架,我们没理由去拒绝...
    貌似javaeye就是因为hibernate而成立的...
      回复  引用  查看    
  20. #20楼 Jeffrey Zhao      2009-08-03 00:48
    @yeml
    不知你的联系方式是什么,我可以怎么问你问题呢?
      回复  引用  查看    
  21. #21楼[楼主] 李永京      2009-08-03 07:49
    @yeml
    初始化Configuration的确慢了点,但是系统只初始化一次,这个性能应该可以接受的。
      回复  引用  查看    
  22. #22楼[楼主] 李永京      2009-08-03 07:54
    @feilng
    有这种意思,有时好像为了NHibernate而NHibernate,好像约束了我们
      回复  引用  查看    
  23. #23楼 侯垒      2009-08-03 08:18
    支持。
      回复  引用  查看    
  24. #24楼 八一精神      2009-08-03 08:28
    楼主有时间写一下,LINQ和NH结合的例子。
      回复  引用  查看    
  25. #25楼[楼主] 李永京      2009-08-03 08:33
    @八一精神
    NHibernate linq 1.0 RTM已经发布了啊,你可以先尝试下。对于linq使用贯的人,这个还是比较好用的
      回复  引用  查看    
  26. #26楼 oec2003      2009-08-03 08:33
    支持
      回复  引用  查看    
  27. #27楼 黑人[未注册用户]2009-08-03 08:45
    李的文章通俗易懂 很喜欢 初学者不看是一大损失啊
      回复  引用    
  28. #28楼 Jeffrey Zhao      2009-08-03 09:52
    @李永京
    我看了一下,的确Criteria API会有限制,还是HQL有前途。
      回复  引用  查看    
  29. #29楼[楼主] 李永京      2009-08-03 10:27
    @Jeffrey Zhao
    但是HQL实在难写,还不是强类型。。。
    http://code.google.com/p/nhlambdaextensions/ 这个可能是将来的趋势,
      回复  引用  查看    
  30. #30楼 Taven      2009-08-03 10:29
    标记一下
      回复  引用  查看    
  31. #31楼[楼主] 李永京      2009-08-03 10:31
    @黑人
    @oec2003
    @侯垒
    谢谢支持咯。
      回复  引用  查看    
  32. #32楼 Jeffrey Zhao      2009-08-03 10:56
    引用李永京:
    @Jeffrey Zhao
    但是HQL实在难写,还不是强类型。。。
    http://code.google.com/p/nhlambdaextensions/ 这个可能是将来的趋势,

    看上去这还是在增强Criteria API的易用性,但是这种做法会受到Criteria API的能力限制。
    我的意思是,HQL的能力比Criteria要强,所以LINQ Support的支持应该基于HQL而不是Criteria。
      回复  引用  查看    
  33. #33楼[楼主] 李永京      2009-08-03 11:04
    引用Jeffrey Zhao:
    引用李永京:
    @Jeffrey Zhao
    但是HQL实在难写,还不是强类型。。。
    http://code.google.com/p/nhlambdaextensions/ 这个可能是将来的趋势,

    看上去这还是在增强Criteria API的易用性,但是这种做法会受到Criteria API的能力限制。
    我的意思是,HQL的能力比Criteria要强,所以LINQ Support的支持应该基于HQL而不是Criteria。

    HQL的确强,好像是基于asl设计的。不知道nh3.0设计查询会怎么样,不过Criteria 也没有什么改善,就是写出来是强类型了。
      回复  引用  查看    
  34. #34楼 kiler      2009-08-03 12:31
    引用李永京:但是HQL实在难写,还不是强类型。。。
    http://code.google.com/p/nhlambdaextensions/ 这个可能是将来的趋势,


    Criteria已经足够好了。HQL我现在开发基本不用,80%的查询都是依靠Criteria查询的。其实自己利用代码生成技术在你的数据层访问类里面自动构建一个表所有字段的查询属性就可以实现强类型的Criteria查询了,不一定要使用linq技术。

    对于你那个例子,可以这么写:
    在数据层PersonDao类里面声明一个查询属性
    public static readonly Property PROPERTY_NAME = Property.ForName(“NAME”);
    就可以直接强类型调用了
    .Add(PROPERTY_NAME.eq("Smith"));
      回复  引用  查看    
  35. #35楼 韦恩卑鄙      2009-08-03 12:39
    Tuplizer

    这一类的名词 美国人每天都在发明


    有什么形容词或者名词 就一定会有 xxlize 就会有xxlizer
      回复  引用  查看    
  36. #36楼[楼主] 李永京      2009-08-03 12:44
    @kiler
    我平时也是使用Criteria,关联、约束、投影都非常好用,比HQL方便,但是HQL相对写法有些简单。
    var query = session.QueryOver<Person>()
    .Where(p => p.Name == "李永京");
    也是非常好的,注意这是nh3.0的Criteria查询,不是linq。
      回复  引用  查看    
  37. #37楼[楼主] 李永京      2009-08-03 12:51
    引用韦恩卑鄙:
    Tuplizer

    这一类的名词 美国人每天都在发明


    有什么形容词或者名词 就一定会有 xxlize 就会有xxlizer

    哎,我们很无奈,每天都出来一些怪词出来.....
      回复  引用  查看    
  38. #38楼 GWPBrian      2009-08-03 13:07
    good 学习
      回复  引用  查看    
  39. #39楼 Jaxu      2009-08-03 13:55
    感谢楼主分享,我还是好多年前研究过NH,现在基本都不怎么用了。
      回复  引用  查看    
  40. #40楼 lola      2009-08-03 14:26
    这么复杂的东东,学习成本太高,还是直接用ado了
      回复  引用  查看    
  41. #41楼 Jeffrey Zhao      2009-08-03 14:35
    @lola
    所以要平时学,关键时候用起来就爽了。
      回复  引用  查看    
  42. #42楼 Jeffrey Zhao      2009-08-03 14:37
    引用韦恩卑鄙:
    Tuplizer
    这一类的名词 美国人每天都在发明
    有什么形容词或者名词 就一定会有 xxlize 就会有xxlizer

    中国人想名字不太容易了,呵呵。
      回复  引用  查看    
  43. #43楼 韦恩卑鄙      2009-08-03 14:52
    组元化者?
    组元化器?
      回复  引用  查看    
  44. #44楼 lola      2009-08-03 15:17
    @Jeffrey Zhao
    什么时候需要使用nh?什么时候适合用ado?而者的开发成本、学习成本如何?
      回复  引用  查看    
  45. #45楼[楼主] 李永京      2009-08-03 15:23
    @lola
    当你想OO的时候用用ORM挺不错的。
      回复  引用  查看    
  46. #46楼 heros      2009-08-03 16:34
    @李永京
    引用李永京:
    @lola
    当你想OO的时候用用ORM挺不错的。

    引用lola:
    @Jeffrey Zhao
    什么时候需要使用nh?什么时候适合用ado?而者的开发成本、学习成本如何?

    ado.net是基础,这个东西肯定得搞熟了。nh也好,ibatis也好,或都什么其它的orm都要在这个基础之上。在一个项目中也完全可以同时使用多种方式,ado.net、nh、ibatis……,一般的应用用nh,r 直接到 o的转换省时省力,但nh不擅长数据更新,这时可以用ibatis来补足,ibatis轻量级有nh映射的优点,但也不缺更新数据的时的性能;一旦有大数据报表等应用,尤其是在wcf等分布应用时不防抛开orm,直接adapter得到ds。ibatis的daomanager可以实现很好的管理。
      回复  引用  查看    
  47. #47楼 韦恩卑鄙      2009-08-03 17:05
    最近翻看企业应用模式那本书
    里面对 table adapter 那种模式评价不是很低啊

      回复  引用  查看    
  48. #48楼 Jeffrey Zhao      2009-08-03 17:30
    引用kiler:
    Criteria已经足够好了。HQL我现在开发基本不用,80%的查询都是依靠Criteria查询的。其实自己利用代码生成技术在你的数据层访问类里面自动构建一个表所有字段的查询属性就可以实现强类型的Criteria查询了,不一定要使用linq技术。

    对于你那个例子,可以这么写:
    在数据层PersonDao类里面声明一个查询属性
    public static readonly Property PROPERTY_NAME = Property.ForName(“NAME”);
    就可以直接强类型调用了
    .Add(PROPERTY_NAME.eq("Smith"));

    如果是这个需求的话,现在NHibernate Linq 1.0已经正式发布了,可以使用一下啊。
      回复  引用  查看    
  49. #49楼 Jeffrey Zhao      2009-08-03 17:34
    引用lola:
    @Jeffrey Zhao
    什么时候需要使用nh?什么时候适合用ado?而者的开发成本、学习成本如何?

    ado.net是必知必会,后者的话就说不准了,有块有慢,有大有小,我现在根本离不开ORM框架。
      回复  引用  查看    
  50. #50楼 andy.wu      2009-08-03 19:24
    总的感觉,运用DDD还是非常吃力的。需要大量的实践。NHibernate也还不是那么的好.

    大胡子MF的理论不错,但说实在的,要运用到实践中不是2,3年可以做到的,实际上等过了n年后,你会发现你自己的最佳实践,虽然理论上和别人差不多,但细节上和别人却完成不是那么一回事。
      回复  引用  查看    
  51. #51楼 Tony Woo      2009-08-03 20:39
    不错。。。
      回复  引用  查看    
  52. #52楼 Kinglee      2009-08-03 23:21
    好文章,先收藏了。
      回复  引用  查看    
  53. #53楼 yeml[未注册用户]2009-08-03 23:57
    引用Jeffrey Zhao:
    @yeml
    不知你的联系方式是什么,我可以怎么问你问题呢?

    我的账号是franklinye,如果你有问题,如果是我知道的,我会尽量告诉你

      回复  引用    
  54. #54楼 Curry      2009-08-04 09:39
    来迟了,顶下
      回复  引用  查看    
  55. #55楼 浅浅dě夕阳      2009-08-05 09:24
    呵呵,我也来迟了。继续学习~~~
      回复  引用  查看    
  56. #56楼[楼主] 李永京      2009-08-05 09:29
    引用Curry:来迟了,顶下

    恩恩,没关系。
      回复  引用  查看    
  57. #57楼[楼主] 李永京      2009-08-05 09:30
    @浅浅dě夕阳
    没关系哦,发完了,做个导航,都看见了
      回复  引用  查看    
  58. #58楼 wzhelp[未注册用户]2009-08-10 22:33
    都不错挺好的,对初学者具有很大的帮助
      回复  引用    
  59. #59楼 ERic Poon      2009-10-12 10:02
    不知“Tuplizers”是否可用作将某段查询投影转为一个实现相应接口的POCO实例,以此来操作一个HQL的投影查询(相当于操作某个View的实例,便于权限控制)。
    例如:User表中有若干字段,而某用户权限操作只需要其中部分的字段,则可以将这些字段定义到一个接口,IUserRead中,由HQL得到这个接口需要的字段,再由Tuplizer转为一个IUserRead的实例,这就可以通过它来操作属性,而不是操作一个Object[]。
      回复  引用  查看    
  60. #60楼[楼主] 李永京      2009-10-12 10:06
    @ERic Poon
    你说的是数据传输对象DTO,我们查询返回一个DTO就可以了。
      回复  引用  查看