精通Hibernate——Hibernate的检索策略

来源:互联网 发布:python 遍历数组 编辑:程序博客网 时间:2024/06/13 01:29

在Session的缓存中存放的是互相关联的对象图。在默认情况下,当Hibernate从数据库中加载Customer对象时,会同时加载所有关联的Order对象,下面我们以Order和Customer为例介绍如何配置Hibernate的检索策略,以优化检索性能。 
Session有三种检索方法:load,get和find,他们都用来从数据中检索对象。load和get按照参数指定的OID加载一个持久化对象,find按照参数指定的HQL语句加载一个或多个持久化对象,如下:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Customer customer = (Customer)session.load(Customer.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Long</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));Customer customer = (Customer)session.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(Customer.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Long</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));List customerList = session.find(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"from Customer as c where c.id = 1"</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

当Hibernate执行以上方法时,需要获得以下信息 
1.类级别检索策略:Session的load、get或find方法直接指定检索的是Customer对象,对Customer对象到底采用立即检索还是延迟检索。 
2.关联检索策略:对与Customer关联的Order对象,即Customer对象orders集合,到底采用立即检索还是延迟检索或者迫切左外连接检索,详细介绍如下: 
这里写图片描述 
三种检索策略的运行机制 
这里写图片描述 
下面详细介绍各种检索方式 
1、类级别的检索策略 
立即检索 
类级别默认为立即检索,如下两种配置都为立即检索策略:

<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><<span class="hljs-type" style="box-sizing: border-box;">class</span> <span class="hljs-property" style="box-sizing: border-box;">name</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.Customer"</span> table=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CUSTOMER"</span> /><<span class="hljs-type" style="box-sizing: border-box;">class</span> <span class="hljs-property" style="box-sizing: border-box;">name</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.Customer"</span> table=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CUSTOMER"</span> lazy=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"false"</span> /></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

当通过session的load方法检索Customer对象时:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Customer customer = (Customer)session.load(Customer.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Long</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

Hibernate会立即查询Customer表

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> CUSTOMER <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> id = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>和<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> ORDERS <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> customer_id = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

延迟检索 
修改以上配置如下:

<code class="hljs fsharp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> name=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.Customer"</span> table=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CUSTOMER"</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">lazy</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span> /></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

当执行session的load方法时,Hibernate不会立即查询CUSTOMER表的select语句,仅仅返回Customer类的代理类的实例,这个代理类具有以下特征: 
1.由Hibernate在运行时动态生成,他扩展了Customer类,因此他继承了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。 
2.当Hibernate创建Customer代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类占用内存很少 
3.当应用程序第一次访问Customer代理类实例时,Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库加载Customer对象所有数据。但有个例外,那就是当应用程序访问Customer代理类的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例的时候OID就有已经存在了,不必去数据库中查询。 
2、一对多和多对多关联的检索策略 
在映射文件中,用set元素来配置一对多关联多对多关联关系。Customer.hbm.xml,如下:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span> name=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"orders"</span> inverse=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span> >    <<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">key</span> column=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"customer_id"</span> />    <one-<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span>-many <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.Order"</span> /></<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span>></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

set元素有个lazy和outer-join属性,下面具体说明: 
这里写图片描述 
批量延迟检索和批量立即检索 
set元素有一个batch-size属性,用于为延迟检索或者立即检索策略设定批量检索的数量。批量检索能减少select语句的数目,提高检索的性能。 
session的find方法用于检索所有的Customer对象,在set元素的lazy属性有true和false来控制延迟加载还是立即加载。 
3、迫切左外连接检索 
如果把set元素的outer-join属性设置为true

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">set</span> name=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"orders"</span> inverse=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span> outer-<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">join</span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span> /></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

当检索Customer对象时,采用迫切左外连接策略来检索所有关联的Order对象,对于以下程序:

<code class="hljs vbnet has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">customer = (Customer)session.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(Customer.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Long</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

当运行session.get()方法时,执行以下以下sql:

<code class="hljs sql has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-operator" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> * <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> customers <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">left</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">outer</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">join</span> orders <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span> customer_id = orders.customer_id <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">where</span> customer_id = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

需要注意的是session的find方法会忽略映射文件中配置的迫切左外连接检索策略,即使以上set的outer-join配置为true,对于以下代码:

<code class="hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">List</span> customerList = session.find(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"from Customer as c"</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

仍然采用立即检索策略。

转载地址:http://blog.csdn.net/fuyuwei2015/article/details/48174195?ref=myread

0 0
原创粉丝点击