hibernate Level 2 Cache

Keywords: Java Ehcache Hibernate Maven

1. What kind of data needs to be cached


1. Data rarely modified
2. Less important data, allowing occasional concurrent data
3. Data that will not be accessed concurrently
4. Reference data refers to constant data that provides reference for use. It has a limited number of instances, and its instances are referenced by instances of many other classes. Instances are rarely or never modified.

2. What is a data dictionary


All the base data in a project is all the drop-down boxes in the project

Problem to solve: If you have one hundred drop-down boxes, then you need to create one hundred tables. Data caching omits the creation of large tables

Table design:

        Data Source Table: Data Source Identification, Data Source Description

        Item Table: Data Source Identification, Data Key, Data Value Key

3. Relational and non-relational databases


Relational databases: Databases that relate (relate) data to data     mysql/Oracle, sqlserver

Non-relational databases: There is no relationship between data and data, such as key-value

There are three types: 1. File-based databases: ehcache
                      2. Memory-based databases: redis, memcache
                      3. Document-based database: mongodb
 

4.map Collection Implementation Caching Principle

 

When the specified data cannot be found in the cache, access the database to get the data and store it in the cache.

package com.wyy.text;

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

/**
 * Simple implementation of caching principle using map collection
 * @author Administrator
 *
 */
public class EhcacheDemo1 {
	static Map<String, Object> cache = new HashMap<String, Object>();
	static Object getValue(String key) {
		Object value = cache.get(key);
		if(value == null) {
			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"));
	}
}

Output results:

  5. Use of ehcache

5.1 Import Dependencies

        <dependency>
         <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.10.0</version>
        </dependency>

5.2ehcache Profile

<?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">
    <!--Disk Storage:Objects temporarily not used in the cache,Transfer to Hard Disk,Be similar to Windows System Virtual Memory-->
    <!--path:Specify the path to store the object on the hard disk-->
    <!--java.io.tmpdir Is the default temporary file path. You can print out specific file paths as follows System.out.println(System.getProperty("java.io.tmpdir"));-->
    <diskStore path="D:\ehcache"/>


    <!--defaultCache: Default Management Policy-->
    <!--eternal: Set Cached elements Will it never expire? If is true,The cached data is always valid if it is false Then also depend on timeToIdleSeconds,timeToLiveSeconds judge-->
    <!--maxElementsInMemory: Cached in memory element Maximum number-->
    <!--overflowToDisk: If in-memory data exceeds memory limits, do you want to cache it to disk?-->
    <!--diskPersistent: Whether to persist on disk. Refer to Restart jvm After that, is the data valid? Default to false-->
    <!--timeToIdleSeconds: Object idle time(Unit: seconds),Refers to how long an object has not been accessed before it becomes invalid. Only for eternal by false Effective. The default value of 0 means always accessible-->
    <!--timeToLiveSeconds: Object Lifetime(Unit: seconds),Refers to the time it takes for an object to be created until it fails. Only for eternal by false Effective. The default value of 0 means always accessible-->
    <!--memoryStoreEvictionPolicy: Three Cleanup Strategies for Cache-->
    <!--FIFO: first in first out (FIFO)-->
    <!--LFU: Less Frequently Used (Minimum use).This means that it has been used least. The cached element has one hit Properties, hit Minimum value will be flushed out of the cache-->
    <!--LRU: Least Recently Used(Minimum recently used). (ehcache Default value).Cached elements have a timestamp, and when the cache is full and you need to make room to cache new elements, the elements with the farthest timestamp from the current time in the existing cached elements will be flushed out of the cache-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>


    <!--name:  Cache Name, must be unique(ehcache Will put this cache put to HashMap in)-->
    <cache name="com.javaxl.one.entity.User" eternal="false" maxElementsInMemory="100"
           overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
           timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
</ehcache>

Three Core Interfaces in 5.3ehcache

  •   CacheManager: Cache Manager
  • Cache: Cache object, several caches can be placed in the cache manager to store the essence of the data. All caches implement the Ehcache interface
  •   Element: The unit that makes up a single piece of cached data

