上一篇主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了。NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是virtual的。请注意这里的要求有两个细节:

  • 即使是方法,也必须标记为virtual
  • 即时是不和数据库有映射关系的属性,也必须标记为virtual

这就让我觉得无厘头了,为什么没有任何关系的东西也要受到限制?我知道NHiberante要求将属性标记为virtual是为了延迟加载,因为只有这样它才能生成如上一篇文章中那样的延迟代理类,这样就可以实现只在第一次访问属性的时候才进行“加载”操作,从而访问数据库并获得数据,再填充字段。不过我认为这也不是合适的理由,因为这又关没有映射的属性,甚至方法什么事情呢?我在很长一段时间内一直没有想明白这个问题。

直到看了NHibernate开发团队成员Davy Brion的文章《Must Everything be Virtual with NHiberante?》之后,我才了解了他们的设计思路——虽然我还是不认同。我真的不喜欢到处virtual。

要求类中所有的公开成员(public/protected)都是virtual,是因为NHibernate想要保证在“访问任何公开成员”之前,数据已经被加载了。也就是说,无论您是想调用它的ToString方法,还是您自己写的辅助方法/属性,在真正进入您自定义的逻辑之前,数据肯定已经存在了——例如,存在于私有的域字段中:

public class Article
{private string m_tagNamespublic virtual string TagNames{get{return this.m_tagName;}set{this.m_tagNames = value;}}public void DoSomethingWithTagNames(){ Console.WriteLine(this.m_tagNames);}
}

虽然NHibernate可以在TagNames属性第一次访问时加载数据,但是如果我们的DoSomethingWithTagNames方法直接访问m_tagNames字段,数据自然无法加载了。因此,NHibernate必须确保有能力在代理类中覆盖DoSomethingWithTagNames方法才行。这就是virtual方法的由来。

但是在我看来,我们真的有多少情况会去访问私有字段呢?事实上对于大部分情况,我们会使用C#中“自动属性”特性来定义属性,这样自然只有属性,没有字段。即使我们使用了自定义的私有字段来保存属性的值,NHibernate也可以“叮嘱”我们应该访问属性,而不要直接访问私有字段——其实在编程上两者并没有差别。现在这样被强迫的感觉不好。

不过昨天我忽然想到,这似乎也是可以理解NHibernate这么做的原因:因为Hibernate要照顾到Java语言开发人员的使用感受——请注意是Hibernate,没有N。不管怎么说,NHibernate是从Hibernate移植过来的。NHiberante的主力开发人员Oren Eini曾在博客中写道(可惜一时没找到),NHiberante刻意与Hibernate的实现保持同步,这样容易进行双向的同步,例如Hibernate解决了一些bug或性能问题,也可以较为轻易地在NHibernate上修补。

不过这还是没有解释为什么Hibernate要一切都是virutal的原因啊。其实您只要看一下这段Java代码就应该明白了:

public class Product
{private String m_tagNames;public String getTagNames(){return this.m_tagNames;}public String setTagNames(String value){this.m_tagNames = value;}
}

这是上面C#中Product的等价Java代码。由于Java里没有“属性”概念,因此Java语言自身一直有一个“约定”:getXxx和setXxx两个方法即为一个属性。这个约定用在很多地方,如IDE就会把它当作是一个属性方便设置及导航,框架在进行序列化时候也知道哪些东西是“属性”。这“约定”本没有问题,但是这就给Java开发人员造成了一定困扰:使用起来实在是太麻烦了。例如,Product有个属性叫做ViewCount,我们想要把它加1,在C#中我们可以写:

this.ViewCount++;

而在Java中则必须是:

this.setViewCount(this.getViewCount() + 1);

因此,如果是你的话,在写Java代码的时候,是愿意使用getXxx()这样的方法,还是直接访问类中的私有字段?因此我认为,是Java语言的特性,导致Java开发人员倾向于直接访问类中的私有字段,从而导致Hibernate需要避免未加载的私有字段,进一步导致Hibernate的代理类会去覆盖所有的公开方法(只有方法,因为Java语言没有“属性”)——最终,由于NHibernate在“统一大业”上的策略,使得我们.NET开发人员也必须把所有成员标记为virtual,无论是方法还是属性。

您可能会说,但也没见Java程序员嚷嚷啊。没错,因为在Java语言中,默认情况下所有的成员都是virtual的。而在.NET平台下情况正好相反。因此在我看来,我们这里必须到处标记virtual所造成的不便,和Java语言本身有着非常大联系——我们需承受Java语言所带来的痛苦。

虽然我理解NHibernate,但这又怎能让我满意呢?

哦,对了。在未来的Java 7中,我们可歌可泣的Java语言终于有了a –> property这样的属性访问语法了。

可惜,迟了。

转自:http://blog.zhaojie.me/2009/09/my-view-of-nhibernate-2-virtually-everything.html

