list与iterate的不同之处:
还是用上一次的例子,话题topic和版块category
Topic.java:
package com.bjsxt.hibernate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.BatchSize;
@Entity
public class Topic {
private int id;
private String title;
private Category category;
private Date createDate;
private List<Msg> msgs = new ArrayList<Msg>();
@OneToMany(mappedBy="topic")
public List<Msg> getMsgs() {
return msgs;
}
public void setMsgs(List<Msg> msgs) {
this.msgs = msgs;
}
@Temporal(TemporalType.TIME)
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@ManyToOne(fetch=FetchType.LAZY)
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Category.java:
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.BatchSize;
@Entity
public class Category {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
添加数据(每一个板块ci下有一个话题ti)
@Test
public void testSave() {
Session session = sf.openSession();
session.beginTransaction();
//每一个版块ci下面有一个话题ti
for(int i=0; i<10; i++) {
Category c = new Category();
c.setName("c" + i);
Topic t=new Topic();
t.setCategory(c);
t.setTitle("t"+i);
t.setCreateDate(new Date());
session.save(c);
session.save(t);
}
session.getTransaction().commit();
session.close();
}
下面进行list与iterate的不同测试
1.list取所有
@Test
public void testOneAddNProblem1(){
Session session = sf.openSession();
session.beginTransaction();
List<Topic> topics=(List<Topic>)session.createQuery("from Topic").list();
for(Topic t:topics){
System.out.println(t.getId()+"-"+t.getTitle());
}
session.getTransaction().commit();
session.close();
}
结果:
Hibernate:
select
topic0_.id as id2_,
topic0_.category_id as category4_2_,
topic0_.createDate as createDate2_,
topic0_.title as title2_
from
Topic topic0_
1-t0
2-t1
3-t2
4-t3
5-t4
6-t5
7-t6
8-t7
9-t8
10-t9
2.iterate先取ID,等用到的时候在根据ID来取对象。
@Test
public void testListAndIterate(){
Session session = sf.openSession();
session.beginTransaction();
Iterator<Topic> topics=(Iterator<Topic>)session.createQuery("from Topic").iterate();
for(Topic t=topics.next();t!=null;t=topics.next()){
System.out.println(t.getId()+"-"+t.getTitle());
}
session.getTransaction().commit();
session.close();
}
测试结果:
Hibernate:
select
topic0_.id as col_0_0_
from
Topic topic0_
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
1-t0
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
2-t1
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
3-t2
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
4-t3
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
5-t4
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
6-t5
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
7-t6
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
8-t7
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
9-t8
Hibernate:
select
topic0_.id as id2_0_,
topic0_.category_id as category4_2_0_,
topic0_.createDate as createDate2_0_,
topic0_.title as title2_0_
from
Topic topic0_
where
topic0_.id=?
10-t9
所以我们可以看出,先取ID,等用到的时候在根据ID来取对象。
3.session中list第二次发出,仍会到数据库查询。
测试代码:
@Test
public void testListAndIterate2(){
Session session = sf.openSession();
session.beginTransaction();
//Iterator<Topic> topics=(Iterator<Topic>)session.createQuery("from Topic").iterate();
Query q=session.createQuery("from Topic");
List<Topic> topics=q.list();
for(Topic t:topics){
System.out.println(t.getId()+"-"+t.getTitle());
}
List<Topic> topics2=q.list();
for(Topic t:topics2){
System.out.println(t.getId()+"-"+t.getTitle());
}
session.getTransaction().commit();
session.close();
}
测试结果:
Hibernate:
select
topic0_.id as id2_,
topic0_.category_id as category4_2_,
topic0_.createDate as createDate2_,
topic0_.title as title2_
from
Topic topic0_
1-t0
2-t1
3-t2
4-t3
5-t4
6-t5
7-t6
8-t7
9-t8
10-t9
Hibernate:
select
topic0_.id as id2_,
topic0_.category_id as category4_2_,
topic0_.createDate as createDate2_,
topic0_.title as title2_
from
Topic topic0_
1-t0
2-t1
3-t2
4-t3
5-t4
6-t5
7-t6
8-t7
9-t8
10-t9
4.iterate第二次,首先找session级缓存
测试代码:
@Test
public void testListAndIterate3(){
Session session = sf.openSession();
session.beginTransaction();
Iterator<Category> categories = (Iterator<Category>)session.createQuery("from Category").iterate();
while(categories.hasNext()) {
Category c = categories.next();
System.out.println(c.getName());
}
Iterator<Category> categories2 = (Iterator<Category>)session.createQuery("from Category").iterate();
while(categories2.hasNext()) {
Category c = categories2.next();
System.out.println(c.getName());
}
session.getTransaction().commit();
session.close();
}
测试结果:
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c0
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c1
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c2
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c3
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c4
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c5
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c6
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c7
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c8
Hibernate:
select
category0_.id as id0_0_,
category0_.name as name0_0_
from
Category category0_
where
category0_.id=?
c9
Hibernate:
select
category0_.id as col_0_0_
from
Category category0_
c0
c1
c2
c3
c4
c5
c6
c7
c8
c9
看出了第二次使用的session缓存里面的数据,而没有去数据库再查。
总结:
原因是:先看list,list取完10个数据以后session中有了10个数据的缓存,第二次list再去取的时候,它仍然要再去数据库里加载一次,然后再刷新缓存,再把原来对象重新刷一遍。也就是list不会去读session的缓存,原因是作为一个查询来说,查询条件很难认定,不是list不想利用,而是很难利用。
iterate就不一样了,首先在第一遍的时候,他首先把id取出来,由于后面我们做了遍历,所以他把id对应的对象全都放在了缓存中,第二次再做遍历的时候,这个时候只要去缓存中查就行了。
什么时候用list?什么时候用iterate?工作的时候用list就行了。
小技巧:第一次用list,第二次再去访问的时候就可以用iterate了。因为iterate会首先检查缓存,缓存中有了,就不会再去数据库里去查了。
主要应付面试
转载请注明出处: