【原】Hibernate数据检索策略和.hbm.xml映射文件
一、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>
一对一、多对一比如学生对班级是多对一关系,要实现对班级的批量加载,如下:
<class name="model.Team" table="team" batch-size="3">
二、下面分析一下.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"当使用一对一、多对一方式加载Student类时,将采用延迟加载(前提是设置预先抓取为false)。
第6、7、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配置文件信息的解释如下:
第6、7、8、9、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配置文件源码:
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配置文件信息的解释如下:
第11、12、13、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"的一方)。这样就解决了。
分享到:
相关推荐
Hibernate.jar包,Hibernate可以应用在任何使用JDBC的场合,包含 hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-...
"Hibernate入门到精通" Hibernate 是一个基于Java的ORM(Object-Relational Mapping,对象关系映射)框架,它提供了一种简洁高效的方式来访问和操作关系数据库。下面是 Hibernate 的主要知识点: Hibernate 简介 ...
hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-4.1.12.Final.jar hibernate-jpa-2.0-api-1.0.1.Final.jar ...
项目原型:Struts2.3.16 + Spring4.1.1 + Hibernate4.3.6 二、 项目目的: 整合使用最新版本的三大框架(即Struts2、Spring4和Hibernate4),搭建项目架构原型。 项目架构原型:Struts2.3.16 + Spring4.1.1 + ...
【hibernate学习资料大全】 Hibernate 是一个开源的对象关系映射(ORM)框架,它极大地简化了Java应用程序对数据库的操作。这个压缩包包含了丰富的Hibernate学习资源,旨在帮助开发者深入理解和熟练掌握这一强大的...
《Hibernate-Extensions全面指南》 Hibernate,作为Java领域中的一款著名对象关系映射(ORM)框架,极大地简化了数据库操作。然而,为了满足更复杂的业务需求,Hibernate还提供了丰富的扩展功能,这就是我们今天要...
【描述】中的"hibernate的jar包"指的是Hibernate框架的运行库文件,这些JAR文件包含了Hibernate的所有核心API、实现和依赖库,如Hibernate Commons Annotations、Hibernate EntityManager、Hibernate Core等。...
Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者使用面向对象的方式来操作数据库,极大地简化了数据访问层的编程工作。这个压缩包包含了Hibernate的基础jar包,这些jar文件是开发Hibernate应用所...
HibernateTools是Java开发人员在使用Hibernate ORM框架时的有力辅助工具集,主要目的是为了提高开发效率,简化数据库操作。在HibernateTools 3.2.4版本中,它包含了一系列的特性与插件,以支持更便捷地进行对象关系...
Hibernate3 是一个强大的Java持久化框架,它允许开发者将数据库操作与业务逻辑解耦,使得应用程序的开发更为简便。这个“hibernate3全部jar包:hibernate3.jar.zip”包含了所有必要的库文件,方便用户一次性下载并...
Hibernate3是一个广泛使用的Java对象关系映射(ORM)框架,它允许开发者用面向对象的方式处理数据库操作,极大地简化了Java应用程序与数据库之间的交互。在这个"Hibernate3的依赖包"中,包含了运行Hibernate3应用...
标题中的“hibernate和MySQL的jar”指的是Hibernate ORM框架与MySQL数据库之间的连接库。Hibernate是一种流行的Java对象关系映射(ORM)工具,它允许开发者使用面向对象的编程方式来操作数据库,而无需直接编写SQL...
在Java开发环境中,与KingbaseV8数据库进行交互通常会用到Hibernate框架和JDBC驱动。 Hibernate是一个优秀的对象关系映射(ORM)框架,它简化了Java应用程序对数据库的操作,通过将Java对象与数据库表进行映射,...
标题"Hibernate 中文api 等学习资料"暗示了这是一组针对Hibernate ORM框架的中文学习资源,包括API文档和其他指南,旨在帮助用户更好地理解和使用Hibernate。 描述中的"hibernate orm框架api中文文档,学习资料,...
包含hibernate所有所需jar包还有一些其他包日志包、jpa支持包等: 列如:hibernate-core-5.1.0.Final.jar hibernate-ehcache-5.1.0.Final.jar hibernate-entitymanager-5.1.0.Final.jar hibernate-envers-5.1.0....
Hibernate是一款强大的Java持久化框架,它简化了数据库与Java对象之间的交互,使开发者可以更加专注于业务逻辑而不是数据访问层的实现。本压缩包提供的是Hibernate入门所需的jar包,包括了Hibernate的核心库以及与之...
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端...
Hibernate3 是一个非常重要的Java持久化框架,它允许开发者将对象模型与数据库关系模型进行映射,从而简化了数据存取的过程。这个压缩包“hibernate3必要jar包”显然是针对Hibernate3版本的,已经去除了冗余的库文件...
Hibernate 是一个著名的开源对象关系映射(ORM)框架,它为Java开发者提供了便捷的数据持久化方式,使得在Java应用程序中操作数据库变得更加简单。这个“hibernate_3.2官方开发包”包含了所有你需要开发基于...
Hibernate是一款强大的Java持久化框架,它为Java开发者提供了一种对象关系映射工具,使得开发者可以使用面向对象的方式来操作数据库,极大地简化了数据库操作。在Java应用中,尤其是在企业级应用开发中,Hibernate是...