Hibernate之二級緩存

      

一級緩存二級緩存的概念解釋
(1)一級緩存就是Session級別的緩存,一個Session作了一個查詢操做,它會把這個操做的結果放在一級緩存中,若是短期內這個java

session(必定要同一個session)又作了同一個操做,那麼hibernate直接從一級緩存中拿,而不會再去連數據庫,取數據;mysql

(2)二級緩存就是SessionFactory級別的緩存,顧名思義,就是查詢的時候會把查詢結果緩存到二級緩存中,若是同一個sessionFactory算法

建立的某個session執行了相同的操做,hibernate就會從二級緩存中拿結果,而不會再去鏈接數據庫;sql

(3)Hibernate中提供了兩級Cache,第一級別的緩存是Session級別的緩存,它是屬於事務範圍的緩存。這一級別的緩存由hibernate管理數據庫

的,通常狀況下無需進行干預;第二級別的緩存是SessionFactory級別的緩存,它是屬於進程範圍或羣集範圍的緩存。這一級別的緩
存能夠進行配置和更改,而且能夠動態加載和卸載。 Hibernate還爲查詢結果提供了一個查詢緩存,它依賴於第二級緩存;

apache

SessionFactory類用於保存二級緩存數據。 它是全部會話對象的全局,默認狀況下是不啓用的。默認啓用session一級緩存api

 

 

ehcache是什麼?
Ehcache 是如今最流行的純Java開源緩存框架,配置簡單、結構清晰、功能強大

注1:這裏介紹的是2.X版本,3.x的版本和2.x的版本API差別比較大緩存

 

 

 


ehcache的特色
1.夠快
Ehcache的發行有一段時長了,通過幾年的努力和不可勝數的性能測試,Ehcache終被設計於large, high concurrency systems.
2.夠簡單
開發者提供的接口很是簡單明瞭,從Ehcache的搭建到運用運行僅僅須要的是你寶貴的幾分鐘。其實不少開發者都不知道本身用在用Ehcache,Ehcache被普遍的運用於其餘的開源項目
3. 夠袖珍
關於這點的特性,官方給了一個很可愛的名字small foot print ,通常Ehcache的發佈版本不會到2M,V 2.2.3 才 668KB。
4. 夠輕量
核心程序僅僅依賴slf4j這一個包,沒有之一!
5. 好擴展
Ehcache提供了對大數據的內存和硬盤的存儲,最近版本容許多實例、保存對象高靈活性、提供LRU、LFU、FIFO淘汰算法,基礎屬性支持熱配置、支持的插件多
6. 監聽器
緩存管理器監聽器 (CacheManagerListener)和 緩存監聽器(CacheEvenListener),作一些統計或數據一致性廣播挺好用的
7. 分佈式緩存
從Ehcache 1.2開始,支持高性能的分佈式緩存,兼具靈活性和擴展性session


 

配合一段代碼來理解一下緩存:app

package com.psy.six.test;

import java.util.HashMap;
import java.util.Map;

/**
 * 利用map集合簡易實現緩存原理
 * @author Administrator
 *
 */
public class EhcacheDemo1 {
    static Map<String, Object> cache = new HashMap<String, Object>();
    static Object getValue(String key) {
        Object value = cache.get(key);
        System.out.println("從緩存中獲取數據");
        if(value == null) {
            System.out.println("從軟件箱對應的配置文件中獲取數據(數據庫)");
            System.out.println("hello zs");
            cache.put(key, new String[] {"zs"});
            return cache.get(key);
        }
        return value;
    }
    
    public static void main(String[] args) {
        System.out.println(getValue("sname"));
        System.out.println(getValue("sname"));
    }
}

第一次查詢緩存中沒有數據 訪問的是數據庫 查詢耗時

第二次查詢的時候數據已經在緩存中了 查詢的速度相對來講會快一點

 


Hibernate中使用二級緩存步驟(Ehcache)

