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. 环境搭建 ...
随机推荐
- 测试网中用户添加docker yum源
/etc/yum.repo.d 中新建docker.repo 添加 [docker]name=CentOS-$releasever - Mediabaseurl=ftp://10.191.51.X/d ...
- c++11 Thread库写多线程程序
一个简单的使用线程的Demo c++11提供了一个新的头文件<thread>提供了对线程函数的支持的声明(其他数据保护相关的声明放在其他的头文件中,暂时先从thread头文件入手吧),写一 ...
- ASP.NET打开项目错误:将指定的计数添加到该信号量中会导致其超过最大计数。
1.错误如图 2.解决方案 重启IIS即可,运行-> 输入IISRESET 命令 即可重启IIS,如图
- Educational Codeforces Round 27 D. Driving Test
单调栈 题意看了半天... #include <cstdio> #include <cstdlib> #include <cmath> #include <c ...
- Javascript加载talbe(包含分页、数据下载功能)
效果图如下: 首先简单说明一下,后面会给所涉及到的代码都贴上来的. 1.excel图标是一个用户控件,用来触发下载 2.首页.上页......每页多少条,这一块是一个整体,你可以选择放置在表格下面,或 ...
- thinkphp 空控制器
空控制器的概念是指当系统找不到请求的控制器名称的时候,系统会尝试定位空控制器(EmptyController),利用这个机制我们可以用来定制错误页面和进行URL的优化. 大理石平台价格表 现在我们把前 ...
- angular2 组件内容嵌入(ng-content)
一.简介 内容嵌入是组件的一个高级功能特性,使用组件的内容嵌入特性能很好地扩充组件的功能,方便代码的复用. 二.用法 如上,在模版中使用了<ng-content>标签,这个标签就是用来渲染 ...
- ListenerExecutionFailedException: Listener threw exception
rabbitmq 监听的队列名称写错导致404找不到队列
- Java-Maven-pom.xml-project-packaging:packaging(war/jar)
ylbtech-Java-Maven-pom.xml-project-packaging:packaging(war/jar) 1.返回顶部 1.packaging 1.1 war <!-- 打 ...
- c++中变量、变量名、变量地址、指针、引用等含义
首先了解内存,内存就是一排房间,编号从0开始,0,1,2,3,4,5...... 房间里面一定要住人,新人住进去了,原来的人就走了:不管你住不住,里面都有人. 编号就是地址.里面的人就是内容,为了我们 ...