hibernate抓取策略
抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。
- <span style="font-size: large;">s = sessions.openSession();
- Transaction tx = s.beginTransaction();
- User u = (User) s.createQuery("from User u where u.name=:userName") .setString("userName", userName).uniqueResult();
- Map permissions = u.getPermissions();
- tx.commit();
- s.close();
- Integer accessLevel = (Integer) permissions.get("accounts"); // Error!</span>
在Session关闭后,permessions集合将是未实例化的、不再可用,因此无法正常载入其状态。 Hibernate对脱管对象不支持延迟实例化. 这里的修改方法是:将permissions读取数据的代码 移到tx.commit()之前。
除此之外,通过对关联映射指定lazy="false",我们也可以使用非延迟的集合或关联。但是, 对绝大部分集合来说,更推荐使用延迟方式抓取数据。如果在你的对象模型中定义了太多的非延迟关联,Hibernate最终几乎需要在每个事务中载入整个数据库到内存中!
但是,另一方面,在一些特殊的事务中,我们也经常需要使用到连接抓取(它本身上就是非延迟的),以代替查询抓取。 下面我们将会很快明白如何具体的定制Hibernate中的抓取策略。在Hibernate3中,具体选择哪种抓取策略的机制是和选择 单值关联或集合关联相一致的。
2. 调整抓取策略(Tuning fetch strategies)
查询抓取(默认的)在N+1查询的情况下是极其脆弱的,因此我们可能会要求在映射文档中定义使用连接抓取:
- <span style="font-size: large;"><set name="permissions" fetch="join">
- <key column="userId"/>
- <one-to-many class="Permission"/>
- </set>
- <many-to-one name="mother" class="Cat" fetch="join"/> </span>
在映射文档中定义的抓取策略将会对以下列表条目产生影响:通过get()或load()方法取得数据。只有在关联之间进行导航时,才会隐式的取得数据。
条件查询,使用了subselect抓取的HQL查询
不管你使用哪种抓取策略,定义为非延迟的类图会被保证一定装载入内存。注意这可能意味着在一条HQL查询后紧跟着一系列的查询。
通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用HQL的左连接抓取(left join fetch) 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询 API中,应该调用 setFetchMode(FetchMode.JOIN)语句。
也许你喜欢仅仅通过条件查询,就可以改变get() 或 load()语句中的数据抓取策略。例如:
- <span style="font-size: large;">User user = (User) session.createCriteria(User.class) .
- setFetchMode("permissions", FetchMode.JOIN).
- add( Restrictions.idEq(userId) ).uniqueResult(); </span>
(这就是其他ORM解决方案的“抓取计划(fetch plan)”在Hibernate中的等价物。)截然不同的一种避免N+1次查询的方法是,使用二级缓存。
- <span style="font-size: large;"><?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.javacrazyer.domain.Product" table="product">
- <id name="id">
- <generator class="native"/>
- </id>
- <version name="version"/>
- <property name="name"/>
- <property name="unitCost" column="unit_cost"/>
- <property name="pubTime" column="pub_time"/>
- <!-- 映射多对一 -->
- <many-to-one name="cate" column="cate_id" fetch="join"/>
- </class>
- </hibernate-mapping></span>
- <span style="font-size: large;">select tab1.xx,tab1.yy,tab2.aa,tab2.cc
- from product tab1
- inner join category tab2
- on tab1.cate_id=tab2.id
- where product_id=?</span>
- <span style="font-size: large;"><?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.javacrazyer.domain.Category" table="category" batch-size="10">
- <id name="id">
- <generator class="native"/>
- </id>
- <version name="version"/>
- <property name="name"/>
- <property name="description"/>
- <!-- 映射集合属性 -->
- <bag name="productList" inverse="true" fetch="subselect">
- <key column="cate_id"/>
- <!-- 映射一对多 -->
- <one-to-many class="com.javacrazyer.domain.Product"/>
- </bag>
- </class>
- </hibernate-mapping></span>
当使用get()或load()方法加载一个Category实体数据时,它对关联的Product集合属性先延迟加载,当真正需要使用 Product集合属性中的数据时,才再发送一条SQL语句来抓取数据; 当使用HQL语句加载多个CategoryShiite数据时,对它们关联的Product集合属性先延迟加载,当真正需要使用Product集合属性的数据时,才会再发送一条子查询语句来抓取相应的数据
hibernate抓取策略的更多相关文章
- Hibernate 抓取策略fetch-1 (select join subselect)
原文 :http://4045060.blog.51cto.com/4035060/1088025 部分参考:http://www.cnblogs.com/rongxh7/archive/2010/0 ...
- 029 hibernate抓取策略
实例A引用实例B,B如果是代理的话(比如多对一关联中):如果遍历A的查询结果集(假设有10条记录),在遍历A的时候,访问B变量,将会导致n次查询语句的发出!这个时候,如果在B一端的class上配置ba ...
- Hibernate 抓取策略
抓取策略: 为了改变SQL语句执行的方式 当应用程序需要在Hibernate实体对象的关联关系间进行导航的时候,Hibernate如何获取关联对象的策略 抓取策略可以在O/R映射的元数据中声明,也可以 ...
- Hibernate 抓取策略fetch-2 (批量抓取batch-size以及hibernate.jdbc.fetch_size、hibernate.jdbc.batch_size)
类关系: User N~1 Group 测试代码: System.out.println("1"); List stuList = session.createQuery(&quo ...
- Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)
假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: Session session=H ...
- 【Java EE 学习 48】【Hibernate学习第五天】【抓取策略】【二级缓存】【HQL】
一.抓取策略. 1.hibernate中提供了三种抓取策略. (1)连接抓取(Join Fetch):这种抓取方式是默认的抓取方式.使用这种抓取方式hibernate会在select中内连接的方式获取 ...
- 【Hibernate 8】Hibernate的调优方法:抓取策略
在上一篇博客中,介绍了Hibernate的缓存机制.合理的配置缓存,可以极大程度上优化Hibernate的性能.这篇博客,介绍另外一个调优方式:抓取策略. 一.什么是抓取策略 抓取策略(fetchin ...
- Hibernate中的多表查询及抓取策略
1.Hibernate中的多表查询 1.1SQL中的多表查询 [交叉连接] select * from A,B; [内连接] 显示内连接:inner join(inner 可以省略) Select * ...
- Hibernate框架笔记04HQL_QBC查询详解_抓取策略优化机制
目录 1. Hibernate的查询方式 1.1 方式一:OID查询 1.2 方式二:对象导航查询 1.3 方式三:HQL方式 1.4 方式四:QBC查询 1.5 方式五:SQL查询 2. 环境搭建 ...
随机推荐
- [eJOI2018]元素周期表
题目 \((r_1,c_1),(r_2,c_1),(r_1,c_2)\)三个格子存在就说明\((r_2,c_2)\)存在,如果我们将\(r_1,c_2,c_1,r_2\)都看成一些点的话,那么这个关系 ...
- 【csp】2017-12
第一题:游戏 题目: 题意:啊,不多赘述.看的懂. 题解:sort一下直接暴力比较大小. 代码: #include<iostream> #include<cstdio> #in ...
- selenium基础-跳过验证码
selenium基础-跳过验证码 一.方法 设置万能验证码或者屏蔽验证码(最常用的方法) 使用验证码识别工具识别验证码 通过selenium操作cookies 直接使用配置文件的webdriver 二 ...
- "_CMTimeGetSeconds", referenced from:
CMTime is defined in the CoreMedia.framework. Add that framework to your project.
- vue-router如何参数传递
1.我们用<router-link>标签中的to属性进行传参,需要您注意的是这里的to要进行一个绑定,写成:to 先来看一下这种传参方法的基本语法: <router-link :to ...
- 传统的dom的渲染方式
DOM渲染的过程大致分为三个阶段: 后端渲染 前端渲染 独立DOM渲染(前后端相结合渲染) 1.后端渲染:DOM树的生成完全是在后端服务器中完成的,后端服务器的程序会把需要的数据拼合成一个类似于前端D ...
- drupal7权限控制之-如何访问未发表的node
在某些特殊需求的情况下,会涉及到匿名用户或非node节点所有者,访问未发表的node节点的需求:或者需要根据不同的用户角色,访问不同的内容类型等,如果不想安装node_access等模块的时候,可以在 ...
- bootstrap-----流体布局解析
流体布局容器 容器的width为auto,只是两边加了15px的padding. 流体布局容器 容器的width为auto,只是两边加了15px的padding. <div class=&quo ...
- lxhgww的奇思妙想 长链剖分板子
https://vijos.org/d/Bashu_OIers/p/5a79a3e1d3d8a103be7e2b81 求k级祖先,预处理nlogn,查询o1 //#pragma GCC optimiz ...
- 二分图建图,并查集求联通——二维等价性传递 cf1012B好题!
/* 模拟二分图:每个点作为一条边,连接的是一列和一行(抽象成一个点,列在左,行在右) 由题意得 a-b相连,a-c相连,b-d相连,那么d-c就不用再相连了 等价于把二分图变成联通的需要再加多少边 ...