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

    Hibernate第二级缓存是会话工厂的所有会话(Session)对象所使用的公共缓存。 如果您有来自会话工厂的多个会话(Session)对象,就可以操作会话工厂中的第二级缓存的数据。

    SessionFactory类用于保存二级缓存数据。 它是所有会话对象的全局,默认情况下是不启用的。

    不同厂商提供了二级缓存的实现。

    1. EH二级缓存
    2. OS二级缓存
    3. Swarm二级缓存
    4. JBoss二级缓存

    每个实现提供不同的缓存使用功能。 有四种方法可以使用二级缓存。

    1. 只读:缓存将适用于只读操作。
    2. 非严格读写:缓存可用于读写,但一次只能读写。
    3. 读写:缓存将用于读写,可以同时使用。
    4. 事务处理:缓存将用于事务处理。
      缓存使用属性可以应用于hbm.xml文件中的类或集合级别。 下面给出了定义缓存使用情况的例子:
      <cache usage="read-only" />
      
      XML
      下面来看看看二级缓存实现和缓存使用情况。
    实现只读非限制读写读写操作
    EH二级缓存 Yes Yes Yes No
    OS二级缓存 Yes Yes Yes No
    Swarm二级缓存 Yes Yes No No
    JBoss二级缓存 No No No Yes

    使用EH缓存的二级缓存示例的额外步骤

    1)在hibernate.cfg.xml文件中添加2个配置设置

    <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>  
    <property name="hibernate.cache.use_second_level_cache">true</property>
    
    XML

    2) 在hbm文件中添加缓存使用情况设置

    <cache usage="read-only" />
    
    XML

    3) 创建ehcache.xml文件

    <?xml version="1.0"?>  
    <ehcache>  
        <defaultCache maxElementsInMemory="100"  eternal="true"/>  
    </ehcache>
    
    XML

    Hibernate二级缓存示例

    要通过下面示例了解二级缓存,我们需要创建一个Java项目:secondlevel, 其完整的目录结构如下所示 -

    创建以下页面:

    1. Employee.java
    2. employee.hbm.xml
    3. hibernate.cfg.xml
    4. ehcache.xml
    5. MainTest.java

    注意:在这里,我们假设,在MySQL数据库中有一个emp_cache2表并包含一些记录。

    文件: Employee.java

    package com.yiibai;
    
    public class Employee {
        private int id;
        private String name;
        private float salary;
    
        public Employee() {
            super();
        }
    
        public Employee(String name, float salary) {
            super();
            this.name = name;
            this.salary = salary;
        }
    
        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 float getSalary() {
            return salary;
        }
    
        public void setSalary(float salary) {
            this.salary = salary;
        }
    
    }
    
    Java

    文件: employee.hbm.xml

    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE hibernate-mapping PUBLIC
              "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
              "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.yiibai.Employee" table="emp_cache">
            <cache usage="read-only" />
            <id name="id">
                <generator class="native"></generator>
            </id>
            <property name="name"></property>
            <property name="salary"></property>
        </class>
    
    </hibernate-mapping>
    
    XML

    在这里,我们使用只读(read-only)高速缓存来使用该类。缓存使用情况也可用于集合。

    文件: hibernate.cfg.xml

    XML

    要实现二级缓存,我们需要在配置文件中定义cache.provider_class属性。

    文件:ehcache.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
        monitoring="autodetect" dynamicConfig="true">
    
        <diskStore path="java.io.tmpdir/ehcache" />
    
        <defaultCache maxEntriesLocalHeap="10000" eternal="false"
            timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"
            maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU" statistics="true">
            <persistence strategy="localTempSwap" />
        </defaultCache>
    
        <cache name="org.hibernate.cache.internal.StandardQueryCache"
            maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120">
            <persistence strategy="localTempSwap" />
        </cache>
    
        <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
            maxEntriesLocalHeap="5000" eternal="true">
            <persistence strategy="localTempSwap" />
        </cache>
        <cache name="com.yiibai.Employee" maxElementsInMemory="100"
            eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="200" />
    </ehcache>
    
    XML

    我们需要创建ehcache.xml文件来定义缓存属性。

    defaultCache将用于所有持久化类。 我们还可以通过使用 cache 元素来明确定义持久化类。
    eternal 如果我们指定eternal =“true”,则不需要定义timeToIdleSecondstimeToLiveSeconds属性,因为它将由hibernate内部处理。 指定eternal =“false”给程序员控制,但是我们需要定义timeToIdleSecondstimeToLiveSeconds属性
    timeToIdleSeconds它定义了二级缓存中对象可以空闲多少秒。
    timeToLiveSeconds它定义了在第二级缓存中对象可以存储多少秒,无论它是否空闲。

    文件:MainTest.java

    package com.yiibai;
    
    import org.hibernate.*;
    import org.hibernate.boot.MetadataSources;
    import org.hibernate.boot.registry.StandardServiceRegistry;
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
    import org.hibernate.cfg.*;
    import org.hibernate.stat.Statistics;
    
    public class MainTest {
        public static void main(String[] args) {
            // 在5.1.0版本汇总,hibernate则采用如下新方式获取:
            // 1. 配置类型安全的准服务注册类,这是当前应用的单例对象,不作修改,所以声明为final
            // 在configure("cfg/hibernate.cfg.xml")方法中,如果不指定资源路径,默认在类路径下寻找名为hibernate.cfg.xml的文件
            final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                    .configure("hibernate.cfg.xml").build();
            // 2. 根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
            SessionFactory sessionFactory = new MetadataSources(registry)
                    .buildMetadata().buildSessionFactory();
    
            /**** 上面是配置准备,下面开始我们的数据库操作 ******/
            Session session = sessionFactory.openSession();// 从会话工厂获取一个session
    
            // creating transaction object
            Transaction tx = session.beginTransaction();
    
            Statistics stats = sessionFactory.getStatistics();
            System.out.println("Stats enabled="+stats.isStatisticsEnabled());
    
            stats.setStatisticsEnabled(true);
            System.out.println("Stats enabled="+stats.isStatisticsEnabled());
    
            session.save(new Employee("苏小牛", 12000));
            session.save(new Employee("库日天", 19000));
    
            Session session1 = sessionFactory.openSession();
            Employee emp1 = (Employee) session1.load(Employee.class, 1);
            System.out.println(emp1.getId() + " " + emp1.getName() + " "
                    + emp1.getSalary());
            session1.close();
    
            //再次查询ID=1的员工信息,因为使用了缓存,这里不会再发出查询语句...
            Session session11 = sessionFactory.openSession();
            Employee emp11 = (Employee) session11.load(Employee.class, 1);
            System.out.println(emp11.getId() + " " + emp11.getName() + " "
                    + emp11.getSalary());
            session11.close();
    
    
            Session session2 = sessionFactory.openSession();
            Employee emp2 = (Employee) session2.load(Employee.class, 2);
            System.out.println(emp2.getId() + " " + emp2.getName() + " "
                    + emp2.getSalary());
            session2.close();
    
            tx.commit();
            session.close();
            sessionFactory.close();
        }
    }
    
    Java

    我们可以看到,hibernate不会发出两次查询。 如果不使用二级缓存,hibernate将会发出两次查询,因为这两个查询都使用不同的会话对象。

    运行实例

    首先运行 MainTest.java 插入数据,然后再读取数据。
    执行 MainTest.java 得到以下结果,

    log4j:WARN No appenders could be found for logger (org.jboss.logging).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    Wed Mar 29 21:38:06 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
    Stats enabled=false
    Stats enabled=true
    Hibernate: insert into emp_cache (name, salary) values (?, ?)
    Hibernate: insert into emp_cache (name, salary) values (?, ?)
    Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_, employee0_.salary as salary3_0_0_ from emp_cache employee0_ where employee0_.id=?
    Wed Mar 29 21:38:08 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
    1 苏小牛 12000.0
    1 苏小牛 12000.0
    Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_, employee0_.salary as salary3_0_0_ from emp_cache employee0_ where employee0_.id=?
    2 库日天 19000.0
    
    Shell
     
  • 相关阅读:
    mtr-网络分析工具
    vpc是什么
    openstack安全组
    nginx服务器有什么作用?什么叫反向代理?为什么要使用反向代理?
    rpm 命令详解
    跟踪路由
    网卡配置bond(绑定)
    核心交换机、汇聚交换机是什么
    U盘制作Linux镜像
    11.MySQL 慢日志PT分析 可视化
  • 原文地址:https://www.cnblogs.com/borter/p/9522215.html
Copyright © 2011-2022 走看看