`
bjlf1105
  • 浏览: 24730 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate缓存策略之1+N(一)

阅读更多

一级缓存中的1+N问题

所谓1+N指的就是:一条查询实体对象的ID列表的查询语句和迭代查询具体的多个实体对象的查询语句

  • session的load/get或iterate操作会利用缓存,如果缓存中已有实体对象,将不再发出查询语句查询实体对象
  • session的list操作将不会利用缓存,每次查询,都会发出查询语句
  • 如果查询实体对象,则list操作直接发查询语句把实体对象加载到内存,而iterate操作先发查询语句查ID列表,再发查询语句根据ID逐个查询实体对象
  • 如果查询的是普通结果集,则list和iterate操作将没有区别

看看下面的代码及描述:

//list()操作,hibernate会马上发出查询语句查询所有的实体对象到内存中!


List persons = 
	session.createQuery("select p from Person p").list();


for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}

打印结果是这样的:

Hibernate: select person_.id as id0_, person_.name as name0_, person_.address as address0_, person_.qq as qq0_, person_.groupId as groupId0_ from t_person person_
小龙哥

小马哥

神马哥

-----------------------------------------------------------------------------------------

 那么iterate操作呢:

//用iterate操作查询实体对象的时候,首先会发出一条查询语句查询实体对象的ID列表
Iterator iterator = 
	session.createQuery("select p from Person p").iterate();
for (; iterator.hasNext();) {	
//当迭代访问具体的某个实体对象的时候,hibernate再次发出查询语句查询此实体对象的数据!
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}
 

Hibernate: select person_.id as col_0_0_ from t_person person_这个是查询id的语句

以下是查找具体对象的3条语句
Hibernate: select person_.id as id0_0_, person_.name as name0_0_, person_.address as person_0_, person_.qq as qq0_0_, contactper0_.groupId as person_0_ from t_person person_ where person_.id=?
小龙哥
Hibernate: select person_.id as id0_0_, person_.name as name0_0_, person_.address as address0_0_, person_.qq as qq0_0_, person_.groupId as groupId0_0_ from t_person person_ where person_.id=?
小马哥
Hibernate: select person_.id as id0_0_, person_.name as name0_0_, person_.address as address0_0_, person_.qq as qq0_0_, person_.groupId as groupId0_0_ from t_person person_ where person_.id=?
神马哥

 

现在来将他们在同一个session中查找两次看看有什么现象?sql语句就不写了

//list()操作,hibernate会马上发出查询语句查询所有的实体对象到内存中!
List persons = 
	session.createQuery("select p from Person p").list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}

//第二次,还是用list操作查询实体对象
//hibernate还会发查询语句查询实体对象
//所以,list操作会把实体对象放入一级缓存,但list操作不利用一级缓存!


persons = session.createQuery("select p from Person p")
	.list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}

那么再看看两个iterate操作

//用iterate操作查询实体对象的时候,首先会发出一条查询语句查询实体对象的ID列表
Iterator iterator = session.createQuery("select p from Person p").iterate();
for (; iterator.hasNext();) {
	//当迭代访问具体的某个实体对象的时候,hibernate再次发出查询语句查询此实体对象的数据!
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}
//第二次用iterate操作
//iterate操作只会再发一条查询ID列表的SQL语句,针对这些实体对象访问的时候,不再发出查询语句
//iterate操作除了能够将实体对象放入一级缓存之外,它还会利用一级缓存!!


iterator = session.createQuery("select p from Person p").iterate();
for (; iterator.hasNext();) {
	//不再发出SQL查询语句!
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}

 看到这样的结果,我们是不是可以把这两个操作结合起来提高查询性能呢?其实是可以的,再看看下面的代码

//list()操作,hibernate会马上发出查询语句查询所有的实体对象到内存中!
List persons = 
	session.createQuery("select p from Person p").list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}
//下面iterate操作,将只发出一条查询ID列表的SQL语句
Iterator iterator = session.createQuery("select p from Person p").iterate();
for (; iterator.hasNext();) {
	//不再发出SQL语句!
	Person p = (Person) iterator.next();
	System.out.println(p.getName());
}

 显然上面的代码分别利用list和iterate的特性,大大提高了数据查询的性能,如果不是list而是get操作,其实是一样的。

 

那如果查询的是一些普通结果集呢?所谓普通结果集就是某实体的某些属性,而上面查找的都是实体,看看下面的代码:

//如果查询的不是实体对象,而是一些普通的结果集,则list操作和iterate操作将没有区别
//不管是List还是iterate操作,每次查询,都会发出SQL语句!!!不再利用一级缓存!!

//也就是说,一级缓存中缓存的数据只是实体
对象,而不是一般的普通结果集!

List persons = 
	session.createQuery("select p.id,p.name from Person p").list();
for (Iterator iterator = persons.iterator(); iterator.hasNext();) {
	Object[] p = (Object[]) iterator.next();
	System.out.println(p[0]+","+p[1]);
}
//如果查询的不是实体对象,而是一些普通的结果集,则list操作和iterate操作将没有区别

Iterator iterator = session.createQuery("select p.id,p.name from Person p").iterate();
for (; iterator.hasNext();) {
	Object[] p = (Object[]) iterator.next();
	System.out.println(p[0]+","+p[1]);
}
 

 

 

 

 

分享到:
评论

相关推荐

    马士兵hibernate学习笔记(原版)

    目录 课程内容 1 HelloWorld 2 Hibernate原理模拟 - 什么是O/R Mapping以及为什么... 4 一级缓存和二级缓存和査询缓存(面试题)(详见hibernate_3000_Hibernate_3KindsOf_Cache) 5 事务并发处理(面试的意义更大)

    彻底解决hibernate常见难点.zip

    Hibernate处理1-N关系时保存技巧、Hibernate缓存机制、Hibernate批量处理数据、Hibernate三种继承映射策略、hibernate映射体系、Hibernate主键生成策略、持久层DAO设计建议、基于xml文件的bean、使用HibernateAPI在...

    Hibernate 课件及源代码

    内容涵盖安装 Hibernatetools 插件、Session 核心方法、持久化对象生命周期、对象关系映射(1-n、1-1、n-n、继承映射)、检索策略、检索方式(对象导航图、OID 检索、HQL、QBC、本地SQL)、Hibernate 一\二级缓存、...

    hibernate总结

    a) 不在一级缓存之中 b) 数据库可能有记录和它对应,也可能没有记录和它对应 c) 从一个持久态对象转化过来的,从session的一级缓存中出来的,因为调用了session的一些方法,产生了这种对象(session.close()) ...

    通俗易懂的Hibernate教程(含配套资料)

    内容涵盖安装 Hibernatetools 插件、Session 核心方法、持久化对象生命周期、对象关系映射(1-n、1-1、n-n、继承映射)、检索策略、检索方式(对象导航图、OID 检索、HQL、QBC、本地SQL)、Hibernate 一二级缓存、...

    jdbc基础和参考

    3.hibernate的一级缓存 4.介于Connection和Transaction之间的一个对象 5.hibernate中用来做持久化操作的 SessionFactory 1.重量级的,创建和销毁需要消耗很大的资源,不建议频繁创建和销毁 2.线程安全的,一个...

    低清版 大型门户网站是这样炼成的.pdf

    5.8.4 hibernate二级缓存的并发访问策略 333 5.8.5 hibernate的二级缓存配置 334 5.9 hibernate应用的性能优化 336 5.10 多数据源的应用 338 5.11 jdbc的应用 343 5.12 hibernate调用存储过程 343 5.13 xml...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    SSH 为 Struts+Spring+Hibernate的一个集成框架,是目前较流行的一种Web应用程序开源框架。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久...

    NHibernate参考文档 2.0.0 chm

    1. 第一个NHibernate应用程序 1.1. 开始NHibernate之旅 1.2. 第一个持久化类 1.3. 映射cat 1.4. 与Cat同乐 1.5. 总结 2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. 上下文相关的...

    iBATIS实战

    6.2.3 避免N+1查询问题 105 6.3 继承 107 6.4 其他用途 109 6.4.1 使用语句类型和DDL 109 6.4.2 处理超大型数据集 109 6.5 小结 115 第7章 事务 116 7.1 事务是什么 116 7.1.1 一个简单的银行转账示例 116 7.1.2 ...

    应用层查询语言PHP库.zip

    <...如果只使用中心缓存,只能减小数据库的压力,对于网络带宽的压力,还是有的,速度上也远远逊于本地缓存的效果,所以要结合本地缓存+中心缓存的策略方案,即提高速度,避免群集复制时的瓶颈。

Global site tag (gtag.js) - Google Analytics