不知不觉,已经1年半没碰hibernate了,东西愈来愈多,愈来愈杂.感受人也愈来愈浮躁.也该是时候沉静下来进行消化了.sql
对于hibernate,正如本身对ddd的认识同样,从一开始的惊为天人,无比推崇,再到复杂的实际应用时落入陷阱,开始疑惑--怀疑--抱怨--抛弃 --走向另外一极端(好比去研究使用ibatis),最后经历种种沟壑,时间的沉淀让本身可以以一种平和的眼光看待这些所谓的"人云亦云""看上去很完美" 的东西,终于发现,脱离实际单纯地抱着技术的眼光去看待任何一门学问,都是片面的肤浅的.存在即合理,刀可用来作菜,也可用来杀人,所用何途全在使用者的 一念之间.所谓破然后立,大道至简,也许本身还远远未到这个层次,可是却不再会被一项技术所迷惑.特此总结以下: 数据库
1.Session是本次请求使用到的持久对象的容器,并在其中使用jdbc的Connection派发sql缓存
2.Session的生命周期的管理:究竟是在1次数据库操做之间打开,仍是选择在1次完整的请求过程当中一直打开(即osiv),决定了应该使用哪些抓取策略以及优化措施.(我的以为理解这一条是可否能用好hibernate的前提)服务器
3.hibernate做为一款优秀的ORM框架,可以彻底支持复杂的领域模型到不匹配的数据库模式的映射:如类表模式/嵌入值模式/类映射到多张表/继承的映射,解决关键字:组件映射,继承映射网络
4.hierbnate的缺点:查询老是加载一个对象的全部列,而属性延迟加载须要运行字节码加强器.解决关键字:类/表/列拆分session
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条SQLfetch
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...
暂时想到这么多,未完待续......