1. 程式人生 > >【Hibernate】解析hibernate中的緩存

【Hibernate】解析hibernate中的緩存

list gre mit details temp odin ica 所有 roo

Hibernate中的緩存一共有三種,一級緩存、二級緩存、查詢緩存。緩存除了使用Hibernate自帶的緩存,還可以使用redis進行緩存,或是MongoDB進行緩存。

所使用的Demo:

技術分享

User.java文件

技術分享
package cn.test.bean;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="user")//
表示對應的表名 public class User { @Id @Column(name="uid") private int id; @Column(name="uname") private String name; @Column(name="upass") private String password; public int getId() { return id; } public void setId(int id) { this.id = id; }
public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
User.java

hibernate.cfg.xml

技術分享
<?xml version=‘1.0‘ encoding=‘UTF-8‘?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>
    <session-factory>
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">517839</property>
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        
        <!-- 加載映射描述信息 -->
        <mapping class="cn.test.bean.User" />
        
    </session-factory>
</hibernate-configuration>
hibernate.cfg.xml

其中:

        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

表示開啟打印底層執行的SQL日誌。

下面這是圖片反應了hibernate緩存的大致流程:

技術分享

1,一級緩存

每個 Session 對象創建出來,就會分配一塊緩存空間,可以存儲 session 對象訪問的對象信息。 session 關閉後會自動清除緩存,手動清除可以用session.clear() , session.evict(obj) 。 Session 一級緩存是獨享。
load/get/save/update/saveorupdate 方法處理的對象都會放入緩存中

Configuration conf = new Configuration();
conf.configure("hibernate.cfg.xml");//讀取連接參數和映射描述信息
SessionFactory factory = conf.buildSessionFactory();
Session session = factory.openSession();
            
User user1 = (User)session.load(User.class,1);
System.out.println(user1.getName());//honny

//先從session緩存中查找,如果沒找到再去數據庫獲取
User user2 = (User)session.load(User.class,1);
System.out.println(user2.getName());//honny
            
System.out.println(user1==user2);//true,因為user1和user2使用的是同一個session

然後再來看一看控制臺:

技術分享

從控制臺中,我們也可以看出上只執行了一次SQL查詢。

一級查詢的優缺點:

優點:可以減少查詢數據庫的次數,加快查詢速度。
缺點:在批量操作中容易導致內存溢出問題。

2,二級緩存

二級緩存是SessionFactory 對象緩存,可以被創建出的多個 Session 對象共享。

下面是一張圖片體現一級緩存和二級緩存的關系:

技術分享

從這個我們就看出了二級緩存包含了一級緩存。

二級緩存默認是關閉的,如果要使用需要手動開啟,下面是開啟過程:

1.導入ehcache 工具包和 ehcache.xml 配置文件(配置文件放到src路徑下)

echache工具包包括:ehcache-core-2.4.3.jar,hibernate-ehcache-4.2.21.Final.jar,slf4j-api-1.6.1.jar

ehcache.xml 文件

技術分享
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
  ~ indicated by the @author tags or express copyright attribution
  ~ statements applied by the authors. All third-party contributions are
  ~ distributed under license by Red Hat Middleware LLC.
  ~
  ~ This copyrighted material is made available to anyone wishing to use, modify,
  ~ copy, or redistribute it subject to the terms and conditions of the GNU
  ~ Lesser General Public License, as published by the Free Software Foundation.
  ~
  ~ This program is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->
<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User‘s home directory
         user.dir - User‘s current working directory
         java.io.tmpdir - Default temp file path -->
    <diskStore path="./target/tmp"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <!--Predefined caches.  Add your cache configuration settings here.
        If you do not have a configuration for your cache a WARNING will be issued when the
        CacheManager starts

        The following attributes are required for defaultCache:

        name              - Sets the name of the cache. This is used to identify the cache. It must be unique.
        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->

    <!-- Sample cache named sampleCache1
        This cache contains a maximum in memory of 10000 elements, and will expire
        an element if it is idle for more than 5 minutes and lives for more than
        10 minutes.

        If there are more than 10000 elements it will overflow to the
        disk cache, which in this configuration will go to wherever java.io.tmp is
        defined on your system. On a standard Linux system this will be /tmp"
        -->
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>
ehcache.xml

2.在 hibernate.cfg.xml 中配置參數開啟二級緩存,啟用 ehcache

<property name="hibernate.cache.use_sencond_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>

3.在要緩存的對象類型中,指定 @Cache 註解標記

@Entity
@Table(name="user")//表示對應的表名
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class User {
    //........
}

到這裏hibernate的二級緩存配置就配好了,下面來測試一下:

Configuration conf = new Configuration();
conf.configure("hibernate.cfg.xml");//讀取連接參數和映射描述信息
SessionFactory factory = conf.buildSessionFactory();
Session session1 = factory.openSession();
User user1=(User)session1.load(User.class, 1);
System.out.println(user1.getName());//honny

Session session2 = factory.openSession();
//先從緩存中查找,如果沒有查到再去數據庫中取
User user2=(User)session2.load(User.class, 1);
System.out.println(user2.getName());//honny

下面是控制臺打印的打印:

技術分享

我們可以看出,用同一個SessionFactory的兩個不同session對象查詢相同的數據,只從數據庫中取了一次。

3,查詢緩存

一級和二級緩存,只能緩存單個對象,如果需要緩存一個結果集,必須使用查詢緩存。

查詢緩存默認也是關閉的,如需使用需要手動開啟,下面是開啟過程:

1.針對的對象必需已經開啟了一級緩存

2.在 hibernate.cfg.xml 中添加開啟查詢緩存的配置

<property name="hibernate.cache.use_query_cache">true</property>

3.在查詢執行前,調用 query.setCacheable(true);

下面看一看測試:

        String hql="from User";
        Configuration conf=new Configuration();
        conf.configure("hibernate.cfg.xml");
        SessionFactory factory=conf.buildSessionFactory();
        Session session1 = factory.openSession();
        Query query1 = session1.createQuery(hql);
        query1.setCacheable(true);//設置開啟緩存
        List list1 = query1.list();
        for(Object user:list1){
            System.out.println(((User)user).getName());
        }
        System.out.println("------------------------");
        Session session2 = factory.openSession();
        Query query2 = session2.createQuery(hql);
        query2.setCacheable(true);
        List list2 =query2.list();
        for(Object user:list2){
            System.out.println(((User)user).getName());
        }

然後來看一看控制臺:

技術分享

從控制臺中,我們可以看出,底層查詢的數據庫的過程也只執行了一次。

上面就是hibernate的三種緩存。最後總結一下,並不是所有的方法都會產生緩存效果,只有“load/get/save/update/saveorupdate”才會產生緩存效果。三種緩存中一級緩存是默認開啟的,二級緩存和三級緩存默認是關閉的。

【Hibernate】解析hibernate中的緩存