Hibernate数据检索策略和.hbm.xml映射文件

1、Hibernate的数据检索策略是面向对象的策略,对与不一样的检索状况,应使用不一样的策略,以提升效率节省资源。常用的是当即检索和延迟检索,预先抓取和批量检索都是为了优化加载性能而设计的策略。检索通常是创建在表关联的基础上的因此咱们先创建三张表Team与Student是一对多关系,Student和Certificate是一对一关系。
Team→id:String、teamName:String
Student→id:String、team_id、name、cardid、age
Certificate→id:String、describe
在这里Team至关于原对象Student至关于Team的附属物,Certificate至关于Student的附属物。当加载一个原对象时,原对象对附属物的使用有2中状况:(1)立刻就用附属物的数据(2)可能一会用,可能不用。第一种状况适用于当即检索,第二种状况适用于延迟检索。
1.当即检索
当即检索的配置文件标识符为lazy="false"。算法

通常状况下咱们把一对一和多对一这样后者为一的对象用于当即检索,由于是“一”的这段,所带来的性能消耗也有限。当即装载附属物有个好处,原对象脱离管理成为VO之后,仍然可使用这些附属物。而对一对多和多对多关联对象则不适合当即检索。好比班级和学生是一对多的关系,当取得班级对象时,如过是当即检索,就会把班级的全部学生对象组装起来,这种资源消耗在这没有必要。
2.延迟检索
延迟检索的配置文件标识符为lazy="true"。
延迟检索就是等到须要用到时(好比调用了Team.getTeamName()。调用stu.getTeam()不行,必须以Team为主体取得附属物时,才会实现延迟加载)才会去取被关联对象Team。所以若是在Student对象的配置文件中设置了对Team进行延迟检索,则在取的学生1对象时,Hibernate仅把学生1对象设置为当即检索的对象和属性装配进学生1对象,而并不会当即去组装设为延迟检索的附属物,只有在同一个Session中使用到班级1时,Hibernate才会从数据库中查找数据并装配成班级1对象。
若是把班级对象归入另外一个Session中,使用org.hibernate.Hibernate这个类的initialize()方法,这时脱离Session管理仍然能够从班级对象中取出数据。
3.预先抓取
预先抓取的配置文件标识符为fetch="join"
若是把三个表之间的关系都设为当即检索,取得班级对象时,从而递归的获得学生和身份证对象。若是有100个学生,则要发送100条SQL语句去取100个身份证。这样会很大程度的下降性能。因此必须减小发送的SQL语句的数量。使用预先抓取只是用一条SQL语句就能代替当即检索的100条SQL语句。再具体点好比有一堆货物,原先有100我的排队顺序去背,如今让一我的一次背回来,反而影响性能。每次背的数量可用hibernate.max_fetch_depth来控制。还有一点须要注意,HQL使用外链接查询时忽略配置文件中配置的预先抓取策略,如:Query q = session .createQuery("from Strudent as s left join s.team");因此咱们应该改成Query q = session .createQuery("from Strudent as s left join fetch s.team");
仅从使用角度来讲。预先抓取和当即检索的效果同样,只不过预先抓取能减小SQL语句的条数。
4.批量加载
批量加载老是和当即或延迟加载联系在一块儿,分为批量当即加载和批量延迟加载。主要是控制发送SQL语句的条数,较少资源的消耗。
对于一对多、多对多在集合的配置中设置,以set为例:
<set name = "students" inverse="true" batch-size="3">
            <key column="team_id"/>
            <one-to-many class="model.Student"/>
</set>
一对1、多对一好比学生对班级是多对一关系,要实现对班级的批量加载,以下:
<class name="model.Team" table="team" batch-size="3">
2、下面分析一下.hbm.xml文件
有3个实体,Team、Student、Certificate,Team与Student是一对多关系,Student和Certificate是一对一。
(1).Student.hbm.xml配置文件源码:数据库

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <class name="model.Student" table="student" lazy="true">    
 6         <id name="id" unsaved-value="null">
 7             <generator class="uuid.hex"/>
 8         </id>
 9         <property name="cardid" type="string"/><!--映射号-->
10         <property name="name" type="string"/><!--映射学生名-->
11         <property name="age" type="int"/><!--映射学生年龄-->
12         <one-to-one name="cer" class="model.Certificate" fetch="join" cascade="all"/><!--映射对应的身份证对象-->
13         <many-to-one name="team" class="model.Team" column="team_id" fetch="join"/><!--映射班级-->
14     </class>
15 </hibernate-mapping>

