标签:hibernate
1.什么是缓存?
缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命 中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗。
2.Hibernate缓存分类:
一、Session缓存(又称作事务缓存):Hibernate内置的,不能卸除。
缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。
二、SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。
缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。
缓存策略提供商:
提供了HashTable缓存,EHCache,OSCache,SwarmCache,jBoss Cathe2,这些缓存机制,其中EHCache,OSCache是不能用于集群环境(Cluster Safe)的,而SwarmCache,jBoss Cathe2是可以的。HashTable缓存主要是用来测试的,只能把对象放在内存中,EHCache,OSCache可以把对象放在内存(memory)中,也可以把对象放在硬盘(disk)上(为什么放到硬盘上?上面解释了)。
session的缓存:
1、生命周期就是session的生命周期
2、session一级缓存存放的数据都是私有数据
把session存放在threadlocal中,不同的线程是不能访问的,所以保证了数据的安全性
3、怎么样把数据存放到一级缓存中
利用session.save/update/load/get方法都可以存放在一级缓存中
4、利用session.get/load方法可以把数据从一级缓存中取出
5、session.evict方法可以把一个对象从一级缓存中清空
6、利用session.clear方法可以把session中的所有的数据清空
7、利用session.Refresh方法把数据库中的数据同步到缓存中
8、session.flush
在session的缓存内部,会去检查所有的持久化对象
1、如果一个持久化对象没有ID值,则会发出insert语句
2、如果一个持久化对象有ID值,则会去检查快照进行对比,如果一样,则什么都不做,如果不一样,则发出update语句
3、检查所有的持久化对象是否有关联对象
检查关联对象的级联操作
检查关联对象的关系操作
9、批量操作
测试
public class SessionCacheTest extends HibernateUtils{ @Test public void testGet(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); Classess = (Classess)session.get(Classess.class,1L); transaction.commit(); } /** * session.load方法把数据存放在一级缓存中 */ @Test public void testLoad(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.load(Classess.class, 1L); Classess.getCname(); Classess = (Classess)session.load(Classess.class,1L); Classess.getCname(); transaction.commit(); } /** * session.save方法把数据保存在一级缓存中 */ @Test public void testSave(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = new Classess(); Classess.setCname("aaa"); Classess.setDescription("asfd"); session.save(Classess); Classess = (Classess)session.get(Classess.class, Classess.getCid()); transaction.commit(); } /** * session.update */ @Test public void testUpdate(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); session.evict(Classess);//Classess对象从session中清空了 session.update(Classess);//把Classess对象放入到了session缓存中 Classess = (Classess)session.get(Classess.class, 1L); transaction.commit(); } /** * session.clear */ @Test public void testClear(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); session.clear();//Classess对象从session中清空了 Classess = (Classess)session.get(Classess.class, 1L); transaction.commit(); } @Test public void testClearTest(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); session.clear();//如果不加这句话,两个不同的对象,相同的ID值,所以得把其中的一个清空 Classess Classess2 = new Classess(); Classess2.setCid(1L); Classess2.setCname("asfd"); session.update(Classess2); transaction.commit(); } /** * 把数据库中的数据刷新到缓存中 */ @Test public void testRefresh(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); Classess.setCname("66"); session.refresh(Classess);//把cid为1的值从数据库刷到了缓存中 System.out.println(Classess.getCname()); transaction.commit(); } /** * session.flush */ @Test public void testFlush(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess =(Classess)session.get(Classess.class, 1L); Classess.setCname("afdsasdf"); Set<Student> students = Classess.getStudents(); for(Student student:students){ student.setDescription("asdf"); } session.flush(); transaction.commit(); } /** * 批量操作 */ @Test public void testSaveBatch(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); for(int i=6;i<1000000;i++){ Classess Classess = new Classess(); Classess.setCname("aaa"); Classess.setDescription("afds"); session.save(Classess); if(i%50==0){ session.flush(); session.clear(); } } transaction.commit(); } /** * session.flush只是发出SQL语句了,并没有清空session缓存 */ @Test public void testFlush2(){ Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Classess Classess = (Classess)session.get(Classess.class, 1L); session.flush(); Classess = (Classess)session.get(Classess.class, 1L); transaction.commit(); } }
二级缓存:存放公有数据
1、适用场合:
1、数据不能频繁更新
2、数据能公开,私密性不是很强
2、hibernate本身并没有提供二级缓存的解决方案
(1.在hibernate中二级缓存用的不多,如果数据跟新频繁,是不会放入二级缓存之中不会提高效率,2.如果不用跟新,直接和数据库交互3.因为是公有数据,每个线程访问还有加密?不懂 )
3、二级缓存的实现是依赖于第三方供应商完成的
ehcache
oscache
jbosscache
swamchache
4、二级缓存的操作
1、二级缓存存在sessionFactory中
2、生命周期:与sessionFactory保持一致(容器启动sessionFactory产生,容器关闭sessionFactory关闭)
3、使用二级缓存的步骤
1、在hibernate.cfg.xml
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
2、让某一个对象进入到二级缓存中
* 在配置文件中
<class-cache usage="read-only" class="cn.itcast.hiberate.sh.domain.Classes"/>
* 在映射文件中
<cache usage="read-only"/>
3、使用
session.get/session.load
/** * session.get * 把数据存在一级缓存和二级缓存 */ @Test public void testGet11(){ Session session = sessionFactory.openSession(); Classess Classess = (Classess)session.get(Classess.class, 1L); session.close(); session = sessionFactory.openSession(); Classess = (Classess)session.get(Classess.class, 1L); session.close(); } /** * session.load * 同上 */ @Test public void testLoad22(){ Session session = sessionFactory.openSession(); Classess Classess = (Classess)session.load(Classess.class, 1L); Classess.getCname(); session.close(); session = sessionFactory.openSession(); Classess = (Classess)session.load(Classess.class, 1L); Classess.getCname(); session.close(); } /** * session.update */ @Test public void testUpdate11(){ Session session = sessionFactory.openSession(); //session.beginTransaction(); Classess Classess = new Classess(); Classess.setCid(1L); Classess.setCname("aaa"); session.update(Classess); session.close(); session = sessionFactory.openSession(); Classess = (Classess)session.get(Classess.class, 1L); session.close(); }
5、查询缓存
在hibernate配置文件添加<property name="cache.use_query_cache">true</property>
@Test public void testQuery(){ Session session = sessionFactory.openSession(); Query query = session.createQuery("from Classess"); query.setCacheable(true);//Classess里的所有的数据要往查询缓存中存放了 List<Classess> ClassessList = query.list(); query = session.createQuery("from Classess");//查询缓存中的数据,sql语句必须和缓存的数据一致,才能利用查询缓存 query.setCacheable(true);//取出缓存数据 ClassessList = query.list(); session.close(); }
6.大量数据缓存
在src下添加一个配置文件ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="D:\\TEMP1"/> <defaultCache maxElementsInMemory="12" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <Cache name="cn.itcast.domain.Classes" maxElementsInMemory="5" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache> @Test public void testAllClassess(){ Session session = sessionFactory.openSession(); List<Classess> ClassessList = session.createQuery("from Classess").list(); session.close(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
标签:hibernate
原文地址:http://pengya123.blog.51cto.com/8467424/1811634