持久化生命:
持久化对象三个状态:短暂,持久,脱离
短暂的对象,通过New出来,如果要持久,必须save,或者引用某个已经持久化的对象。
持久化对象,某个实例带有数据库身份。持久化对象要么通过短暂对象持久化得到,或者Query语句得到,或者通过对象图导航得到。一句话都和Session和事物相关。
持久化使用事物,在事物结束的时候,持久化对象状态自动和数据库同步。通过insert update delete语句,在事物提交的时候,如果开发者没有更新状态到数据库,Hibernate提供脏数据检测功能,后写入事物级特性,把脏数据自动写入数据库,在事物结束的时候。
持久化也能转换成零时对象。
脱离对象,脱离Session的持久化对象,不再受Hibernate管理.通过session.close,或者evict,如果在cache的时候。该对象可以用到其他层,比如业务层,表现层。
对象身份的范围,一般在session范围内,先后调取数据库中一个记录,返回对象,应是相同的。
对象身份范围外:用户可以Reattachment脱离对象,这样就有一个问题怎么区别脱离对象和临时对象,最好方法就是看身份ID的数值.
实现Equals,hashcode,三种方法,
第一种:按数据库的主键,如果主键缺失,那就出问题了,
第二种:如果按内容的值的话,可能会产生不同数据库的记录是相同的错误。
可以按第三种,按业务的key,比如用户。
持久化管理:
持久化重点就是session。
持久化一个对象,比如save()方式,在事物commit的时候,执行SQL,也就是说这个时候session取得connection,执行SQL,sesssion.close(),connection释放。
持久化脱离对象的状态,用update,lock把游离的对象,与当前的session关联,变更状态,事物提交,对象状态持久化
检索持久化对象,如果没有返回null
更新持久化对象,检索出来,改变状态,事物提交,自动持久化
持久化对象变短暂,session.delete()
把脱离对象变成短暂.sesssion.delete()
传递持久化
可触持久化,
级联持久化:
You can map entity associations in metadata with the following attributes:
■ cascade="none", the default, tells Hibernate to ignore the association.忽略■ cascade="save-update" tells Hibernate to navigate the association when thetransaction is committed and when an object is passed to save() orupdate() and save newly instantiated transient instances and persist changes todetached instances.保存和更新■ cascade="delete" tells Hibernate to navigate the association and delete persistentinstances when an object is passed to delete().删除■ cascade="all" means to cascade both save-update and delete, as well ascalls to evict and lock.包括保存,更新,删除■ cascade="all-delete-orphan" means the same as cascade="all" but, in addition,Hibernate deletes any persistent entity instance that has been removed(dereferenced) from the association (for example, from a collection).包括全部情况■ cascade="delete-orphan" Hibernate will delete any persistent entityinstance that has been removed (dereferenced) from the association (forexample, from a collection).删除孤儿级联持久化举例
短暂和游离的实例区分:
主要看id,version是否空,或者为未保存的的值是否与事先指定一致。
检索数据
检索对象,有多种方法,对象导航,id查找,HQL,Criteria,SQL查询等方法.
通过身份检索
load,旧的方法,如果没在缓存和database中查找到,返回的代理不是真正的持久实例,并且返回代理,不会直接去访问数据库,只有当该代理首次被访问的时候,才访问数据库,这时候才抛出异常
get,新的,如果不能确定是否存在,返回null,去缓存中去找,如果能找,被查找过代理,如果没有去二级缓存,再没有去数据库查,再没有则返回null,如果有就返回真实的持久实例
来贴一段网友经典总结:
2.缓存中没有这个对象 就创建个代理 因为延迟加载需要代理来执行 所以就创建了个代理 ok 到此为止 这句话就干了个这个 并没有去数据库交互查询 当你使用这个对象 比如tfag2.getTfRtitle()或get方法时候
这个时候 hibernate就去查询二级缓存和数据库,数据库没有这条数据 就抛出异常 整个load方法调用结束 load没什么神奇 这就是他干过所有的事情 load方法讲完了 我在讲一下get方法工作原理 因为hibernate规定get方法不能使用延迟加载 所以和load还是不一样的 TFaq tfag2=(TFaq)sess.get(TFaq.class, 300); 在创建这条语句时候 我们看看hibernate干了哪些事 1.get方法首先查询session缓存 (session缓存就是hibernate的一级缓存 这个概念大家应该清楚吧 ) 2.get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象。 3.如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。 (这个代理实际就是空的对象 并没有去数据库查询得到的 我们叫代理对象,如果 去数据库查询了 返回到了这个对象 我们叫实体对象 就是这个对象真实存在) 我在总结性一句话这2者区别 get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库
HQL:只有select,没有update,delete,insert
criteria:
取的策略:
四种策略,立刻攫取,懒加载,积极加载,批量加载。
立刻攫取:立刻取得关联对象。
懒加载:不是立刻取得,根据需要去数据库取的。
积极加载:外部连接方式积极加载相关联对象。
批量加载:指定多个对象身份,在where条件,加载
选择取得策略:
单点关联
代理存在,必须设置lazy=true,或者设置proxy,为类的某个接口
out-join属性 auto 缺省值,懒加载
true积极加载
false 从不用out-join加载关联
集合都有自己的代理,不像类,集合的代理始终存在。
lazy,outjoin all=false,有缓存最好,或者发起一个额外的SQL。
out-join=true,通过out-join取得collection,并且在某个持久类中,只有一个collecion可以这样规定。
lazy=true,懒加载。
batch-size='9'意味9个类实例,可以取得collecion,批量取得
一对多的关系,collection是多
多对多的关系,collection是指link关系。
设置取得深度:the maximum fetch depth
hibernate.max_fetch_depth 缺省值为1,只取得一层的关系,最好1-4
可以考虑一个例子,category,item,bid
category-item 一对多,item-bid多对多,从category到bid就是两层关系,如果为1,category-item
如果为2,同一个SQL要join 四个表,category,categoryitem ,item,bid
懒加载关系
一个代理或集合包装是自动的初始化,当其中的任何一个方法被调用的时候(除了取得身份getter,可能只回身份值,并没有取得底面的持久对象),但是,是可能初始化proxy,和集合wrapper,如果所关联的session是open的,如果关闭session,试图存取代理和集合,Hibernate就会抛出运行异常。
可以用Hibernate.initialize()手工初始化,
也可保持session open知道应用线程完成为止。
调优对象检索:
1,enable sql显示
2,对整个应用SQL执行,就行查看,进行调优
3,两个共通的问题
out-join问题,
如果SQL太复杂,可以out-join=false,hibernate.max_fetch_depth调节这个值
如果太多SQL要执行,out-join=true,lazy=false积极取得
collection 批量取得
4,设置新的取得策略,查查SQL,是否优化
5,查找了优化,是不是对其他的有影响.