Student.hbm.xml配置文件信息的解释以下:
第5行:model.Student类对应的数据库表是student表。lazy="true"当使用一对1、多对一方式加载Student类时,将采用延迟加载(前提是设置预先抓取为false)。
第六、七、8行:Student类有一个主键id,id由Hibernate自动生成,生成算法是uuid.hex。在内存中有不少对象,能够经过unsaved-value="null"来判断对象是持久化的仍是临时状态。当对象的id值为unsaved-value指定的"null"时,认为未持久化,不然认为此对象是持久化或托管状态。注意int、long型的主键id的默认unsaved-value="0"。
第12行:一个一对一关联的对象属性,名为cer,fetch="join"在获得Student对象时。采用预先抓取获得cer对象。cascade="all"表示级联为all,说明Student的crud操做都会影响cer对象。
第13行:一个多对一关联的对象属性,名为Team,在Student表中经过team_id与Team对象发生关联,引用team中id成外键,没个Student对象对应惟一的team。team的实体类是model.Team。在取得Student实例时。使用预先抓取获得team对象。
(2).Certificate.hbm.xml配置文件源码:缓存

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5    <class name="model.Certificate" table="certificate" lazy="true">
 6        <id name="id">
 7            <generator class="foreign">
 8                <param name="property">stu</param>
 9            </generator>
10        </id>
11        <one-to-one name="stu" class="model.Student" fetch="join" constrained="true">
12        </one-to-one>
13        <property name="describe" column="describes" type="string"></property>
14    </class>
15 </hibernate-mapping>

Certificate.hbm.xml配置文件信息的解释以下:
第六、七、八、九、10行:Certificate和Student是一对一关联,使用的是以主键关联,即Certificate和Student公用一个主键值。Certificate的主键id生成使用外键方式(generator class="foreign"),此外键参考一对一引用中的"stu"变量。
第11行:一对一关联model.Student类,当取Certificate对象时,预先抓取Student类(fetch="join"),声明了constrained="true"。这个选项影响save()和delete()在级联执行的前后顺序以及决定该关联类可否被延迟加载(true时,此是的Student类才可被延迟加载)。
(3).Team.hbm.xml配置文件源码:session

 

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5    <class name="model.Team" table="team" lazy="true">
 6        <id name="id" unsaved-value="null">
 7             <generator class="uuid.hex">
 8             </generator>
 9         </id>
10         <property name="teamName" type="string"/>
11         <set name="students" inverse="true" fetch="select" lazy="true">
12             <key column="team_id"/>
13             <one-to-many class="model.Student"/>
14         </set>
15     </class>
16 </hibernate-mapping>

Team.hbm.xml配置文件信息的解释以下:
第十一、十二、1三、14行:一个Set集合名为students,采用延迟加载,在实体对象Student对象的student表中。一team_id列对应Team对象。

(4)须要在说一下的问题:
cascade属性的用法:
save-update:在执行save/update/saveOrUpdate时进行关联操做。
delete:在执行delete时进行关联操做。
none:全部状况下均不进行关联操做。这是默认值。
all的意思是save-update + delete 。
all-delete-orphan 的意思是当对象图中产生孤儿节点时,在数据库中删除该节点 。
举个例子说一下all-delete-orphan,Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items.
举个例子,现items中存两个Item, item1,item2,若是定义关系为all-delete-orphan ,当items中删除掉一个item(好比用remove()方法删除item1),那么被删除的Item类实例 ,将变成孤儿节点,当执行category.update(),或session.flush()时
hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉。
在多对多关系中不能够把cascade设置为all和delete,这样问题就大了,想一想会有什么后果。
unique属性的用法:
之外间关联的一对一,本质上变成了一对多的双向关联了,编写以一对多和多对一要求编写,最后在many-to-one这一边加上unique="true"即说明它只不过是一对多的特例(“多”这一方只有一个对象)。
constrained属性的用法:
对one-to-one关系进行延迟加载和其余关系相比稍微有些不一样。many-to-one的延迟加载是在配置文件的class标签设置lazy="true",one-to-many和many-tomany的延迟加载在Set标签设置lazy="true",而one-to-one不仅要在class标签设置lazy="true",并且要在one-to-one标签中设置constrained="true"。也就是说one-to-one关系,constrained="true"和附属物的lazy="true"才能实现延迟加载,并忽略默认的预先抓取。(这里说的是默认,若是指定fetch="join",则不管如何都是预先抓取)。
inverse属性的用法:
两个表设置了双相关联,inverse="true"表示双方的关系将由对方去维护。
一对多应该让“多”的这一端有主动权,也就是在“一”这一端设置inverse="true"。
多对多关联关系中,若是双方都有控制权,这时会有一些问题,好比双方都引发插入语句,这就会违反数据库的主键约束,缘由是试图插入重复主键。说以在某一方设置inverse="true",而后在执行语句时使用主控方进行操做(也就是没有设置inverse="true"的一方)。这样就解决了。app

Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear. 面对过去无怨无悔,把握如今充满信心,备战将来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术须要不断的积淀!
相关文章
相关标签/搜索