二十三 iterate查询与N+1次查询的问题

test.java

view plaincopy to clipboardprint?
01.import hibernate.HibernateUtil;   
02.  
03.import java.util.Date;   
04.import java.util.Iterator;   
05.  
06.import org.hibernate.Query;   
07.import org.hibernate.Session;   
08.  
09.import domain.Users;   
10.  
11.  
12.  
13.public class test {   
14.  
15.  
16.       
17.    public static void main(String[] args) {   
18.        Users user = new Users();   
19.        user.setBirthday(new Date());   
20.        user.setName("pf1");   
21.        HibernateUtil.add(user);   
22.        user.setName("pf2");   
23.        HibernateUtil.add(user);   
24.        user.setName("pf3");   
25.        HibernateUtil.add(user);   
26.           
27.        iterator();   
28.           
29.           
30.    }   
31.       
32.    static void iterator(){   
33.        Session s = HibernateUtil.getSession();   
34.        Query query = s.createQuery("from Users");   
35.        Iterator<Users> it = query.iterate();   
36.        while(it.hasNext()){   
37.            System.out.println(it.next().getName());   
38.        }   
39.    }   
40.}  
import hibernate.HibernateUtil;

import java.util.Date;
import java.util.Iterator;

import org.hibernate.Query;
import org.hibernate.Session;

import domain.Users;



public class test {


	
	public static void main(String[] args) {
		Users user = new Users();
		user.setBirthday(new Date());
		user.setName("pf1");
		HibernateUtil.add(user);
		user.setName("pf2");
		HibernateUtil.add(user);
		user.setName("pf3");
		HibernateUtil.add(user);
		
		iterator();
		
		
	}
	
	static void iterator(){
		Session s = HibernateUtil.getSession();
		Query query = s.createQuery("from Users");
		Iterator<Users> it = query.iterate();
		while(it.hasNext()){
			System.out.println(it.next().getName());
		}
	}
}
 

执行结果:

Hibernate: insert into Users (ver, name, birthday) values (?, ?, ?)
Hibernate: insert into Users (ver, name, birthday) values (?, ?, ?)
Hibernate: insert into Users (ver, name, birthday) values (?, ?, ?)
Hibernate: select users0_.id as col_0_0_ from Users users0_
Hibernate: select users0_.id as id0_0_, users0_.ver as ver0_0_, users0_.name as name0_0_, users0_.birthday as birthday0_0_ from Users users0_ where users0_.id=?
pf1
Hibernate: select users0_.id as id0_0_, users0_.ver as ver0_0_, users0_.name as name0_0_, users0_.birthday as birthday0_0_ from Users users0_ where users0_.id=?
pf2
Hibernate: select users0_.id as id0_0_, users0_.ver as ver0_0_, users0_.name as name0_0_, users0_.birthday as birthday0_0_ from Users users0_ where users0_.id=?
pf3

可以发现红色那条语句,iterator查询是先查出记录的id号,在需要的时候再去查询,查询时候先从缓存里查找,再从数据库中读取。

由于我的Users是native方式生成主键,所以不会保存在缓存里,因为没访问数据库前不知道数据库生成的id号。

所有的select语句加起来是4条,包括查id的语句,所以一共是N+1次查询。所以缓存没命中的情况下查询效率极低。

同样懒加载的时候也会有N+1次查询的情况,第一次查询出所有当前对象,N次查询查询关联对象。


懒加载也会有N+1次查询
当有个部门它下面有十个员工 我们去查这个部门,当要查询这个部门下的员工时,就会出现11条select语句,一条是
这个部门的查询 另外十条是根据部门id查员工的select语句

如果我查询员工,通过员工去查部门,就不会有N+1次查询,因为这在查员工的时候就把部门信息给查出来了 
这种情况在一对一的关系中特别明显


总结 N+1次查询和懒加载
     1.用Query.iterator可能会有N+1次查询。
     2.懒加载时获取关联对象。
     3.如果打开对查询的缓存即使用list也可能有N+1次查询。


完毕 end!

 

你可能感兴趣的:(iterate)