`
fw2003
  • 浏览: 80198 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

hibernate复习小结......

阅读更多

  不知不觉,已经1年半没碰hibernate了,东西越来越多,越来越杂.感觉人也越来越浮躁.也该是时候沉静下来进行消化了.

 

  对于hibernate,正如自己对ddd的认识一样,从一开始的惊为天人,无比推崇,再到复杂的实际应用时落入陷阱,开始疑惑--怀疑--抱怨--抛弃--走向另一极端(比如去研究使用ibatis),最后经历种种沟壑,时间的沉淀让自己能够以一种平和的眼光看待这些所谓的"人云亦云""看上去很完美"的东西,终于发现,脱离实际单纯地抱着技术的眼光去看待任何一门学问,都是片面的肤浅的.存在即合理,刀可用来做菜,也可用来杀人,所用何途全在使用者的一念之间.所谓破而后立,大道至简,也许自己还远远未到这个层次,但是却再也不会被一项技术所迷惑.特此总结如下:

 

1.Session是本次请求使用到的持久对象的容器,并在其中使用jdbc的Connection派发sql

 

2.Session的生命周期的管理:到底是在1次数据库操作之间打开,还是选择在1次完整的请求过程中一直打开(即osiv),决定了应该使用哪些抓取策略以及优化措施.(个人觉得理解这一条是能否能用好hibernate的前提)

 

3.hibernate作为一款优秀的ORM框架,能够完全支持复杂的领域模型到不匹配的数据库模式的映射:如类表模式/嵌入值模式/类映射到多张表/继承的映射,解决关键字:组件映射,继承映射

 

4.hierbnate的缺点:查询总是加载一个对象的所有列,而属性延迟加载需要运行字节码增强器.解决关键字:类/表/列拆分

 

5.所谓的查询性能/n+1查询问题:在默认的情况下因为延迟加载子对象/集合,通过父象查询子对象时需要先通过1条sql返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询

解决关键字:抓取策略/主动加载/缓存

5-1.fetch=join 使用外连接形式通过1条sql获取父/子表数据

5-2.fetch=subselect 使用1句select xxx from 子表 where 子表外键id in(select 主表id from 主表)的相关子查询,使得遍历多个父对象的子对象集合时只需要发送1条SQL

5-3.batch-size=xx 子查询抓取的变种 原理相同

5-4.与主动加载相矛盾的是,如果要使被加载的数据命中cache,则不能使用主动加载

 

6.如果session生命周期只在1次数据库操作之间,5-1是最为合适的主动加载方式.如果能够保持session一直打开,如osiv,那么5-2,5-3可以在默认的抓取策略即fetch=select也即lazy=true的基础上作为补充方式

 

7.静态配置抓取策略(即在配置文件中指定)的作用范围:get/load/criteria条件查询,而在hql中则必须通过fetch join关键字才能使用连接主动加载,如果只有join没有fetch,则虽然连接但是不会得到子表数据

 

8.动态设置抓取策略(setFetchModel(FetchModel.xx))优先级高于静态配置,即可以在QBC查询中通过设置FetchModel而使配置文件中的静态配置失效.而所有抓取策略优先于预定义的lazy策略(即默认的fetch=select),即一旦通过静态或动态修改默认抓取策略后lazy=xx的配置就不会起作用

 

9.使用DetachedCriteria时,可能会因为API实现中没有public Criteria createAlias(String associationPath, String alias, int joinType) throws HibernateException 这个方法而导致使用别名后无法使自定义抓取策略生效

 

10.综上所述,如果将session交给sping管理,在默认配置情况下,延迟加载就等于没有加载(可能需要显示地在HibernateCallback的回调方法中实现+1查询).解决:参考5,6

 

11.OSIV的缺陷:并发大且网络阻塞(页面的输出时间即out.print的时间过长导致filter阻塞)会造成数据库连接一直被占用(虽然事务已提交但是连接一直没有放回池中)而导致连接池资源不足.同时由于session得不到及时释放也会导致session级缓存占用JVM内存相当长一段时间.解决:增加连接池数量/用包装器包装response输出页面后立即显示关闭SESSION/服务器提供NIO/AIO支持 

 

12.inverse和cascade:inverse指定谁来维护"关系"(表示是否把对set的改动反映到数据库中去.inverse=false————反映;inverse=true————不反映.inverse属性默认为false).cascade则简化了在代码中的级联更新和删除.一般在双向关联的一对多中,在父对象集合属性上面设置cascade=all或all-delete-orphan以及inverse="true"(many-to-many中可以在任意一端设置inverse="true"),而在子对象中设置cascade=none.即(下面这段是引用的,个人觉得说得很好):

老爸可以有多个孩子,一个孩子不能有多个老爸,而且老爸说的算, 孩子围着老爸转。
                所以Photos老爸要有权力所以 cascade 这个关键字都是送给老爸的, 也就是级联更新,
               老爸改姓了,儿子也得跟着改,呵呵。“不然,就没有零花钱咯”。
                而Picture儿子整体挨骂,但是还是要维护父子之间良好的关系,对老爸百依百顺,所
               以老爸就说,儿子,“关系,由你来维护(inverse="true") ,不然就不给零花钱。呵。”。

 

13.关于session.flush():清空缓存时执行SQL操作数据库的顺序 save-->update-->delete(在1次事务中多次执行save/update/delete时应注意这点并正确地使用session.flush同步缓存数据到数据库以便确保多个操作按正确的顺序执行)

 

14...

 

  暂时想到这么多,未完待续......

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics