Hibernate Query借口的iterate方法 查询缓存的问题。

jiakai0419 2011-12-09 04:06:26
iterate()方法查询一级缓存吗?

在我机器上测试,怎么不查询一级缓存呢?

@Test
public void testIterate() {
Session s = sf.getCurrentSession();
s.beginTransaction();

Query q = s.createQuery("from Category");
Iterator<Category> it = q.iterate();

while (it.hasNext()) {
Category c = it.next();
System.out.println(c.getId());
}

it = q.iterate();

while (it.hasNext()) {
Category c = it.next();
System.out.println(c.getId());
}
s.getTransaction().commit();
}




结果
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
1
2
3
4
5
6
7
8
9
10
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
1
2
3
4
5
6
7
8
9
10


为什么不查询一级缓存呢?

不是说list 和 iterate 方法有一个区别就是iterate查询缓存吗?

...全文
100 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiakai0419 2011-12-09
  • 打赏
  • 举报
回复
刚才没理解了。

现在理解了。
jiakai0419 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zyz1985 的回复:]

iterate分两个步骤加载数据
1.查询出所有符合数据的ID,此步骤无法利用缓存,所以就会出现你看靠的多次select id from category;
2.当你真正访问实体属性时执行select * from Category where id=? 此步骤可以利用一级缓存,前提是这个实体已经加载到内存中,如果内存中不存在则需要发起查询,反之不需要....这就是所谓的利用缓存..
[/Quote]

2你都不用说了

你的第一条就是说iterate不查询1级缓存。

因为如果他查询,就不用每次都发。
游一游走一走 2011-12-09
  • 打赏
  • 举报
回复
下面的代码1就是利用了一级缓存,不会发起select * from Category where id=? 但会发起select id from category
代码1

public static List queryList(String hql) {
Session session = null;
Transaction tx = null;
List result=null;
try {
session = getCurrentSession();
tx = session.beginTransaction();
Query query=session.createQuery(hql);
result = query.list();
query.list();
Iterator iterator=query.iterate();
if(iterator.hasNext()){
((Event)iterator.next()).getTitle();
}
tx.commit();
} catch (Exception e) {
try {
tx.rollback();
} catch (HibernateException e1) {
logger.error("transaction rollback failed", e);
}
logger.error("data insert failed", e);
} finally {
closeCurrentSession();
}
return result;
}

下面的代码2两个SQL都会执行
代码2

public static List queryList(String hql) {
Session session = null;
Transaction tx = null;
List result=null;
try {
session = getCurrentSession();
tx = session.beginTransaction();
Query query=session.createQuery(hql);
/*result = query.list();
query.list();*/
Iterator iterator=query.iterate();
if(iterator.hasNext()){
((Event)iterator.next()).getTitle();
}
tx.commit();
} catch (Exception e) {
try {
tx.rollback();
} catch (HibernateException e1) {
logger.error("transaction rollback failed", e);
}
logger.error("data insert failed", e);
} finally {
closeCurrentSession();
}
return result;
}
游一游走一走 2011-12-09
  • 打赏
  • 举报
回复
iterate分两个步骤加载数据
1.查询出所有符合数据的ID,此步骤无法利用缓存,所以就会出现你看靠的多次select id from category;
2.当你真正访问实体属性时执行select * from Category where id=? 此步骤可以利用一级缓存,前提是这个实体已经加载到内存中,如果内存中不存在则需要发起查询,反之不需要....这就是所谓的利用缓存..
jiakai0419 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zyz1985 的回复:]

楼主再那看的有这个区别
我只知道他们有个很大的区别,iterate第一次查询只会查询出ID,当需要实体时才发出类似的select * from
Category where id=?
API也无说缓存的问题
[/Quote]

嗯。楼上哥们说的那个区别我知道。

我看的是马士兵的视频。。。。。



@Test
public void testCache3() {
Session s = sf.getCurrentSession();
s.beginTransaction();
Iterator<Category> it1 = s.createQuery("from Category").setCacheable(true).iterate();
while (it1.hasNext()) {
Category c = it1.next();
System.out.println(c.getId());
}
Iterator<Category> it2 = s.createQuery("from Category").setCacheable(true).iterate();
s.getTransaction().commit();
}


2级缓存他也不查。。。


我刚才测试list方法查询2级缓存(中的查询缓存)

而iterate方法不查2级缓存(中的查询缓存)。



到底是,马老师说错了。

还是我哪配置的不对啊?





我测试出来的结论是,query接口的list和iterate方法都不查询一级缓存。

list方法查询二级缓存(中的查询缓存)
游一游走一走 2011-12-09
  • 打赏
  • 举报
回复
楼主再那看的有这个区别
我只知道他们有个很大的区别,iterate第一次查询只会查询出ID,当需要实体时才发出类似的select * from
Category where id=?
API也无说缓存的问题
hibernate 3中的缓存小结 2.2. 一级缓存的管理: 当应用程序调用Session的save()、update()、savaeOrUpdate()、get()或load(),以及调用查询接口的list()、iterate()或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。 Session为应用程序提供了两个管理缓存方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。 2.3. 二级缓存的管理: 2.3.1. Hibernate的二级缓存策略的一般过程如下: 1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。 2) 把获得的所有数据对象根据ID放入到第二级缓存中。 3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。 4) 删除、更新、增加数据的时候,同时更新缓存。   Hibernate的二级缓存策略,是针对于ID查询缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询Query Cache。 2.3.2. 什么样的数据适合存放到第二级缓存中? 1 很少被修改的数据 2 不是很重要的数据,允许出现偶尔并发的数据 3 不会被并发访问的数据 4 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。 2.3.3. 不适合存放到第二级缓存的数据? 1 经常被修改的数据 2 财务数据,绝对不允许出现并发 3 与其他应用共享的数据。 2.3.4. 常用的缓存插件 Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件: l EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate查询缓存提供了支持。 l OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate查询缓存提供了支持。 l SwarmCache:可作为群集范围内的缓存,但不支持Hibernate查询缓存。 l JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate查询缓存提供了支持。 2.3.5. 配置二级缓存的主要步骤: 1) 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。 2) 选择合适的缓存插件,然后编辑该插件的配置文件。 2.4. 使用EhCache配置二级缓存: 2.4.1. 配置准备: 1) 把ehcache-1.2.3.jar加入到当前应用的classpath中。 2) 在hibernate.cfg.xml文件中加入EhCache缓存插件的提供类。 <!--配置缓存插件 --> org.hibernate.cache.EhCacheProvider 3) 挎贝ehcache.xml文件到类路径(项目工程的src目录下),这个文件在Hibernate安装目录的etc下。 2.4.2. 配置步骤: Hibernate允许在类和集合的粒度上设置第二级缓存。在映射文件中,元素都有一个子元素,这个子元素用来配置二级缓存。 示例:以category(产品类别)和product(产品)的映射为例: 1) 修改要配置缓存的那个持久化类的对象关系映射文件: Category.hbm.xml <?xml version="1.0" encoding="utf-8"?> hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> 缓存,必须紧跟在class元素后面 对缓存中的Category对象采用读写型的并发访问策略 --> <!-- 配置版本号,必须紧跟在id元素后面 --> <!-- Hibernate只会缓存对象的简单属性的值, 要缓存集合属性,必须在集合元素中也加入子元素 而Hibernate仅仅是把与当前持久对象关联的对象的OID存放到缓存中。 如果希望把整个关联的对象的所有数据都存入缓存, 则要在相应关联的对象的映射文件中配置元素 --> hibernate-mapping>
一.使用Hibernate的Session对象操作数据库 1.初始化Hibernate:在要使用Hibernate的类的方法中实例化Configuration对象并用Configuration对象的configure()方法hibernate.cfg.xml中的配置加载到内存,即: Configuration config = new Configuration().configure(); //该方法将到classpath下解析hibernate.cfg.xml中的配置,如果不用Hibernate默认的配置文件名和路径,可在该方法中指定Hibernate配置文件的名称和路径 2.用Configuration对象获取SessionFactory和Session对象:SessionFactory sf = Configuration对象.buildSessionFactory();Session session = SessionFactory对象.openSession(); 注:由于SessionFactory是重量级对象,很耗资源,所以在获取SessionFactory对象时最好用单例模式获取,以确保一个应用中只有一个SessionFactory对象存在和线程安全,由于Session对象 是非线程安全的(尽管创建一个Session对象消耗的资源很小),所以在获取Session对象时候也最好用单例模式获取 3.提交并清空Session中缓存的数据后开始一个事务 Session对象.flush(); //将Session中的缓存内容提交到数据库 Session对象.clear(); //清空Session中的所有缓存(彻底清除会话) Session对象.beginTransaction().begin(); //开始一个事务 4.用Session对象的以下方法操作数据 (1).save(Object obj); (2).saveOrUpdate(Object obj); (3).delete(Object obj); //只要删除的对象设置了主键的值就可以删除而无需先获取 (4).update(Object obj); //只要更新的对象设置了主键的值就可以更新而无需先获取 (5).get(Class classes,Serializable pk); //该方法会立即加载/获取数据(只要调用该方法就会立即向数据库发出查询语句),该方法只在内部缓存查找数据,如果内部缓存中没有数据就直接去数据库查询,当数据库中没有要查询的数据时返回null (6).load(Class classes,Serializable pk); //该方法会延迟加载/获取数据(只有使用该对象中的字段时才会向数据库发出查询语句),该方法会在内部和二级缓存中查找数据,当数据库中没有要查询的数据时报ObjectNotFoundException异常 (7).createQuery(String HQL).list()/iterate()/uniqueResult(); //HQL(Hibernate Query Language)语句查询

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