深入理解Hibernate中Iterate方法
数据准备参考博文(这是链接) 在实际需求中有时需要对一些业务数据进行频繁的查询处理,可能会这样处理: 二、list查询剖析
public void testQuerySingleTable_HQL_List() { Session session = HbnUtils.getSession(); try { session.beginTransaction(); String hql = "from Student where age > 17"; // 执行第一次查操作 List<Student> list = session.createQuery(hql).list(); for (Student stu : list) { System.out.println(stu); } System.out.println("\t-------第一次查询与第二次查询的分割线--------"); // 执行第二次查操作 List<Student> list_1 = session.createQuery(hql).list(); for (Student stu : list) { System.out.println(stu); } session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } }下面是控制台打印的SQL语句和提示语句
Hibernate: select student0_.t_id as t_id1_0_, student0_.t_name as t_name2_0_, student0_.t_age as t_age3_0_, student0_.t_score as t_score4_0_ from t_student student0_ where student0_.t_age>17 Student [id=8, name=张8三, age=18, score=88.0] Student [id=9, name=张9三, age=19, score=89.0] Student [id=10, name=张10三, age=20, score=90.0] -------第一次查询与第二次查询的分割线-------- Hibernate: select student0_.t_id as t_id1_0_, student0_.t_name as t_name2_0_, student0_.t_age as t_age3_0_, student0_.t_score as t_score4_0_ from t_student student0_ where student0_.t_age>17 Student [id=8, name=张8三, age=18, score=88.0] Student [id=9, name=张9三, age=19, score=89.0] Student [id=10, name=张10三, age=20, score=90.0]从上面的输出信息可以看出,用List方法Hibernate查询了几次就访问了几次数据库,为了提高效率,本应该在第二次查询的时候可以从缓存中获取,因为第一次的结果已经保存在Session缓存中了!
代码
/** * iterate * */ @Test public void testQuerySingleTable_HQL_Iterate() { Session session = HbnUtils.getSession(); try { session.beginTransaction(); String hql = "from Student where age>17"; // 执行(第一次查询) Iterator<Student> iterator = session.createQuery(hql).iterate(); while(iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("\t-------第一次查询与第二次查询的分割线--------"); //执行第二次查询操作 List<Student> list_1 = (List<Student>) session.createQuery(hql).iterate(); while(iterator.hasNext()){ System.out.println(iterator.next()); } session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } }执行后控制台输出信息
Hibernate: select student0_.t_id as col_0_0_ from t_student student0_ where student0_.t_age>17 Hibernate: select student0_.t_id as t_id1_0_0_, student0_.t_name as t_name2_0_0_, student0_.t_age as t_age3_0_0_, student0_.t_score as t_score4_0_0_ from t_student student0_ where student0_.t_id=? Student [id=8, name=张8三, age=18, score=88.0] Hibernate: select student0_.t_id as t_id1_0_0_, student0_.t_name as t_name2_0_0_, student0_.t_age as t_age3_0_0_, student0_.t_score as t_score4_0_0_ from t_student student0_ where student0_.t_id=? Student [id=9, name=张9三, age=19, score=89.0] Hibernate: select student0_.t_id as t_id1_0_0_, student0_.t_name as t_name2_0_0_, student0_.t_age as t_age3_0_0_, student0_.t_score as t_score4_0_0_ from t_student student0_ where student0_.t_id=? Student [id=10, name=张10三, age=20, score=90.0] -------第一次查询与第二次查询的分割线-------- Hibernate: select student0_.t_id as col_0_0_ from t_student student0_ where student0_.t_age>17分析输出信息可以看出:Hibernate的iterate执行过程 1): Hibernate: select student0_.t_id as col_0_0_ from t_student student0_ where student0_.t_age>17 Student [id=8, name=张8三, age=18, score=88.0] Student [id=9, name=张9三, age=19, score=89.0] Student [id=10, name=张10三, age=20, score=90.0] 1):先把所有满足条件的记录的id从数据库查询出来 2):然后根据查询出来的id逐个去查询每一条记录的详细信息 3):先根据id在Session缓存中查找 4):如果没有,就需要去数据库查找,有几个满足条件的id,就需要访问几次数据库 3):当进行第二次查询时,先到数据库进行了一次主键查询,查查满足条件的id,然后直接根据id从Session缓存中读出满足条件的记录的详细信息
List方法不会从Session缓存中读取数据
Iterate方法会从Session缓存中读取数据
List方法第一次查询效率高
Iterate方法第一次查询效率很低(2n+1次)
所以为了避免n+1问题,我们取长补短,第一次查询用List,第二次查询用Iterate
看结果:———
Hibernate: select student0_.t_id as t_id1_0_, student0_.t_name as t_name2_0_, student0_.t_age as t_age3_0_, student0_.t_score as t_score4_0_ from t_student student0_ where student0_.t_age>17 Student [id=8, name=张8三, age=18, score=88.0] Student [id=9, name=张9三, age=19, score=89.0] Student [id=10, name=张10三, age=20, score=90.0] -------第一次查询与第二次查询的分割线-------- Hibernate: select student0_.t_id as col_0_0_ from t_student student0_ where student0_.t_age>17 Student [id=8, name=张8三, age=18, score=88.0] Student [id=9, name=张9三, age=19, score=89.0] Student [id=10, name=张10三, age=20, score=90.0]从结果分析效率确实提高了不少!!!
