码迷,mamicode.com
首页 > Web开发 > 详细

hibernate缓存

时间:2016-07-06 21:56:44      阅读:283      评论:0      收藏:0      [点我收藏+]

标签:hibernate

20.session的一级缓存

1.什么是缓存?

缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做缓存命 中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗。

 

2.Hibernate缓存分类:

一、Session缓存(又称作事务缓存):Hibernate内置的,不能卸除。

缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。

 

二、SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。

缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。

缓存策略提供商:

提供了HashTable缓存,EHCacheOSCacheSwarmCachejBoss Cathe2,这些缓存机制,其中EHCacheOSCache是不能用于集群环境(Cluster Safe)的,而SwarmCachejBoss Cathe2是可以的。HashTable缓存主要是用来测试的,只能把对象放在内存中,EHCacheOSCache可以把对象放在内存(memory)中,也可以把对象放在硬盘(disk)上(为什么放到硬盘上?上面解释了)。

 

 

session缓存:

   1、生命周期就是session的生命周期

   2session一级缓存存放的数据都是私有数据

        把session存放在threadlocal中,不同的线程是不能访问的,所以保证了数据的安全性

   3、怎么样把数据存放到一级缓存中

        利用session.save/update/load/get方法都可以存放在一级缓存中

   4、利用session.get/load方法可以把数据从一级缓存中取出

   5session.evict方法可以把一个对象从一级缓存中清空

   6、利用session.clear方法可以把session中的所有的数据清空

   7、利用session.Refresh方法把数据库中的数据同步到缓存中

   8session.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();
    }
}

21.二级缓存

二级缓存:存放公有数据

   1、适用场合:

        1、数据不能频繁更新

        2、数据能公开,私密性不是很强

   2hibernate本身并没有提供二级缓存的解决方案

(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缓存

标签:hibernate

原文地址:http://pengya123.blog.51cto.com/8467424/1811634

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!