zoukankan      html  css  js  c++  java
  • hibernate二级缓存

    缓存的作用:  提高程序的性能

      ehcache:Ehcache 是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大

    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开始,支持高性能的分布式缓存,兼具灵活性和扩展性

    hibernate(5.2.12.Final)中使用二级缓存步骤(ehcache)
    导入ehcache相关依赖
    <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>5.2.12.Final</version>
    </dependency>

     src添加ehcache.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>

    指定实体类开启二级缓存
    <!-- 注解式开发 -->
    <class-cache usage="read-write" class="entity.Dict"/>

    <!-- xml配置方式 -->
    <class table="t_sys_dict" name="entity.Dict">
    <cache usage="read-write"/>
    .......
    </class>

    案例:

    利用map集合实现缓存原理:

    EhcacheDemo1:

    package com.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("从数据库中读取数据");
    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"));
    }
    }

      

    利用缓存存储数据:

    EhcacheDemo2:

    package com.test;
    
    import com.util.EhcacheUtil;
    
    /**
     * 演示利用缓存存储数据
     * @author Administrator
     *
     */
    public class EhcacheDemo2 {
    	public static void main(String[] args) {
    		System.out.println(System.getProperty("java.io.tmpdir"));
    		EhcacheUtil.put("com.entity.Book", 11, "zhangsan");
    		System.out.println(EhcacheUtil.get("com.entity.Book", 11));
    	}
    }
    

      EhcacheUtil:

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

      导入pom依赖:

    <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</groupId>
    	<artifactId>HIbernate3</artifactId>
    	<packaging>war</packaging>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>HIbernate3 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>org.hibernate</groupId>
    			<artifactId>hibernate-core</artifactId>
    			<version>${hibernate.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>javax.servlet-api</artifactId>
    			<version>${servlet.version}</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<version>${mysql.driver.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>net.sf.ehcache</groupId>
    			<artifactId>ehcache</artifactId>
    			<version>${ehcache.version}</version>
    		</dependency>
    
    		<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>Hibernate3</finalName>
    		<plugins>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>3.7.0</version>
    				<configuration>
    					<source>${maven.compiler.source}</source>
    					<target>${maven.compiler.target}</target>
    					<encoding>${project.build.sourceEncoding}</encoding>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    </project>
    

      hibernate.cfg.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE hibernate-configuration PUBLIC
    	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    	<session-factory>
    		<!-- 1. 数据库相关 -->
    		<property name="connection.username">root</property>
    		<property name="connection.password">123</property>
    		<property name="connection.url">jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=UTF-8
    		</property>
    		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    
    		<!-- 配置本地事务(No CurrentSessionContext configured!) -->
    		<property name="hibernate.current_session_context_class">thread</property>
    
    		<!-- 2. 调试相关 -->
    		<property name="show_sql">true</property>
    		<property name="format_sql">true</property>
    
    		<!-- 开启二级缓存 -->
    		<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>
    		<!-- 3. 添加实体映射文件 -->
    		<mapping resource="com/entity/user.hbm.xml" />
    
    
    		<!-- 主键生成策略 -->
    		<!-- <mapping resource="com/entity/Worker.hbm.xml" /> -->
    		<!-- <mapping resource="com/entity/Student.hbm.xml" /> -->
    		<!-- 关联关系(一对多) -->
    	<!-- 	<mapping resource="com/entity/Order.hbm.xml" />
    		<mapping resource="com/entity/OrderItem.hbm.xml" /> -->
    		<!-- 一对多自关联 -->
    	<!-- 	<mapping resource="com/entity/TreeNode.hbm.xml" /> -->
    		<!-- -->
    		<!-- <mapping resource="com/entity/Book.hbm.xml" />
    		<mapping resource="com/entity/category.hbm.xml" /> -->
    	</session-factory>
    </hibernate-configuration>
    

      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="20" overflowToDisk="false" diskPersistent="false"
                      timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
    
    
        <!--name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)-->
        <cache name="com.entity.User" eternal="false" maxElementsInMemory="20"
               overflowToDisk="true" diskPersistent="false" timeToIdleSeconds="0"
               timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
    </ehcache>
    

      

    开启二级缓存后,默认查询单个的话是会使用二级缓存的,但是查询多条记录是不会使用二级缓存的;

    并且在这里需要区分session级别的缓存与sessionfactory级别的缓存;

     验证:创建一个dao方法:

    package com.dao;
    
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.entity.User;
    import com.util.SessionFactoryUtils;
    
    public class UserDao {
    
    	public User get(User u) {
    		Session session = SessionFactoryUtils.openSession();
    		Transaction transaction = session.beginTransaction();
    		
    		User user = session.get(User.class, u.getId());
    		
    		
    		transaction.commit();
    		session.close();
    		return user;
    	}
    }
    

      

     演示查单个用户使用了缓存:

    	package com.test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.dao.UserDao;
    import com.entity.User;
    import com.util.SessionFactoryUtils;
    
    
    /**
     * 演示查单个用户使用了缓存
     * @author Administrator
     *
     */
    public class EhcacheDemo3 {
    	/**
    	 * 默认情况下,sql语句形成了三次,这里为了提高性能,必须使用二级缓存SessionFactory缓存
    	 *  <!-- 开启二级缓存 -->
    	 *  <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>
          
          	映射文件中添加标签
          	<cache usage="read-write" region="com.javaxl.one.entity.User"/>
          	这里的region指的是Ehcache.xml中cacheName
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		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);
    		
    	}
    	
    	/**
    	 * 同一个session,sql语句只生成一次,这里用到了一级缓存
    	 */
    	public static void main() {
    		Session session = SessionFactoryUtils.openSession();
    		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();
    	}
    }
    

      

      

    hibernate二级缓存不会同时缓存多条数据
    package com.test;
    
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.query.Query;
    
    import com.util.SessionFactoryUtils;
    
    
    /**
     * hibernate二级缓存不会同时缓存多条数据
     * @author Administrator
     *
     */
    public class EhcacheDemo4 {
    	public static void main(String[] args) {
    		Session session = SessionFactoryUtils.openSession();
    		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();
    	}
    }
    

      

    注:需要编写代码来开启二级缓存的
    query.setCacheRegion("entity.Dict");//指定缓存策略,名字必须实体类的完整类名
    query.setCacheable(true);//手动开启二级缓存




  • 相关阅读:
    ubuntu 安装 redis desktop manager
    ubuntu 升级内核
    Ubuntu 内核升级,导致无法正常启动
    spring mvc 上传文件,但是接收到文件后发现文件变大,且文件打不开(multipartfile)
    angular5 open modal
    POJ 1426 Find the Multiple(二维DP)
    POJ 3093 Margritas
    POJ 3260 The Fewest Coins
    POJ 1837 Balance(二维DP)
    POJ 1337 A Lazy Worker
  • 原文地址:https://www.cnblogs.com/omji0030/p/11332714.html
Copyright © 2011-2022 走看看