先从N+1问题说起吧,看如下查询:
@Test
public void test1() {
Session session = null;
try {
session = HibernateUtils.openSession();
// N+1问题
Iterator<Classroom> iter = session.createQuery("from Classroom")
.iterate();
while (iter.hasNext()) {
System.out.println(iter.next().getName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
}
运行之,发出如下SQL:
Hibernate: select classroom0_.id as col_0_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@115126e
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@12a73d9
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@18d30fb
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@8dcd5d
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@159780d
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@eafb71
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@82d210
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@48f675
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1a3ca10
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@6c5482
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@9fea8a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@467991
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1f1cbf6
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@8e4805
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1b7c76
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@56b93a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@3a0ab1
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@179d854
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@3a835d
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@cfe049
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@179f36b
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@a8e586
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1afb0c7
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@89e2f1
这说明:Iterator方法先查询出所有的ID,然后当需要的时候再逐个查出,这就出现的经典的N+1问题,很明显,iterator不是这样用的。
再看:
@Test
public void test2() {
Session session = null;
try {
session = HibernateUtils.openSession();
List<Classroom> list = session.createQuery("from Classroom").list();
// N+1问题
List<Classroom> list2 = session.createQuery("from Classroom")
.list();
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
}
这里取出两个List,发出如下SQL:
Hibernate: select classroom0_.id as id0_, classroom0_.name as name0_, classroom0_.grade as grade0_, classroom0_.spe_id as spe4_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as id0_, classroom0_.name as name0_, classroom0_.grade as grade0_, classroom0_.spe_id as spe4_0_ from t_cla classroom0_
很明显,有点占用内存了。
再看一下,经典来了!
@Test
public void test2() {
Session session = null;
try {
session = HibernateUtils.openSession();
List<Classroom> list = session.createQuery("from Classroom").list();
// N+1问题
Iterator<Classroom> iter = session.createQuery("from Classroom")
.iterate();
while (iter.hasNext()) {
System.out.println(iter.next().getName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
}
这里先用List,然后iterator,发出如下SQL:
Hibernate: select classroom0_.id as id0_, classroom0_.name as name0_, classroom0_.grade as grade0_, classroom0_.spe_id as spe4_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as col_0_0_ from t_cla classroom0_
此时,木有出现N+1问题,为什么呢!因为有hibernate的一级缓存存在!等到list执行完成,session会将数据缓存到内存中,然后iterator时执行查询所有id,发现缓存里都有,所以就不再发语句了!
然后咱们再看一下一级缓存的作用域
@Test
public void test5() {
Session session = null;
try {
session = HibernateUtils.openSession();
List<Classroom> list = session.createQuery("from Classroom").list();
// N+1问题
List<Classroom> list2 = session.createQuery("from Classroom")
.list();
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.openSession();
Iterator<Classroom> iter = session.createQuery("from Classroom")
.iterate();
while (iter.hasNext()) {
System.out.println(iter.next());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
}
此时,发出SQL如下:
Hibernate: select classroom0_.id as id0_, classroom0_.name as name0_, classroom0_.grade as grade0_, classroom0_.spe_id as spe4_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as col_0_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@d480ea
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@913dc1
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1f98d58
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@9fe84e
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@9300cc
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@9bad5a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@940f82
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@179d854
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1867df9
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@18e18a3
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@6f8b2b
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1bc1fb9
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1117a20
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@18efaea
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@16504fa
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@5dfaf1
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@edbe39
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@bd09e8
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@20807c
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@10a5c21
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@98350a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@670479
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@9b1670
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@3f4ebd
又出现了N+1,哦哦,session一关闭,缓存就不存在了,这充分说明了一个问题,一级缓存的作用域只在session内!
再来:
@Test
public void test6() {
Session session = null;
try {
session = HibernateUtils.openSession();
// List<Classroom> list =
// session.createQuery("from Classroom").list();
session.createQuery("select cla.name,cla.id from Classroom cla")
.list();
Iterator<Classroom> iter = session.createQuery("from Classroom")
.iterate();
while (iter.hasNext()) {
System.out.println(iter.next());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtils.closeSession(session);
}
}
发出SQL:
Hibernate: select classroom0_.name as col_0_0_, classroom0_.id as col_1_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as col_0_0_ from t_cla classroom0_
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@dd75a4
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@146b6db
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@121df2a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@ad2c30
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@2c9103
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@26f9e5
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@205756
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@df2d38
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@d75c47
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@504ec1
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@16877f8
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@18adae2
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@134eb84
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@16d8196
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@adae91
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@91f005
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@cfe049
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@179f36b
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@12b19c5
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1c6e818
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@68cd79
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@2515
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@d0357a
Hibernate: select classroom0_.id as id0_0_, classroom0_.name as name0_0_, classroom0_.grade as grade0_0_, classroom0_.spe_id as spe4_0_0_ from t_cla classroom0_ where classroom0_.id=?
org.yanglg.model.Classroom@1fb3211
又是N+1,这又说明了什么?缓存缓的不是属性,是对象!!!