Hibernate_6

Java的集合类位于java.util包中,Java集合中存放的是对象的引用,而非对象本身。Java集合主要分为3种类型:
Set(集):集合中的对象不按特定方式排序,并且没有重复对象。
List(列表):集合中的对象按索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置索引对象。
Map(映射):集合中的每一个元素包含一对键对象和值对象,集合中没有重复的键对象,值可以重复。

Bag集合中的对象不按特定方式排序,订单式允许有重复对象。在Java集合API中并没有提供Bag接口,Hibernate允许在持久化类中用List模拟Bag的行为。
<idbag name="images" table="IMAGES" lazy=""true>
   <collection-id type="long" column="ID">
       <generator class="increment" />
   </colletion-id>
   <key column="CUSTOMER_ID"  />
   <element column="FILENAME" type="string" not-null="true"  />
</idbag>

Hibernate对集合中的元素支持两种排序方式:在数据库中排序和在内存中排序
在数据库中排序:简称为数据库排序,当Hibernate通过select语句到数据库中检索集合对象时,利用order by子句进行排序
在内存中排序:简称为内存排序,当Hibernate把数据库中的集合数据加载到内存中的Java集合后,利用Java集合的排序功能进行排序,可以选择自然排序或客户化排序两种方式。
set、map支持内存排序,idbag、list不支持。
set、map和idbag支持数据库排序,list不支持。
<set name="images" table="IMAGES" lazy="true" order-by="FILENAME asc" >
    <key column="CUSTOMER_ID"  />
    <element column="FILENAME" type="string" not-null="true" />
</set>

//sort也可以自定比较器,该类需实现Comparator接口。
<map name="images" table="IMAGES" lazy="true" sort="true">
    <key column="CUSTOMER_ID"  />
    <map-key column="IMAGE_VALUE" type="string"   />
    <element column="FILENAME"  type="string" not_null="true">
</map>

尽管Hibernate并不强迫所有的组件类都必须重新实现equals()和hasCode()方法,但为使程序更加健壮,建议为所有的组件类实现equals()和hasCode()方法。

组件类的映射类型:
<set name="image" table="IMAGE" lazy="true" order-by="IMAGE_NAME asc">
    <key column="CUSTOMER_ID"/>
    <composite-element class="Image">
      <parent name="customer" />  //映射image中customer的属性
      <property name="name" column="IMAGE_NAME" not-null="true" />
      ....
    </composite-element>
</set>

在双向多关联映射中,必须把其中一端的inverse属性设为true。inverse属性为false的一端可以使用<set>、<idbag>、<list>和<map>元素。而inverse=true的一端则只能使用<set>和<idbag>。

Hibernate在检索一个对象时立即检索与之相关的对象,这种检索策略成为立即检索策略。立即检索策略存在两大不足:select语句的数目太多,需频繁地访问数据库,会影响检索性能。这种检索策略没有利用SQL的连接查询功能;在应用逻辑只需要访问对象,不需要访问与之关联的对象,加载与之关联的对象是多余的操作,会浪费很多内存空间。
未解决以上两大问题,Hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用SQL的外连接查询功能,能减少select语句数目。

检索策略的作用域:类级别和关联级别。
类级别可选的检索策略:立即检索和延迟检索;默认检索策略是延迟检索,而且只有在使用Session.load()方法时才会延迟检索。
关联级别可选的检索策略:立即检索、延迟检索和迫切左外连接检索。默认检索策略是延迟检索,它影响所有的方法。

一对多和多对多关联的检索策略
                   映射文件中用于设定检索策略的几个属性
