HibernateTest.java
代码:
/** * */ package com.b510.examplex;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;
/** * * @author XHW * * @date 2011-7-15 * */ public class HibernateTest {
/** * @param args */ public static void main(String[] args) { new HibernateTest().getGuestbooks(); }
public void getGuestbooks(){ SessionFactory sessionFactory=HibernateSessionFactoryUtil.getSessionFactory(); Session session1=sessionFactory.getCurrentSession(); System.out.println("Session1:"+session1); Transaction tx=session1.beginTransaction();
//Guestbook gb=(Guestbook)session1.load(Guestbook.class, 1); Guestbook gb=(Guestbook)session1.get(Guestbook.class, 1); System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); tx.commit(); System.out.println("----------------------------------"); Session session2=sessionFactory.getCurrentSession(); System.out.println("Session2:"+session2); System.out.println("session1是否等于session2 ?"); System.out.println(session1==session2); session2.beginTransaction();
// gb=(Guestbook)session2.load(Guestbook.class, 1); load和get方法在这里可以随便使用,不会影响运行的结果 gb=(Guestbook)session2.get(Guestbook.class, 1); System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); session2.getTransaction().commit(); } }
运行效果:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. Session1:SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]]) Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 1name: liuwei ---------------------------------- Session2:SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]]) session1是否等于session2 ? false ID : 1name: liuwei
我们看到,session1和session2两个session对象是不想等的,也就是说两个session的地址不是同一个内存地址
然而我们却看到,这里却只用了一条select语句,我们明明是查询两条记录啊!这说明HIbernate的缓存是跨session的
也就是一个session对象被干掉了以后,他的缓存还是存在的,不因session被干掉二干掉。这样在我们读取相同的数据
的时候就不会再却读数据库,而是直接从缓存中读取出来。
测试代码二:
HibernateTest.java
代码;
/** * */ package com.b510.examplex;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;
/** * * @author XHW * * @date 2011-7-15 * */ public class HibernateTest {
/** * @param args */ public static void main(String[] args) { new HibernateTest().getGuestbooks(); }
public void getGuestbooks(){ SessionFactory sessionFactory=HibernateSessionFactoryUtil.getSessionFactory(); Session session1=sessionFactory.getCurrentSession(); Transaction tx=session1.beginTransaction(); Query query=session1.createQuery("from Guestbook"); List<Guestbook> list=query.list(); for(Guestbook gb:list){ System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } tx.commit(); System.out.println("----------------------------------"); Session session2=sessionFactory.getCurrentSession(); session2.beginTransaction(); query=session2.createQuery("from Guestbook"); list=query.list(); for(Guestbook gb:list){ System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } session2.getTransaction().commit(); } }
运行效果:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. Hibernate: select guestbook0_.id as id0_, guestbook0_.version as version0_, guestbook0_.name as name0_, guestbook0_.email as email0_, guestbook0_.phone as phone0_, guestbook0_.title as title0_, guestbook0_.content as content0_, guestbook0_.created_time as created8_0_ from users.guestbook guestbook0_ ID : 1name: liuwei ID : 2name: Hongtenzone@foxmail.com ID : 3name: Hongten ID : 4name: HOngten ID : 5name: HOngten ID : 6name: HOngten ID : 7name: HOngten ---------------------------------- Hibernate: select guestbook0_.id as id0_, guestbook0_.version as version0_, guestbook0_.name as name0_, guestbook0_.email as email0_, guestbook0_.phone as phone0_, guestbook0_.title as title0_, guestbook0_.content as content0_, guestbook0_.created_time as created8_0_ from users.guestbook guestbook0_ ID : 1name: liuwei ID : 2name: Hongtenzone@foxmail.com ID : 3name: Hongten ID : 4name: HOngten ID : 5name: HOngten ID : 6name: HOngten ID : 7name: HOngten
我们看到的结果是用两条select语句,查出了相同的结果!
这个list对象有这么一个特点:他只是从数据库中读取数据,放到缓存中,但是据对不会到缓存中
去索要数据。也就是说list只是贡献缓存,不会索要缓存。
他不用二级缓存。
测试代码三:
HibernateTest.java
代码:
/** * */ package com.b510.examplex;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;
/** * * @author XHW * * @date 2011-7-15 * */ public class HibernateTest {
/** * @param args */ public static void main(String[] args) { new HibernateTest().getGuestbooks(); }
public void getGuestbooks(){ SessionFactory sessionFactory=HibernateSessionFactoryUtil.getSessionFactory(); Session session1=sessionFactory.getCurrentSession(); Transaction tx=session1.beginTransaction(); Query query=session1.createQuery("from Guestbook"); List<Guestbook> list=query.list(); for(Guestbook gb:list){ System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } tx.commit(); System.out.println("----------------------------------"); Session session2=sessionFactory.getCurrentSession(); session2.beginTransaction(); query=session2.createQuery("from Guestbook"); Iterator it=query.iterate(); while(it.hasNext()){ Guestbook gb=(Guestbook)it.next(); System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } session2.getTransaction().commit(); } }
运行效果:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. Hibernate: select guestbook0_.id as id0_, guestbook0_.version as version0_, guestbook0_.name as name0_, guestbook0_.email as email0_, guestbook0_.phone as phone0_, guestbook0_.title as title0_, guestbook0_.content as content0_, guestbook0_.created_time as created8_0_ from users.guestbook guestbook0_ ID : 1name: liuwei ID : 2name: Hongtenzone@foxmail.com ID : 3name: Hongten ID : 4name: HOngten ID : 5name: HOngten ID : 6name: HOngten ID : 7name: HOngten ---------------------------------- Hibernate: select guestbook0_.id as col_0_0_ from users.guestbook guestbook0_ ID : 1name: liuwei ID : 2name: Hongtenzone@foxmail.com ID : 3name: Hongten ID : 4name: HOngten ID : 5name: HOngten ID : 6name: HOngten ID : 7name: HOngten
第一条selelct语句是从数据库中读出数据然后将数据放入二级缓存中,接着进入第二个会话
Iterator会向二级缓存索要查询的数据,他的方式是首先将要查的实体类的主键值获取到,
这样在底层上就要使用一条selelct id 的语句,就是我们看到的第二条selelct语句。这样就获取了
这个持久化对象的的主键值的一个集合。从 这个主键值集合中再分别读出一个主键值,将他的其他内容
读取出来。如上面显示的一样,先获取Id=1,然后获取id=1的其他数据,如name字段的值,然后再获取
id=2,再获取id=2的其他数据(name),以这种方式进行下去,直到读取完数据。还要申明的是,Iterator
都是先从二级缓存中获取数据,如果不在二级缓存中,那么要使用“n+1”方式了。
看下面的测试代码:
HibernateTest.java
代码:
/** * */ package com.b510.examplex;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;
/** * * @author XHW * * @date 2011-7-15 * */ public class HibernateTest {
/** * @param args */ public static void main(String[] args) { new HibernateTest().getGuestbooks(); }
public void getGuestbooks(){ SessionFactory sessionFactory=HibernateSessionFactoryUtil.getSessionFactory(); /* Session session1=sessionFactory.getCurrentSession(); Transaction tx=session1.beginTransaction(); Query query=session1.createQuery("from Guestbook"); List<Guestbook> list=query.list(); for(Guestbook gb:list){ System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } tx.commit(); */ System.out.println("----------------------------------"); Session session2=sessionFactory.getCurrentSession(); session2.beginTransaction(); Query query=session2.createQuery("from Guestbook"); Iterator it=query.iterate(); while(it.hasNext()){ Guestbook gb=(Guestbook)it.next(); System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); } session2.getTransaction().commit(); } }
运行效果:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. ---------------------------------- Hibernate: select guestbook0_.id as col_0_0_ from users.guestbook guestbook0_ “n+1”方式中 的“1” Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 1name: liuwei Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 2name: Hongtenzone@foxmail.com Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 3name: Hongten Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 4name: HOngten Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 5name: HOngten Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 6name: HOngten Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 7name: HOngten
这就是“n+1”或者说“1+n”方式,也就是说,我们要查询的结果只有7条记录,但是,我们看到 的selelctyuj
却是8条。首先从缓存中去找,没有找到,就向数据库发出请求,查询出数据。然后执行id=2的Guestbook对象,
缓存中没有记录,有要向数据库发出请求,以这种方式进行下去。
要注意 的是:如果二级缓存中没有任何对象或者说是数据,那么这时如果我们采用Iterator方法,就会用到“n+1”
条selelct语句,这时还不如list的查询效率高。所以我们要用Iterator的时候的前提是二级缓存中要有数据,这样
的查询效率要才会高。不然会出现相反的效果。
测试代码四;
HibernateTest.java
代码:
/** * */ package com.b510.examplex;
import java.util.List;
import java.util.Iterator;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration;
/** * * @author XHW * * @date 2011-7-15 * */ public class HibernateTest {
/** * @param args */ public static void main(String[] args) { new HibernateTest().getGuestbooks(); }
public void getGuestbooks(){ SessionFactory sessionFactory1=new Configuration().configure().buildSessionFactory(); Session session1=sessionFactory1.getCurrentSession(); Transaction tx1=session1.beginTransaction(); Guestbook gb=(Guestbook)session1.get(Guestbook.class, 1); System.out.println("ID : "+gb.getId()+"name: "+gb.getName()); System.out.println(sessionFactory1); sessionFactory1.close(); System.out.println("----------------------------------"); SessionFactory sessionFactory2=new Configuration().configure().buildSessionFactory(); Session session2=sessionFactory2.getCurrentSession(); Transaction tx2=session2.beginTransaction(); Guestbook gb2=(Guestbook)session2.get(Guestbook.class, 1); System.out.println("ID : "+gb2.getId()+"name: "+gb2.getName()); System.out.println(sessionFactory2); sessionFactory2.close(); } }
运行效果:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment). log4j:WARN Please initialize the log4j system properly. Hibernate: select guestbook0_.id as id0_0_, guestbook0_.version as version0_0_, guestbook0_.name as name0_0_, guestbook0_.email as email0_0_, guestbook0_.phone as phone0_0_, guestbook0_.title as title0_0_, guestbook0_.content as content0_0_, guestbook0_.created_time as created8_0_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 1name: liuwei org.hibernate.impl.SessionFactoryImpl@1fcc0a2 ---------------------------------- Hibernate: select guestbook0_.id as id2_0_, guestbook0_.version as version2_0_, guestbook0_.name as name2_0_, guestbook0_.email as email2_0_, guestbook0_.phone as phone2_0_, guestbook0_.title as title2_0_, guestbook0_.content as content2_0_, guestbook0_.created_time as created8_2_0_ from users.guestbook guestbook0_ where guestbook0_.id=? ID : 1name: liuwei org.hibernate.impl.SessionFactoryImpl@19b46dc
Hibernate的二级缓存是跟SessionFactory相关的,所以当一个SessionFactory对象关闭后,二级缓存中的
数据就会跟着这个SessionFactory对象的关闭而随之消失,当我们启动第二个SessionFactory对象的时候,这个
这个对象的二级缓存生效。当然当这个SessionFactory对象关闭的时候,二级缓存中的数据也会消失。
因此,我们就会看到两个select语句。
所以:Hibernate的二级缓存又被叫做SessionFactory缓存