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

Query.iterator()的N+1问题的解决:Hibernate Iterator JCS分析

阅读更多
JCS(Java Caching System)是一个对象Cache,它可以把Java对象缓存起来,提高那些访问频率很高的Java对象的存取效率。JCS是按照对象的唯一标示来存取对象的,比如说可以按照对象的hashCode来存取。

对于Hibernate来说,可以利用JCS来缓存查询结果,这样当下次访问同样的数据,就无须去数据库取,直接从JCS中取出来,加快了查询速度。

当Hibernate使用List或者Iterator方式来第一次读取数据的时候,JCS是空的,此时不管是List方式还是Iterator方式都会往JCS里面填充查询出来的持久对象,例如:

select c from Cat as c



select c.id, c.name from Cat as c

这种HQL语句不构造PO,因此不会去填充JCS。

好了,现在JCS里面填好了数据,但是该怎么取呢?上面我说过是按照对象的唯一标示来存取的,而对于PO持久对象来说,唯一标示就是主键,因此Hibernate首先必须获得主键列表,然后根据主键列表挨个判定,看这个持久对象究竟是在JCS里面还是在数据库里面,假如在JCS里面,那么按照主键取,假如在数据库,那么发送sql取。

现在我们来分析为什么Iterator可以使用JCS,而List不能。上面说了,用JCS之前,要先获得持久对象的主键,才能去JCS里面取持久对象,而我们怎么才能获得主键列表呢?必须去数据库中取得,这一步是没有办法缓冲的。

Hibernate Iterator的查询本身是分为两步的:

==> select id from cat
==> select * from cat where id = ?
==> select * from cat where id = ?
...
==> select * from cat where id = ?

第一步,去数据库中取主键列表,第二步,按照主键一个一个取数据。当然了,我们现在可以看出来,Iterator方式下假如不用JCS的话,那么从数据库中取出n条记录就需要n+1次sql查询,这是非常可怕的事情,因此假如在没有使用JCS的情况下,你又必须一次去取大量数据,应该避免使用Iterator。

而Iterator的第一次sql是取主键列表,这个时间消耗是非常少的,假如使用了JCS,那么每次查询仍然要不可避免的去发送一次sql: select id from cat 去取主键列表,然后呢? 然后Iterator就不会那么傻了,他会先到JCS里面去看看,按照主键去找持久对象,假如有了,直接拿出来用,假如没有,那么只好去数据库中取得,然后再把它填到JCS里面去。

因此可以看出来,JCS有点类似一个内存中的简单对象数据库, Iterator的第一次sql取主键列表是必须要到数据库里面取的,取得了主键这把钥匙以后,Iterator会首先尝试开JCS这把锁,打得开就直接进去,假如打不开,就只好去开数据库这把锁了。

Hibernate List方式是JDBC的简单封装,一次sql就把所有的数据都取出来了,它不会像Iterator那样先取主键,然后再取数据,因此List无法利用JCS。不过List也可以把从数据库中取出的数据填充到JCS里面去。

最佳的方式:第一次访问使用List,快速填充JCS,以后访问采用Iterator,充分利用JCS。

mikeho write:

那JCS是如何和Database保持同步的?

robbin write:

jcs.default.elementattributes.MaxLifeSeconds=240(最大缓冲时间)

超时做作废,另外你在程序里面也可以clear JCS cache
分享到:
评论