1.導入相關依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cpc</groupId>
    <artifactId>CpC-Hibernate</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>CpC-Hibernate Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <junit.version>4.12</junit.version>
        <servlet.version>4.0.0</servlet.version>
        <hibernate.version>5.2.12.Final</hibernate.version>
        <mysql.driver.version>5.1.46</mysql.driver.version>

        <ehcache.version>2.10.0</ehcache.version>
        <slf4j-api.version>1.7.7</slf4j-api.version>
        <log4j-api.version>2.9.1</log4j-api.version>

    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.driver.version}</version>
        </dependency>
        <!--ehcache的核心依賴-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>${ehcache.version}</version>
        </dependency>
        
        <!--這裏導入hibernate和ehcache橋接-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <!-- slf4j核心包(這是抽象日誌)-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j-api.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!--用於與slf4j保持橋接 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>${log4j-api.version}</version>
        </dependency>

        <!--核心log4j2jar包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j-api.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>CpC-Hibernate</finalName>
        <plugins>
            <!--配置maven-compiler-plugin插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--磁盤存儲:將緩存中暫時不使用的對象,轉移到硬盤,相似於Windows系統的虛擬內存-->
    <!--path:指定在硬盤上存儲對象的路徑-->
    <!--java.io.tmpdir 是默認的臨時文件路徑。 能夠經過以下方式打印出具體的文件路徑 System.out.println(System.getProperty("java.io.tmpdir"));-->
    <diskStore path="D://xxx"/>


    <!--defaultCache:默認的管理策略-->
    <!--eternal:設定緩存的elements是否永遠不過時。若是爲true,則緩存的數據始終有效,若是爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷-->
    <!--maxElementsInMemory:在內存中緩存的element的最大數目-->
    <!--overflowToDisk:若是內存中數據超過內存限制,是否要緩存到磁盤上-->
    <!--diskPersistent:是否在磁盤上持久化。指重啓jvm後,數據是否有效。默認爲false-->
    <!--timeToIdleSeconds:對象空閒時間(單位:秒),指對象在多長時間沒有被訪問就會失效。只對eternal爲false的有效。默認值0,表示一直能夠訪問-->
    <!--timeToLiveSeconds:對象存活時間(單位:秒),指對象從建立到失效所須要的時間。只對eternal爲false的有效。默認值0,表示一直能夠訪問-->
    <!--memoryStoreEvictionPolicy:緩存的3 種清空策略-->
    <!--FIFO:first in first out (先進先出)-->
    <!--LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的。緩存的元素有一個hit 屬性,hit 值最小的將會被清出緩存-->
    <!--LRU:Least Recently Used(最近最少使用). (ehcache 默認值).緩存的元素有一個時間戳,當緩存容量滿了,而又須要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>


    <!--name: Cache的名稱,必須是惟一的(ehcache會把這個cache放到HashMap裏)-->
    <cache name="com.javaxl.one.entity.User" eternal="false" maxElementsInMemory="100"
           overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
           timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
</ehcache>

3.hibernate.cfg.xml

<!-- 開啓二級緩存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 開啓查詢緩存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- EhCache驅動 -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

4.演示

package com.psy.six.util;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import java.io.InputStream;

public class EhcacheUtil {

    private static CacheManager cacheManager;

    static {
        try {
            InputStream is = EhcacheUtil.class.getResourceAsStream("/ehcache.xml");
            cacheManager = CacheManager.create(is);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private EhcacheUtil() {
    }

    public static void put(String cacheName, Object key, Object value) {
        Cache cache = cacheManager.getCache(cacheName);
        if (null == cache) {
            //以默認配置添加一個名叫cacheName的Cache
            cacheManager.addCache(cacheName);
            cache = cacheManager.getCache(cacheName);
        }
        cache.put(new Element(key, value));
    }


    public static Object get(String cacheName, Object key) {
        Cache cache = cacheManager.getCache(cacheName);
        Element element = cache.get(key);
        return null == element ? null : element.getValue();
    }

    public static void remove(String cacheName, Object key) {
        Cache cache = cacheManager.getCache(cacheName);
        cache.remove(key);
    }
}
/**
 * 演示利用緩存存儲數據
 * @author Administrator
 *
 */
public class EhcacheDemo2 {
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.io.tmpdir"));
        EhcacheUtil.put("com.javaxl.four.entity.Book", 11, "zhangsan");
        System.out.println(EhcacheUtil.get("com.javaxl.four.entity.Book", 11));
    }
}

 

ehcache.xml中添加:

 <!--name: Cache的名稱,必須是惟一的(ehcache會把這個cache放到HashMap裏)-->
    <cache name="com.psy.one.entity.User" eternal="false" maxElementsInMemory="100"
           overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
           timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>

 

package com.psy.one.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.psy.one.entity.User;
import com.psy.two.util.SessionFactoryUtils;

public class UserDao {

    public User get(User user) {
        Session session = SessionFactoryUtils.openSession();
        Transaction transaction = session.beginTransaction();
        
        User u = session.get(User.class, user.getId());
        
        

        transaction.commit();
        session.close();
        return u;
    }
    
    
    public static void main(String[] args) {
                UserDao userDao  = new UserDao();
                User u = new User();
                u.setId(2);
                User user = userDao.get(u);
                System.out.println(user);
                User user2 = userDao.get(u);
                System.out.println(user2);
                User user3 = userDao.get(u);
                System.out.println(user3);
    }
}

這裏利用了二級緩存,查詢三次但只訪問了一次數據庫

 

  Hibernate第二級緩存是會話工廠的全部會話(Session)對象所使用的公共緩存。 若是您有來自會話工廠的多個會話(Session)對象,就能夠操做會話工廠中的第二級緩存的數據。

相關文章
相關標籤/搜索