[转]Hibernate3如何解决n+1 selects
Hibernate3中取得多层数据的所产生的n+1 selects问题的解决:
其实这个问题在Hibernate in Action中已经有很多种解决办法了。但我觉得其中最好的办法是用Criteria
的FetchMode来解决,但是Hibernate in Action中写的很不详细。我昨晚试了好长时间来的到答案。下
面总结一下。
需求这样的,我有四张表(one,two,three,four)从one一直外键关联到four。结构如下

现在在Session中得到One,并从One里一直取到Four里的内容。如果简单的用Session.get来实现是这
样的。
Java代码
这样我在Session关闭后返回的One里是从One到Four的信息都有的。
然而这样做所导致的结果是生成大量的SQL查询,这是一个典型的n+1 Selects问题。如果系统结构层次多,符合条件的记录多,那么Hibernate为你生成的SQL查询将是难以接受的。
对于这个例子生成的SQL是这样的
SQL代码
对于这样的问题,在没有Hibernate以前我们一般都用jdbc来做,那样的话我们其实用一个进行3次join
的sql语句就可以实现,但 是这样解决也有问题,就是返回的ResultSet中的数据非常多,而且杂乱,其
实是从one到four平行排列的。对于这样的结果集我们要把它手动影射 曾对象结构也是一个很复杂的操
作。
幸好Hibernate3可以为我们做这些事情(我再一次被Hibernate的强大所震撼)。
上面的实现可以用Criteria来实现: Java代码
这里的重点是这句话
criteria.setFetchMode("twos",FetchMode.JOIN).
setFetchMode("twos.threes",FetchMode.JOIN).
setFetchMode("twos.threes.fours",FetchMode.JOIN).uniqueResult();
在用Criteria之前先设置FetchMode,应为Criteria是动态生成sql语句的,所以生成的sql就是一层层Join
下去的。
setFetchMode(String,Mode)第一个参数是association path,用"."来表示路径。这一点具体的例子
很少,文档也没有写清楚。我也是试了很久才试出来的。
就这个例子来所把因为取道第四层,所以要进行三次setFetchMode
第一次的路径是twos,一位one中有two的Set。这个具体要更具hbm.xml的配置来定。
第二个路径就是twos.threes
第三个就是twos.threes.fours
一次类推,一层层增加的。
这样做法最终生成的SQL是这样的:
SQL代码
虽然很长但是只有一条SQL语句。性能要好很多。Hibernate的强大之处是它会把返回的ResultSet自动
影射到你的对象模型里面去。这就为我们省了很多事。
看来Hibernate真是一个耐人寻味的Framework啊。
[转]Hibernate3如何解决n+1 selects的更多相关文章
- Hibernate3疑惑解决
1.session的get()和load()有什么区别? # get()如果没有找到持久化类返回null,有可能导致空指针异常. # load()如果没有找到持久化类直接抛出异常. ...
- Hibernate批量操作(二)
Hibernate提供了一系列的查询接口,这些接口在实现上又有所不同.这里对Hibernate中的查询接口进行一个小结. 我们首先来看一下session加载实体对象的过程:Session在调用数据库查 ...
- Java_SSH项目主要步骤记录
建立Spring-Struts-Hibernate的步骤整理 1. 建立web project 2. 建立hernate, action, service包 3. 右击项目,add myeclipse ...
- Maven 开发hibernate存在的诸多问题
项目结构: 开发平台: maven version 3.5 eclipse 4. 7 oxyen 最新:hibernate 5.x 引入问题 官网提供的必需选择只有 这个 当然还需要我们单独配置mys ...
- org.springframework.orm.hibernate3.LocalSessionFactoryBean的疑惑解决办法
在项目中使用了SSH框架(Struts2 + Spring3+ Hibernate3),applicationContext中配置了sessionFactory <bean id="s ...
- 使用myeclipse自动导入hibernate3的jar包,如何关联hibernate源码的解决办法
1.在网上找了好久,今天终于解决了,如果你的myeclipse自动生成的添加hibernate3jar包时,依靠通常的方法是无法关联其相应版本的源代码的,就是你在编写代码是,按住ctrl + hibe ...
- 如何利用hibernate3解决数据库丢失更新问题?
首先我们要明白什么叫丢失更新. 比如数据库有一个person表,里面有一条这样的数据 "5 zhangsan shenzhen"; 现在有两个事务A.B同时查找了这一条记录: A事 ...
- 解决 spring mvc 3.0 结合 hibernate3.2 使用<tx:annotation-driven>声明式事务无法提交的问题(转载)
1.问题复现 spring 3.0 + hibernate 3.2 spring mvc使用注解方式:service使用@service注解 事务使用@Transactional 事务配置使用 < ...
- 解决 spring mvc 3.+ 结合 hibernate3.+ 使用<tx:annotation-driven>声明式事务无法提交的问题
spring mvc使用注解方式:service使用@service注解 事务使用@Transactional 事务配置使用 <tx:annotation-driven transaction- ...
随机推荐
- buildroot mysql
/******************************************************************** * buildroot mysql * 说明: * 这两天要 ...
- JDBC接口规范
前言 JDBC(JavaDatabase Connectivity)表示Java查询引擎连接,由一组用Java编程语言编写的类和接口组成.JDBC为Java程序访问关系型查询引擎提供了编程接口,为查询 ...
- PAT (Basic Level) Practise:1004. 成绩排名
[题目链接] 读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3 ...
- UI学习笔记---第八天
UINavigationController的用法 界面间传值 UInavigationController继承于UIViewController,以栈的方式管理所控制的师徒控制器,至少要有一个被 ...
- 转载:LBP代码详细注释
%LBP returns the local binary pattern image or LBP histogram of an image.% J = LBP(I,R,N,MAPPING,MOD ...
- 350. Intersection of Two Arrays II
Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...
- hdu1059 Dividing ——多重背包
link:http://acm.hdu.edu.cn/showproblem.php?pid=1059 最简单的那种 #include <iostream> #include <cs ...
- 关于JSP的C标签之forEach循环分隔符
页面中可能说出现在forEach循环中间需要出力分隔符的问题, 比如: 小明 1年级,小王 2年级, 小张 3年级(循环单位是 ${bean.name} ${bean.class}) 此时的逗号出力, ...
- linux网络故障解决方法
一.检测工具 tcpdump:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的“头”完全截获 ...
- C++@冒号(:)和双冒号(::)的用法
转自:http://blog.csdn.net/zimingjushi/article/details/6549390 1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) ty ...