相关推荐

    Absolute+C++中文版:完美的C++教程(原书第2版).pdf

    - 迭代器(iterator):用于访问容器元素的方式。 - 算法(algorithm):sort、find等通用算法的使用。 4. **内存管理**: - new/delete操作符的使用。 - 智能指针(shared_ptr/unique_ptr)。 - 内存泄漏的预防与...

    IDEA KeyMap中文版

    ##### 1. **Usage Search** - **Alt+F7 / Ctrl+F7**:显示“用法”查找结果。 - **Ctrl+Shift+F7**:高亮显示用法。 - **Ctrl+Alt+F7**:导航到用法位置。 ##### 2. **Compile and Run** - **Ctrl+F9**:编译...

    java-util-iterator.pdf java-util-iterator.pdf

    本文通过对`java.util.Iterator`接口的深入分析,展示了其在Java集合框架中的重要作用。通过使用`Iterator`模式,我们能够以统一的方式遍历不同类型的集合,同时保持代码的简洁性和可维护性。这对于理解和开发高质量...

    idea 快捷键.docx

    1. **代码补全与智能提示**: - `Ctrl + Space`:基础代码补全,提供类、方法或变量名称的建议。 - `Ctrl + Shift + Space`:智能代码补全,根据上下文和预期类型过滤出可用的方法和变量。 2. **代码完成与信息...

    Java笔记Map,九大内置对象

    1. 使用迭代器 Iterator: ```java Map, String> map = new HashMap(); for (Iterator<Map.Entry, String>> it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry, String> entry = it.next(); System...

    Hibernate几种获数据方法比较

    本文将深入探讨Hibernate中的几种主要的数据获取方式,包括`Session.get()`与`Session.load()`、`Query.iterator()`与`Query.list()`以及使用HQL(Hibernate Query Language)进行查询。 ### 1. `Session.get()`与`...

    struts2+spring2+hibernate3增删改查和分页

    1. **配置环境**:添加SSH2相关的JAR包到项目的类路径中,包括Struts2、Spring和Hibernate的库。 2. **Struts2配置**:创建struts.xml配置文件,定义Action类及其对应的处理方法,配置拦截器栈。 3. **Spring配置*...

    jdbc和hibernate的区别

    4. **适用场景**:Hibernate的Iterator适合大数据量且只需要部分数据的情况,而List适合一次性加载所有数据。 **结论:** 1. 精心优化的JDBC在性能上通常是最佳选择,特别是在读取操作中。 2. Hibernate提供了更高...

    hashMap利用iterator迭代器迭代元素方法

    1. **使用`entrySet()`迭代**: 这是最常见的迭代方式,因为它允许同时访问键和值。首先,通过`hashMap.entrySet()`获取`Entry`对象的集合,然后通过迭代器遍历这些`Entry`。例如: ```java HashMap, Integer> ...

    java.util.ConcurrentModificationException 异常问题详解1

    Java.util.ConcurrentModificationException 异常问题详解 ConcurrentModificationException 异常是 Java 中一个常见的异常,它发生在 Iterator 遍历集合时,集合同时被修改引起的异常。在 Java 中,集合类如 ...

    java 1. 泛型 2. 队列 3. 栈 4. Iterator 和 ListIterator迭代器

    java 1. 泛型 2. 队列 3. 栈 4. Iterator 和 ListIterator迭代器

    开源项目-json-iterator-go.zip

    `json-iterator-go`项目旨在解决这个问题,它通过优化算法和内存管理,提高了处理速度,对于需要频繁进行JSON操作的高性能服务来说尤其有吸引力。 `json-iterator-go`的核心特性包括: 1. **兼容性**:完全兼容`...

    Java源码分析:深入探讨Iterator模式

    ### Java源码分析:深入探讨Iterator模式 #### 一、引言 在Java编程语言中,集合框架(`java.util`包)提供了多种容器类来存储对象,如`List`、`Set`和`Map`等。为了遍历这些容器中的元素,Java引入了迭代器模式...

    迭代器模式(Iterator)C++实现

    1. **聚合类(Aggregate)**:这是包含一组元素的对象,如数组或容器。在C++中,这可能是一个类,如`std::vector`、`std::list`等。 2. **迭代器(Iterator)**:迭代器对象实现了访问聚合对象元素的接口。它有一个指针...

    hibernate 的开发注意项与性能调优

    3. **懒加载与急加载**:合理运用懒加载可以减少不必要的数据库访问,但需要注意控制加载时机,避免出现N+1查询问题。 #### 六、批量处理与数据处理 1. **批量操作**:通过设置`batch_size`等参数,可以提高批量...

    struts+hibernate基于购物车的功能小demo

    Struts和Hibernate是两种在Java Web开发中广泛使用的开源框架,它们在构建高效、可维护的Web应用程序中扮演着重要角色。本项目"struts+hibernate基于购物车的功能小demo"是一个实用的学习资源,旨在帮助初学者理解并...

    hibernate性能优化.doc

    - 避免N+1查询问题,通过JOIN语句一次性获取关联数据。 9. **API使用**: - 根据业务场景选择适当的集合类型和查询方法,如List、Set、Bag等,以及Query、Criteria等API。 10. **映射文件调整**: - 优化ID生成...

    java NIO详细教程

    这种模型在面对少量连接时没有问题,但在高并发场景下,大量的阻塞会导致系统性能急剧下降。 ##### 实现原理 Java NIO的核心组件包括Channel(通道)、Buffer(缓冲区)和Selector(选择器)。 - **Channel**:...

    关于方法iterator()找不着的问题~~~~~

    为了更好地调试和解决问题,你可以按照以下步骤操作: 1. 检查你的`import`语句。 2. 确保你的集合对象已经实例化并且包含元素。 3. 使用`try-catch`块捕获并打印异常,以便获取更多错误信息。 4. 确认你的集合类...

Global site tag (gtag.js) - Google Analytics