  EhcacheUtil class

package com.zking.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);
        }
    }

   
    /**
     * Storage value
     * @param cacheName
     * @param key
     * @param value
     */
    public static void put(String cacheName, Object key, Object value) {
        Cache cache = cacheManager.getCache(cacheName);
        if (null == cache) {
            //Add a Cache named cacheName with the default configuration
            cacheManager.addCache(cacheName);
            cache = cacheManager.getCache(cacheName);
        }
        cache.put(new Element(key, value));
    }

    /**
     * Value
     * @param cacheName
     * @param key
     * @return
     */
    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);
    }
}

Test Code

package com.wyy.text;

import com.zking.util.EhcacheUtil;

/**
 * Demonstrate using a cache to store data
 * @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));
	}
}

  When you do not set the storage address <diskStore path="xxx"/>, there will be a default temporary path, java.io.tmpdir

Output results:  

 

  When data stored in memory exceeds the memory limit set in the configuration file, it will be stored in the location <diskStore path="xxx"/>.

6.hibernate Level 2 Cache

By default, hibernate has a first-level cache, which is the default Session cache. When we make a query, hibernate caches this result, called a first-level cache. When we then make another query with the same conditions in this Session session, hibernate does not query the database again, but gets the results directly in the first-level cache and returns them. The first level cache is built-in. A first-level cache is a cache made by a query within the same Session session that is invalid if it crosses a Session or if the current Session is closed and a new Session is reopened.

Secondary caching is a pluggable cache, optional or nonexistent. If you configure it, it does. If you do not configure it, it does not. Implementation of secondary cache, default is ehcache

6.1 Level 1 Cache Instance

	/**
	 * The same session, the sql statement is only generated once, where the first level cache is used
	 */
	public void test1() {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		
		User user = session.get(User.class, 7);
		System.out.println(user);
		User user2 = session.get(User.class, 7);
		System.out.println(user2);
		User user3 = session.get(User.class, 7);
		System.out.println(user3);
		
		transaction.commit();
		session.close();
	}

Print results

Different Session Session Queries

public void test2() {
		UserDao userDao  = new UserDao();
		User u = new User();
		u.setId(7);
		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);
		
	}
	

  Print results

Three SQL statements are generated, and performance is degraded

6.2 Level 2 Cache

6.2.1 Introducing Dependency

<dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-ehcache</artifactId>
        <version>5.2.12.Final</version>
      </dependency>

Opening two caches in 6.2.2 hibernate.cfg.xml  

<property name="hibernate.cache.use_second_level_cache">true</property>
      <!-- Turn on query cache -->
      <property name="hibernate.cache.use_query_cache">true</property>
      <!-- EhCache drive -->
      <!-- 	Note: You must use hibernate 5.2.12.Final Edition -->
      <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
      

6.2.3 Mapping File

Turn on secondary caching in mapping files of entity class objects that require secondary caching

<cache usage="read-write" region="com.wyy.entity.User"/>

Run the above method again

   Compared with the printed results above, SQL only produces one, that is, it queries the database once.

7.hibernate secondary cache stores multiple pieces of data  

public static void main(String[] args) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		
		Query query = session.createQuery("from User");
		List list = query.list();
		System.out.println(list);
		List list2 = query.list();
		System.out.println(list2);
		List list3 = query.list();
		System.out.println(list3);
		
		
		transaction.commit();
		session.close();
	}

Output Results

As you can see from the background print results, three SQL s are still generated. Think about the failure of the secondary cache? Actually, the secondary cache is still valid, just because hibernate does not cache multiple pieces of data by default.

Open it manually when we need to cache more than one piece of data

public static void main(String[] args) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		
		Query query = session.createQuery("from User");
		query.setCacheable(true);
		List list = query.list();
		System.out.println(list);
		List list2 = query.list();
		System.out.println(list2);
		List list3 = query.list();
		System.out.println(list3);
		
		
		transaction.commit();
		session.close();
	}

Posted by albatros21 on Wed, 20 Oct 2021 14:05:01 -0700