实体对象查询:
² N + 1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题,所谓的N+1是在查询的时候发出了N+1条sql语句:
1:首先发出一条查询对象id列表的sql
N:根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句
² list和iterate的区别?
list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据。
iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题。
例子1代码如下:
|
/** * 实体对象查询 */ public class SimpleObjectQueryTest1 extends TestCase {
public void testQuery1() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); //返回Student对象的集合 //可以忽略select List students = session.createQuery ("from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); //返回Student对象的集合 //可以忽略select,表可以使用别名 List students = session.createQuery ("from Student s").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery3() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction();
//返回Student对象的集合 //可以忽略select,表可以使用as命名别名 List students = session.createQuery ("from Student as s").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery4() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); //返回Student对象的集合 //使用select查询实体对象,必须采用别名 List students = session.createQuery ("select s from Student as s").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery5() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); //不支持select * from .....这样的查询语句 List students = session.createQuery ("select * from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } } |
例子2代码如下:
|
/** * 实体对象查询 */ public class SimpleObjectQueryTest2 extends TestCase { public void testQuery1() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); /** * 采用list查询发出一条查询语句,取得Student对象数据、 * * Hibernate: select student0_.id as id1_, student0_.name as name1_, * student0_.createTime as createTime1_, student0_.classesid as classesid1_ * from t_student student0_ * */ List students = session.createQuery ("from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery2() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); /** * 出现N+1问题 * 1:发出查询id列表的sql * Hibernate: select student0_.id as col_0_0_ from t_student student0_ * * N:在依次发出根据id查询Student对象的sql * Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, * student0_.createTime as createTime1_0_, student0_.classesid as classesid1_0_ * from t_student student0_ where student0_.id=? */ Iterator iter = session.createQuery ("from Student").iterate(); while(iter.hasNext()) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery3() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); List students = session.createQuery ("from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } System.out.println("----------------------"); /** * 不会出现N+1问题 * 因为list操作已经将Student对象放到了一级缓存中,所以再次使用 iterate操作的时候 * 它首先发出一条查询id列表的sql,在根据id到缓存中去数据,只有 在缓存中找不到相应的 * 数据时,才会发出sql到数据库中查询 */ Iterator iter = session.createQuery ("from Student").iterate(); while(iter.hasNext()) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } public void testQuery4() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); List students = session.createQuery ("from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } System.out.println("-------------------"); /** * 再次发出查询sql * 在默认情况下list每次都会向数据库发出查询对象的sql,除非配置 查询缓存,所以下面的list操作 * 虽然在一级缓存中已经有了对象数据,但list默认情况下不会利用缓 存,而再次发出sql * 默认情况下,list会向缓存中放入数据,但不会利用数据 */ students = session.createQuery("from Student").list(); for (Iterator iter=students.iterator(); iter.hasNext();) { Student student = (Student)iter.next(); System.out.println(student.getName()); } session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } } |

本文探讨了Hibernate中list和iterate方法的区别,特别是在处理N+1查询问题时的行为差异。通过示例代码展示了如何避免不必要的数据库查询,提高应用程序性能。

被折叠的 条评论
为什么被折叠?