转载于:https://www.cnblogs.com/zjoch/p/4360006.html

我对NHibernate的感受(2):何必到处都virtual相关推荐

  1. NHibernate :何必到处都virtual

    上一篇文章主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了.NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是vi ...

  2. 宜信创始人唐宁:技术到处都是,关键看怎么用

     宜信创始人唐宁:技术到处都是,关键看怎么用 极客公园 2017-06-02 16:15 阅读:4443 摘要:作者:「痛点是什么?」5月26日下午的北大斯坦福中心,这是宜信创始人唐宁口中出现频率 ...

  3. 最近大街上,到处都是X团的地推

    小文说,最近大街上,到处都是X团的地推,成群结队的,拉着每一个路人推销他们的软件,忽悠着你下载他们的APP. 小文昨天中午出去吃饭,五.六个X团的地推,把一个漂亮女孩围在中间,各个都是轻佻的语气,拜托 ...

  4. 不要到处都用@Autowired啦

    相信大部分人项目只要用了spring框架,肯定到处都是@Autowired. 注意: spring4.3以后就可以省略@Autowired了,全部更新内容: 地址:其中跟新内容如下 这是什么意思呢,翻 ...

  5. 我对NHibernate的感受(3):有些尴尬的集合支持

    既然是一个ORM框架,那么自然是将O这一端映射R上.至于集合,是O这方面最常见,也是R这一边非常容易表示的关系.例如,一个问题(Question)可以包含多个回答(Answer),于是我的代码里就有这 ...

  6. 艾伟_转载:我对NHibernate的感受(1):对延迟加载方式的误解

    NHibernate是.NET平台上最著名的ORM框架,虽说出身于Java平台上的Hibernate,但是从外部看来这几乎就是一个.NET平台上的原生产品:有自己的社区,有自己的用户,有自己的商业支持 ...

  7. 这个时代,到处都是才华横溢的穷光蛋

    过多的才华是一种病,害死很多人. 其实,过多的才华何止是一种病,还是一种罪. 过多的内涵,过多的思想,过多的情怀都是一种罪. 我生平见过无数有才华或者有理想的人,他们无一不活得很痛苦. 他们不愿向世俗 ...

  8. ad走线画直线_作为立体几何的热点,直线与平面的平行关系,到处都是考试的影子...

    在高考数学里,空间直线与平面的平行有关的知识内容和题型,一直是近几年高考命题的热点,成为立体几何重要的基础考点.如何巧妙快速的判定空间直线与平面平行位置关系,如何在平面内寻找一条直线,探索该直线与平面 ...

  9. 现在的年轻人。。。到处都是套路。。。

    防不胜防! 下面这个是我最近新开的小号 平时会分享一些有趣的日常见闻(前沿.脑洞.搞笑) 推荐一些我用过的数码产品,也会吐槽一些不好用的东西

最新文章

  1. 表单的几个基本常用功能
  2. QNX设置开机启动命令来修改IP地址
  3. 在Spring Controller中将数据缓存到session
  4. 实战~阿里神器 Seata 实现 TCC模式 解决分布式事务,真香
  5. 构建LAMP平台及应用系统
  6. Android Service完全解析
  7. java是一种,java是一种编译程序吗
  8. LeetCode刷题(6)
  9. perl脚本中的特殊字符也与V字符串
  10. SpringMVC整合fastjson、easyui 乱码问题
  11. C#的String.Split方法
  12. net core文件接收(jpg、png、zip、pdf等自己设置)
  13. mysql点击计数器_高性能Mysql(第3版)_网站点击计数器
  14. ElasticSearch7.8.0下载与安装
  15. PCIE 协议分析工具
  16. 2021-07-13
  17. 马蜂窝火车票系统服务化改造初探
  18. WIFI6 5G信道、频宽对应关系
  19. ftp服务器修改默认端口,FTP原理和修改FTP默认端口
  20. CEPH DAYS 2016 APAC ROADSHOW Ceph社区分享资料

热门文章

  1. Net::SSH::Perl 模块
  2. C#去掉字符串中的汉字
  3. 织梦channel标签currentstyle样式无效不起作用
  4. JBoss下布署Spring2.5和Struts2系统
  5. 【数字信号处理】序列傅里叶变换 ( 基本序列的傅里叶变换 | 求 1 的傅里叶变换 )
  6. 【Android 逆向】IDA 工具使用 ( 交叉引用数量设置 | 调试设置 )
  7. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )
  8. 【计算理论】可判定性 ( 丘奇-图灵论题 | 可判定性引入 | 图灵机语言 | 图灵机结果 | 判定机 | 部分函数与全部函数 | 可判定性定义 )
  9. 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 最简单用法 | 一行代码搞定权限申请 | 推荐用法 )
  10. 【数据挖掘】贝叶斯公式应用 拼写纠正示例分析 ( 先验概率 | 似然概率 | 后验概率 )