二十三 iterate查询与N+1次查询的有关问题
二十三 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!