`
ch_space
  • 浏览: 109246 次
  • 性别: Icon_minigender_1
  • 来自: 农村进城务工人员
社区版块
存档分类
最新评论

Hibenate关联策略探讨

阅读更多
以下涉及的几个问题是在实际开发中经常或碰到的,大家也渐渐形成了所谓的“最佳实践”,不过还存在一些问题,没有好的方案,请大家一起探讨。
1、是否延迟加载
    为了保持较好的性能,通常我们会选择延迟加载关联对象,这一点在one-to-many、many-to-one中体现最深。然而在下列情形中我们可能需要立刻加载关联的对象:
有一个Topic表,一个Comment表,Topic有一些统计信息例如浏览次数、回复次数、最后回复时间(回复者),这些信息是需要在查询Topic时立刻加载的。通常有两种方案:
1)将这些信息保存在Topic中,即topic表中含有这些统计信息字段。
    这种设计的问题:这些统计信息需要经常修改,例如有了新的回复,这会引起对topic表的更新,由于topic表的内容较多(含有text类型的字段),更新时性能影响较大。

2)将这些统计信息单独放在另一张表topic_stat。
    由于要立刻加载这些统计信息,所以要使用one-to-one主键关联,即将topic的主键作为topic_stat的主键,但是很不幸,这里又引起了另一个问题:每次对topic的分页查询都会再发送n个sql去查询关联的topic_stat,也就是n+1问题;而查询指定id的topic会使用left out join的方式抓取关联的topic_stat。所以这里的瓶颈是n+1问题。

    所以以上两种方案都不是理想的方案,有人提出使用唯一外键关联的方式避免n+1问题,但是这种方式会lazy加载关联对象,在需要立刻加载关联对象的情景下(如topic需要立刻加载topic_stat),这种方法是不适用的(对于不需要立刻加载而体现为一对一关系的情况下,唯一外键关联是一种很好的方案)。

2、OpenSessionInView
   针对需要立刻加载,而又想避免由于使用one-to-one主键关联引起n+1查询的问题,有人提出使用OpenSessionInView方法,这种方法也是可以接受的方案,但是由于session的打开是在请求到来就开始,视图渲染完毕之后才关闭,这中间的时间间隔较大,对于数据库访问频繁的应用来讲,不是一种好的方案。

结合上面的讨论,我想大家都有各自的看法,请大家分享一下。
分享到:
评论
6 楼 cmzx3444 2010-02-08  
ch_space 写道
[size=medium]以下涉及的几个问题是在实际开发中经常或碰到的,大家也渐渐形成了所谓的“最佳实践”,不过还存在一些问题,没有好的方案,请大家一起探讨。
1)将这些信息保存在Topic中,即topic表中含有这些统计信息字段。
    这种设计的问题:这些统计信息需要经常修改,例如有了新的回复,这会引起对topic表的更新,由于topic表的内容较多(含有text类型的字段),更新时性能影响较大。
size]

这个问题我想可以这么解决,在Topic对象中有个属性,比如是最新发布者:lastReply,和回复数:countReply,但是这两个都住存数据库,当对象加载后,我们再构建出完整的Topic对象,并放会缓存,这样有新的回复就更新缓存,数据库中的酒不用更新了,回复数直接加上去就可以了,最后的回复就把lastReply更新一下就可以了,但是有个问题我不知道怎么搞,那就是帖子浏览量的问题,难道我没点一次帖子就更新一下帖子
5 楼 hxl1013 2010-01-07  
ch_space 写道


2)将这些统计信息单独放在另一张表topic_stat。
    由于要立刻加载这些统计信息,所以要使用one-to-one主键关联,即将topic的主键作为topic_stat的主键,但是很不幸,这里又引起了另一个问题:每次对topic的分页查询都会再发送n个sql去查询关联的topic_stat,也就是n+1问题;而查询指定id的topic会使用left out join的方式抓取关联的topic_stat。所以这里的瓶颈是n+1问题。

左连接了,就是n的问题了
4 楼 hxl1013 2010-01-07  
ch_space 写道

1)将这些信息保存在Topic中,即topic表中含有这些统计信息字段。
    这种设计的问题:这些统计信息需要经常修改,例如有了新的回复,这会引起对topic表的更新,由于topic表的内容较多(含有text类型的字段),更新时性能影响较大。

Hibernate应该有控制使得只去更新更改过的数据,所以这不是个问题
3 楼 walle1027 2009-12-30  
onkyo 写道
我推荐用aop的形式延迟加载. 想法是在hibernate的HibernateProxy上再加上一个动态代理。 当get函数被调用前可以先判断hibernateproxy有没有被初始化, 如果过初始化了就继续, 如果没有初始化打开session然后加载hibernateproxy, 然后关闭session。 返回已经加载的值。

那这样要代理所有get方法,会不会性能上有问题?
2 楼 yfddht1573 2009-12-07  
ch_space 写道
1)将这些信息保存在Topic中,即topic表中含有这些统计信息字段。
    这种设计的问题:这些统计信息需要经常修改,例如有了新的回复,这会引起对topic表的更新,由于topic表的内容较多(含有text类型的字段),更新时性能影响较大。


小弟有个提义就是。为什么不把这种含有text的字段放在另一表中去喃?
1 楼 onkyo 2009-12-04  
我推荐用aop的形式延迟加载. 想法是在hibernate的HibernateProxy上再加上一个动态代理。 当get函数被调用前可以先判断hibernateproxy有没有被初始化, 如果过初始化了就继续, 如果没有初始化打开session然后加载hibernateproxy, 然后关闭session。 返回已经加载的值。

相关推荐

Global site tag (gtag.js) - Google Analytics