查询实体对象:

n+1问题:在默认情况下,使用query.iterator()查询,有可能有n+1问题,所谓n+1是指在查询对象的时候发出n+1条查询语句。

1:先发出查询id列表的sql语句。

N:再发出根据id到缓存中查询,如果缓存中有与之匹配的数据,就从缓存中取得数据,否则依次根据id发出sql语句。

list和iterator到区别:

list:在默认情况下,list每次都会发出sql查询实体对象,list会向缓存里放数据,但是不会利用缓存中的数据。

iterator:首先发出一条查询id列表的sql语句,如果缓存中有与之匹配的数据,就从缓存中取得数据,否则依次根据id发出sql语句。

 
  
  1. import java.util.Iterator;  
  2. import java.util.List;  
  3.  
  4. import junit.framework.TestCase;  
  5.  
  6. import org.hibernate.Session;  
  7. import org.hibernate.Transaction;  
  8. //...  
  9.  
  10.  
  11. public class QueryTest extends TestCase {  
  12.  
  13. public void testQuery1() {  
  14. Session session = null;  
  15. Transaction t = null;  
  16. try {  
  17. session = HibernateUtils.getSession();  
  18. t = session.beginTransaction();  
  19. /**  
  20. * 采用list查询,将发出一条sql语句来获取student数据  
  21. * Hibernate: select student0_.id as id1_, student0_.name as name1_ from Student student0_  
  22. 张三  
  23. 李四  
  24. */  
  25. List<Student> list = session.createQuery("from Student").list();  
  26. for (Iterator<Student> iter = list.iterator(); iter.hasNext();) {  
  27. Student student = iter.next();  
  28. System.out.println(student.getName());  
  29. }  
  30.  
  31. t.commit();  
  32. } catch (Exception e) {  
  33. e.printStackTrace();  
  34. t.rollback();  
  35. } finally {  
  36. HibernateUtils.closeSession(session);  
  37. }  
  38. }  
  39. public void testQuery2() {  
  40. Session session = null;  
  41. Transaction t = null;  
  42. try {  
  43. session = HibernateUtils.getSession();  
  44. t = session.beginTransaction();  
  45. /**  
  46. * N+1问题:  
  47. * 使用iterator,先发出查询id列表的sql语句,  
  48. * Hibernate: select student0_.id as col_0_0_ from Student student0_  
  49. * 再发出根据id查询实体对象的sql  
  50. * Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_ from Student student0_ where student0_.id=?  
  51. 张三  
  52. Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_ from Student student0_ where student0_.id=?  
  53. 李四  
  54. ×   
  55. */  
  56. Iterator<Student> it = session.createQuery("from Student").iterate();  
  57. while(it.hasNext()){  
  58. Student student = it.next();  
  59. System.out.println(student.getName());  
  60. }  
  61. t.commit();  
  62. } catch (Exception e) {  
  63. e.printStackTrace();  
  64. t.rollback();  
  65. } finally {  
  66. HibernateUtils.closeSession(session);  
  67. }  
  68. }  
  69. public void testQuery3() {  
  70. Session session = null;  
  71. Transaction t = null;  
  72. try {  
  73. session = HibernateUtils.getSession();  
  74. t = session.beginTransaction();  
  75.  
  76. List<Student> list = session.createQuery("from Student").list();  
  77. for (Iterator<Student> iter = list.iterator(); iter.hasNext();) {  
  78. Student student = iter.next();  
  79. System.out.println(student.getName());  
  80. }  
  81.  
  82. System.out.println("=======================");  
  83.  
  84. /**  
  85. * 不会出现n+1问题  
  86. * 因为list操作已经将对象加入到一级缓存,所以在使用iterator的时候,  
  87. * 他首先发出查询id列表的sql,再根据id到缓存中获取数据,  
  88. * 只有在缓存中找不到,才再次发出sql语句  
  89.  
  90. Hibernate: select student0_.id as id1_, student0_.name as name1_ from Student student0_  
  91. 张三  
  92. 李四  
  93. =======================  
  94. Hibernate: select student0_.id as col_0_0_ from Student student0_  
  95. 张三  
  96. 李四  
  97.  
  98. */  
  99. Iterator<Student> it = session.createQuery("from Student").iterate();  
  100. while(it.hasNext()){  
  101. Student student = it.next();  
  102. System.out.println(student.getName());  
  103. }  
  104. t.commit();  
  105. } catch (Exception e) {  
  106. e.printStackTrace();  
  107. t.rollback();  
  108. } finally {  
  109. HibernateUtils.closeSession(session);  
  110. }  
  111. }  
  112. }