持久化生命:
持久化对象三个状态:短暂,持久,脱离
短暂的对象,通过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 the
transaction is committed and when an object is passed to save() or
update() and save newly instantiated transient instances and persist changes to
detached instances.保存和更新
■ cascade="delete" tells Hibernate to navigate the association and delete persistent
instances when an object is passed to delete().删除
■ cascade="all" means to cascade both save-update and delete, as well as
calls 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 entity
instance that has been removed (dereferenced) from the association (for
example, from a collection).删除孤儿
级联持久化举例
短暂和游离的实例区分:
主要看id,version是否空,或者为未保存的的值是否与事先指定一致。
检索数据
检索对象,有多种方法,对象导航,id查找,HQL,Criteria,SQL查询等方法.
通过身份检索
load,旧的方法,如果没在缓存和database中查找到,返回的代理不是真正的持久实例,并且返回代理,不会直接去访问数据库,只有当该代理首次被访问的时候,才访问数据库,这时候才抛出异常
get,新的,如果不能确定是否存在,返回null,去缓存中去找,如果能找,被查找过代理,如果没有去二级缓存,再没有去数据库查,再没有则返回null,如果有就返回真实的持久实例
来贴一段网友经典总结:
load是true而get是false
意 思就是 load采用的是延迟加载的方式 而get不是,hibernate思想是 既然这个方法支持延迟加载 他就认为这个对象一定在数据库存在,在你 声明 TFaq tfag2=(TFaq)sess.load(TFaq.class, 300); 这句时候,hibernate就干了一件事
1.查询session缓存
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,查找了优化,是不是对其他的有影响.
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>