一級緩存二級緩存的概念解釋
(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)對象,就能夠操做會話工廠中的第二級緩存的數據。