lazy  
类级别:<class>元素中lazy的可选值:true(延迟检索、默认)false(立即检索)
一对多关联级别<set>元素中lazy的可选只为:true(延迟检索、默认)、false(立即检索)和extra(增强延迟检索) 
多对一关联级别:<many-to-one>元素中lazy的属性可选为:proxy(延迟检索)、no-proxy(无代理延迟检索)和false(立即检索),默认值为true
fetch
类级别:无
一对多关联关系:<set>元素中fetch属性的可选值为:select(查询语句、默认)、subselect(带子句的查询语句)和join(迫切左外连接检索)
多对一关联级别:<many-to-one>元素中lazy属性的可选值为:select(查询语句、默认)和join(迫切左外连接检索)。
batch-size
设定批量检索的数量。可选值为一个正整数,默认值为1。若设定此项。合理的取之在3~10之间。仅适用于关联级别的立即检索和延迟检索。在<class>和<set>元素中包含此属性。

Hibernate允许在应用程序中以编程方式显式设定检索策略。程序代码中的检索策略会覆盖映射文件中配置的检索策略。

若程序加载一个持久化对象的目的是为了访问它的属性,可以采用立即检索。若程序加载一个持久化对象的目的是为了获得它的引用,可以采用延迟检索。

<set name="orders" inverse="true"  lazy="false" fetch="subselect">
    <key column="CUSTOMER_ID"  />
    <one-to-many class="Order" />
</set>
若fetch设为join,则lazy属性被忽略
若fetch设为subselect时,则batch-size属性被忽略

当使用延迟检索时,有两种情况对象的属性引用的集合代理类实例被初始化:当应用程序第一次访问它;通过org.hibernate.Hibernate类的initialize()静态方法初始化它。

增强延迟检索策略与延迟检索策略的主要区别在于增强延迟检索策略能进一步延迟对象的集合代理类实例的初始化时间。


多对一和的一对一关联的索引策略
                   设置多对一关联的检索策略
lazy属性          fetch属性          检索对象时对关联的对象使用的检索策略
proxy        取默认值select        延迟检索
no-proxy     取默认值select        无代理延迟检索
false        取默认值select        立即检索
未显式设置     join                 迫切左外连接检索

对于一对一关联,若使用延迟加载策略,必须把<one-to-one>元素的constrained属性设为true。

在属性级别也就可设置检索策略。在对象-关系映射文件中,<property>和<component>元素的lazy属性若为true,表示采用延迟加载。若为false,则采用立即加载策略。默认是false。属性级别的延迟检索策略使用于二进制大对象、字符串大对象及大容量组件类型的属性。

立即检索
优点:对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以方便地从一个对象导航到与它关联的对象
缺点:select语句数目多;可能会加载应用程序不需要访问的对象
优先考虑使用的场合:类级别;应用程序需要立即访问的对象;使用了第二季缓存。

延迟检索
优点:由应用程序决定需要加在哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并能节省内存空间。
缺点:应用程序如果希望访问游离状态的代理类实例,必须保证它在持久化状态时已被初始化。
优先考虑使用的场合:一对多或多对多关联;应用程序不需要立即访问或者根本不会访问的对象。

迫切左外连接检索
优点:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地从一个对象导航到与它关联的对象;使用了外连接,select语句数目少
缺点:可能会加载应用程序不需要访问的对象,白白浪费很多内存空间;复杂的数据库表连接也会影响检索性能
优先考虑使用的场合:多对一或一对一关联;应用程序需要立即访问的对象;数据库系统具有良好的表连接性能

Hibernate提供了以下几种检索对象的方式:
导航对象图检索方式:根据已经加载的对象,导航到其他对象。
OID检索方式:按照对象的OID来检索对象。Session的get()和load()方法提供了这种功能。
HQL检索方式:使用面向对象的HQL查询语言。Hibernate还提供了Query接口,是专门的HQL查询接口,能执行各种复杂的HQL查询语句。
QBC检索方式:使用QBC(Query By Criteria)API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
本地SQL检索方式:使用本地数据库的SQL查询语句。Hibernate会负责把检索到的JDBC ResultSet结果集映射为持久化对象图。

HQL具有以下功能:在查询语句中设定各种查询条件;支持投影查询,即仅检索出对象的部分属性;支持分页查询;支持连接查询;支持分组查询,允许使用having和group by关键字;提供内置聚集函数;能够调用用户定义的SQL函数或标准SQL函数;支持子查询,即嵌入式查询;支持动态绑定参数。
HQL检索方式包括以下步骤:
通过Session的createQuery()方法创建一个Query对象,它包含一个HQL查询语句。
动态绑定参数。Query接口提供了给各种类型的命名参数赋值的方法。
调用Query的list()方法执行查询语句。该方法返回java.util.List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。

HQL和SQL本质是不一样的:HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息,把HQL查询语句翻译成相应的SQL语句。HQL查询语句中的主体是与模型中的类及类的属性。SQL查询语句是与关系数据库绑定在一起的。SQL查询语句中的主体是数据库表及表的字段。

QBC API只要由org.hibernate.Criteria接口、org.hibernate.criterion.Criterion接口和org.hibernate.criterion.Restrictions类组成,支持在运行时动态生成查询语句。
QBC检索方式包括以下步骤:
调用Session接口的createCriteria()创建一个Criteria对象
设定查询条件。Restrictions类提供了一系列用于设定查询条件的静态方法,这些静态方法都返回Criterion实例,每个Criterion实例代表一个查询条件。Criterion接口的add()方法用于加入查询条件。
调用Criteria接口的list()方法执行查询语句。该方法返回java.util.List类型的查询结果,在List集合中存放了符合条件的持久化对象。
//创建一个Criteria对象
Criteria criteria = session.createCriteria(Customer.class);

//设定查询条件,然后把查询条件加入到Criteria中
Criterion criterion1 = Restrictions.like("name","T%");
Criterion criterion2 = Restrictions.eq("age","new Integer(21)");

criteria = criteria.add(criterion1);
criteria = criteria.add(criterion2);

//执行查询语句,返回查询结果
List result = criteria.list();

Hibernate还提供了QBE(Query By Example)检索方式,它是QBC的子功能。QBE允许先创建一个对象模版,然后检索出所有和这个模板相同的对象,
Customer exampleCustomer = new Customer();
exampleCustomer.setAge(23);
List result = session.createCriteria(Custmer.class)
                     .add(Example.create(exampleCustomer))
                     .list();
QBE适用于查询窗口中,让用户输入一些列的查询条件,然后返回匹配的对象。但QBE只支持"="和"like"比较运算符。

Query和Criteria接口都提供了用于分页获取查询结果的方法。
setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0。在默认情况下,Query和Criteria接口从查询结果中的第一个对象,也就是索引位置为0的对象开始检索。
setMaxResult(int maxResult):设定一次最多检索出的对象数目。在默认的情况下,Query和Criteria接口检索出查询结果中所有的对象。

Query和Criteria接口都提供了一下用于执行查询语句并返回查询结果的方法。
list()方法:返回一个List类型的查询结果,在List集合中存放了所有满足查询条件的持久化对象。
uniqueResult()方法:返回单个对象
Customer customer = (Customer)session.createQuery("from Customer c order by c.name asc)
                                     .uniqueResult();
Query接口还提供了一个iterator()方法,它和list()方法一样,也能执行查询操作。iterator()和list()的区别在于两者使用的查询机制不一样。
Query的iterate()方法仅在满足一下条件的场合,可以稍微提高查询性能:表中包含大量字段;启用了第二级缓存,第二级缓存中可能包含了带查询的对象。
iterator()对象一直处于打开状态,在以下情况被关闭:遍历访问完结果集中的多有对象;关闭Session对象;通过org.hibernate.Hibernate.close(iterator)方法关闭Iterator对象。

JDBC API提供了一种可滚动的结果集,它是利用数据库系统中的游标来实现的。游标用于定位查询结果集中的记录,应用程序可以通过任意移动游标来定位到特定记录。

猜你喜欢

转载自forever1121.iteye.com/blog/2116498
今日推荐