Hibernate(四)

Hibernate的二级缓存

  • 理解缓存定义:

    • 缓存(Cache):计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。
  • 理解二级缓存的定义:
    • Hibernate中提供了两个级别的缓存

      • 一级缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存是由Hibernate管理的,一般情况下无需进行干预。
      • 二级缓存是SessionFactory级别的缓存,它是属于进程范围的缓存。
    • Hibernate的SessionFactory缓存可以分为两类:
      • 内置缓存:Hibernate自带的,不可拆卸。通常在Hibernate的初始化阶段,Hibernate会把映射元数据和预定义的SQL语句放到SessionFactory的缓存中,映射元数据是映射文件中数据(*.hbm.xml文件中的数据)的复制,该内置缓存是只读的。
      • 外置缓存(二级缓存):一个可排至的缓存插件,在默认情况下,SessionFactory不会启用这个缓存插件。外置缓存中的数据是数据库数据的复制,外置缓存的物理介质可以是内存或硬盘。
  • 使用Hibernate的二级缓存:
    • 适合放入二级缓存中的数据:

      • 很少被修改。
      • 不是很重要的数据,允许出现偶尔的并发问题。
    • 不适合放入二级缓存中的数据:
      • 经常被修改。
      • 财务数据,绝对不允许出现并发问题。
      • 与其他应用程序共享的数据。
  • Hibernate的二级缓存的架构

    

  • 二级缓存的并发访问策略:

    • 两个并发的事务同时访问吃就吃的缓存的相同数据时,也有可能出现各类并发问题。
    • 二级缓存可以设定一下4中类型的并发访问策略,每一种访问策略对应一种事务的隔离级别。
      • 非严格读写(nonstrict-read-wirte):不保证缓存与数据库中数据的一致性。提供Read Uncommited事务隔离级别。对于极少被修改,而且允许脏读的数据,可以采用这种策略。
      • 读写型read-write):提供Read Committed数据隔离级别。对于经常读但是很少被修改的数据,可以采用这种隔离烈性,因为它可以防止脏读。
      • 事务型(transaction):仅仅在受管理环境下使用。它提供了Repeatable Read 事务隔离级别。对于经常读但是很少被修改的数据,可以采用这种隔离级别,因为它可以防止脏读和不可以重复读。
      • 只读型(read-only):提供Serializable数据隔离级别。对于从来不会被修改的数据,可以采用这种访问策略。
  • 管理Hibernate的二级缓存
    • Hibernate的二级缓存是进程或集群范围内的缓存。
    • 二级缓存是可配置的插件,Hibernate允许选用以下类型的缓存插件:
      • EHCache:可作为进程分为内的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
      • OSCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
      • SwarmCache:可作为集群范围内的缓存,但是不支持Hibernate的查询缓存。
      • JBossCache:可作为集群范围内的缓存,支持Hibernate的查询缓存。
    • 4种缓存插件的并发访问策略
缓存插件 read-only nonstrict-read-write read-write transaction
EHCache  
OSCache  
SwarmCache    
JBossCache    
  • 使用Hibernate的二级缓存的步骤:

    • 加入二级缓存插件的jar包及配置文件。

      • backport-util-concurrent.jar
      • commons-logging.jar
      • ehcache-1.5.0.jar
      • ehcache.xml
    • 配置hibernate.cfg.xml
      • 配置启动Hibernate的二级缓存

        • <!-- 启用二级缓存 -->
          <property name="hibernate.cache.use_second_level_cache">true</property>
      • 配置二级缓存的提供商

        • <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
      • 配置那些类使用二级缓存
        • <!-- 配置那个类使用二级缓存 -->
          <class-cache usage="read-only" class="cn.hibernate3.demo4.Customer"/>
  • 二级缓存的示例:证明二级缓存的存在
    • 配置演示环境:实体类,对应的映射文件及核心配置文件
    • 实体类:
      • Customer.java
package cn.hibernate3.demo4;

import java.io.Serializable;
import java.util.HashSet;
/**
 * 客户实体
 */
import java.util.Set;
public class Customer implements Serializable{
    private Integer cid;
    private String cname;
    //一个客户有多个订单
    private Set<Order> orders = new HashSet<Order>();
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public Set<Order> getOrders() {
        return orders;
    }
    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

}
      • Order.java
package cn.hibernate3.demo4;

import java.io.Serializable;
/**
 * 订单实体
 */
public class Order implements Serializable{
    private Integer oid;
    private String addr;
    //订单属于某一个客户
    private Customer customer ;

    public Integer getOid() {
        return oid;
    }
    public void setOid(Integer oid) {
        this.oid = oid;
    }
    public String getAddr() {
        return addr;
    }
    public void setAddr(String addr) {
        this.addr = addr;
    }
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

}
    • 映射文件:

      • Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.hibernate3.demo4.Customer" table="customer" lazy="true">
        <!-- 配置唯一标识 -->
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <!-- 配置普通属性 -->
        <property name="cname" column="cname" type="java.lang.String"/>
        <!-- 建立映射 -->
        <!-- 配置集合 -->
        <!--
            set标签中的name表示关联对象的属性名称

         -->
        <set name="orders" cascade="save-update">
            <!-- key标签中的column用来一对多的多的一方的外键 -->
            <key column="cno"/>
            <!-- 配置一个one-to-many -->
            <one-to-many class="cn.hibernate3.demo4.Order" />
        </set>
    </class>
</hibernate-mapping>
      • Order.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.hibernate3.demo4.Order" table="orders">
        <!-- 配置唯一标识 -->
        <id name="oid" column="oid">
            <generator class="native"/>
        </id>
        <!-- 配置普通属性 -->
        <property name="addr" column="addr" type="java.lang.String"/>
        <!-- 建立映射 -->
        <!--
            many-to-one标签
                属性:
                    name:关联对象的属性名称。
                    column:表中外键的名称。
                    class:关联对象的全路径。
         -->
        <many-to-one name="customer"  column="cno" class="cn.hibernate3.demo4.Customer"></many-to-one>
    </class>
</hibernate-mapping>
    • 核心映射文件
<?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>
    <!-- 配置数据库的基本信息 -->
    <!-- 驱动的名称 -->
    <property name="hibernate.connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <!-- 访问数据库的url -->
    <property name="hibernate.connection.url">
        jdbc:mysql:///hibernate_day03
    </property>
    <!-- 用户名 -->
    <property name="hibernate.connection.username">root</property>
    <!-- 密码 -->
    <property name="hibernate.connection.password">root</property>
    <!-- 方言 -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <!-- C3P0连接池设定-->
    <!-- 使用c3po连接池  配置连接池提供的供应商-->
    <property name="connection.provider_class">
        org.hibernate.connection.C3P0ConnectionProvider
    </property>
    <!--在连接池中可用的数据库连接的最少数目 -->
    <property name="c3p0.min_size">5</property>
    <!--在连接池中所有数据库连接的最大数目  -->
    <property name="c3p0.max_size">20</property>
    <!--设定数据库连接的过期时间,以秒为单位,
        如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
    <property name="c3p0.timeout">120</property>
    <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
    <property name="c3p0.idle_test_period">3000</property>
    <!-- 可选配置 -->
    <!-- 显示SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>
    <!-- hbm:映射 2:to ddl:create drop alter -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!--
        1—Read uncommitted isolation
        2—Read committed isolation
        4—Repeatable read isolation
        8—Serializable isolation
     -->
    <property name="hibernate.connection.isolation">4</property>

    <property name="hibernate.current_session_context_class">thread</property>

    <!-- 启用二级缓存 -->
    <property name="hibernate.cache.use_second_level_cache">true</property>

    <!-- 配置使用的二级缓存提供商 -->
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

    <mapping resource="cn/hibernate3/demo4/Customer.hbm.xml" />
    <mapping resource="cn/hibernate3/demo4/Order.hbm.xml" />
    <!--  

<class-cache usage="read-write" class="cn.hibernate3.demo4.Customer"/>
<class-cache usage="read-write" class="cn.hibernate3.demo4.Order"/>

<collection-cache usage="read-write" collection="cn.hibernate3.demo4.Customer.orders"/>


-->

</session-factory>
</hibernate-configuration>
    • 测试类
  @Test
    public void demo13(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = (Customer) session.get(Customer.class, 1);
        System.out.println(customer1.getCname());
        tx.commit();

        session = HibernateUtils.openSession();
        tx = session.beginTransaction();
        Customer customer2 = (Customer) session.get(Customer.class, 1);
        System.out.println(customer2.getCname()); 

        tx.commit();
        session.close();

    }

    • 设置Customer类使用二级缓存。其核心配置文件如下:
<?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>
    <!-- 配置数据库的基本信息 -->
    <!-- 驱动的名称 -->
    <property name="hibernate.connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <!-- 访问数据库的url -->
    <property name="hibernate.connection.url">
        jdbc:mysql:///hibernate_day03
    </property>
    <!-- 用户名 -->
    <property name="hibernate.connection.username">root</property>
    <!-- 密码 -->
    <property name="hibernate.connection.password">root</property>
    <!-- 方言 -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <!-- C3P0连接池设定-->
    <!-- 使用c3po连接池  配置连接池提供的供应商-->
    <property name="connection.provider_class">
        org.hibernate.connection.C3P0ConnectionProvider
    </property>
    <!--在连接池中可用的数据库连接的最少数目 -->
    <property name="c3p0.min_size">5</property>
    <!--在连接池中所有数据库连接的最大数目  -->
    <property name="c3p0.max_size">20</property>
    <!--设定数据库连接的过期时间,以秒为单位,
        如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
    <property name="c3p0.timeout">120</property>
    <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
    <property name="c3p0.idle_test_period">3000</property>
    <!-- 可选配置 -->
    <!-- 显示SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>
    <!-- hbm:映射 2:to ddl:create drop alter -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!--
        1—Read uncommitted isolation
        2—Read committed isolation
        4—Repeatable read isolation
        8—Serializable isolation
     -->
    <property name="hibernate.connection.isolation">4</property>

    <property name="hibernate.current_session_context_class">thread</property>

    <!-- 启用二级缓存 -->
    <property name="hibernate.cache.use_second_level_cache">true</property>

    <!-- 配置使用的二级缓存提供商 -->
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

    <mapping resource="cn/hibernate3/demo4/Customer.hbm.xml" />
    <mapping resource="cn/hibernate3/demo4/Order.hbm.xml" />

  <!-- 配置那个类使用二级缓存-->
  <class-cache usage="read-write" class="cn.hibernate3.demo4.Customer"/>
  <class-cache usage="read-write" class="cn.hibernate3.demo4.Order"/>
  <!-- 集合缓存区 -->
  <collection-cache usage="read-write" collection="cn.hibernate3.demo4.Customer.orders"/>

</session-factory>
</hibernate-configuration>

  • 类缓存区的特点:缓存的是对象的散装的数据。
@Test
    public void demo13(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = (Customer) session.get(Customer.class, 1);
        Customer customer2 = (Customer) session.get(Customer.class, 1);
        System.out.println(customer1==customer2);
        tx.commit();

        session = HibernateUtils.openSession();
        tx = session.beginTransaction();
        Customer customer3 = (Customer) session.get(Customer.class, 1);
        Customer customer4 = (Customer) session.get(Customer.class, 1);
        System.out.println(customer3 == customer4);

        System.out.println(customer1 == customer3);

        tx.commit();
        session.close();

    }

  • 集合缓存区的特点:缓存的是对象的id,需要依赖类缓存区的配置。      
@Test
    public void demo13(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = (Customer) session.get(Customer.class, 1);
        System.out.println(customer1.getOrders().size());
        tx.commit();

        session = HibernateUtils.openSession();
        tx = session.beginTransaction();
        Customer custome2 = (Customer) session.get(Customer.class, 1);
        System.out.println(custome2.getOrders().size());

        tx.commit();
        session.close();

    }

                

          

                 

时间: 2024-10-10 08:38:26

Hibernate(四)的相关文章

Hibernate(四)之对象状态及一级缓存

一.Hibernate中的对象状态 1.1.瞬时态(临时态) 没有与Hibernate产生关联 与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应) 获得:一般都只直接创建(new) 瞬时态 转换 持久态 一般操作:save方法.saveOrUpdate 瞬时态 转换 脱管态 一般操作:通过setId方法设置数据 1.2.持久态 Hibernate有关联 对象有id 获得: 查询操作:get.loat.createQuery.createCriteria 等 获得都是持久态[] 执

Hibernate(四)结构-基础语义和事务

一.基础语义 核心: Configuration SessionFactory Session 二.Configuration Configuration类负责管理Hibernate的配置信息,Hiber运行时需要获取一些底层实现基本信息 1.数据库URL 2.数据库用户 3.数据库用户密码 4.数据库JDBC驱动 5.数据库dialect,用于对特定的数据库提供支持,其中包含了针对特定数据库特性的实现 当调用Hibernate时,Hibernate会自动在当前CLASSPATH,中搜寻配置文件

hibernate(四) 双向多对多映射关系

序言 莫名长了几颗痘,真TM疼,可能是现在运动太少了,天天对着电脑,决定了,今天下午花两小时去跑步了, 现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感觉还是比较容易的,需要理清楚其数据库关系图,那么你就拿下了它.映射文件的配置还是那么些死东西. --WH 一.小疑问的解答 问题一:到这里,有很多学习者会感到困惑,因为他不知道使用hibernate是不是需要自己去创建表,还是hibernate全自动,如果需要自己创建表,那么主外键这种设置也是自己设

Hibernate(四)

1. 抓取策略 抓取策略:怎样发出sql语句 懒加载:什么时候发出sql语句 配置:<set fetch="join/select/subselect"> Class.hbm.xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0

Hibernate(四)——缓存策略+lazy

Hibernate作为和数据库数据打交道的框架,自然会设计到操作数据的效率问题,而对于一些频繁操作的数据,缓存策略就是提高其性能一种重要手段,而Hibernate框架是支持缓存的,而且支持一级和二级两种缓存,合理的使用缓存策略可以大大提高我们的操作数据效率,但是利用不能,可能会造成不必要的麻烦.  一,一级缓存(Session缓存):  Session缓存表示将查询结果放置到Session的临时存储空间(一级缓存中).Hibernate框架默认支持一级缓存的.一级缓存的范围较小,一旦Sessio

hibernate(四)__由表逆向创建Domain对象和对象关系映射文件

之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: 1.创建一个web工程项目 2.通过myeclipse 提供的数据库浏览器连接到我们的数据库. ①新建一个数据库连接: ②配置数据库连接(这里借用以oracle一张图,后面都是在sql server的数据库下的配置,可以忽视不影响): ③成功之后输入登录密码进入数据库: 右键表可直接修改删除表,当然这也是相当

Hibernate四 关联关系之双向关联

双向关联 一 双向1--N关联 1.无连接表的双向1--N关联 N的一端需要使用@ManyToOne注解来修饰代表关联实体的属性,1的一端需要使用@OneToMany注解来修饰代表关联实体的属性. 双向关联应该由N的一端来控制关联关系,因此在使用@OneToMany注解时指定mappedBy属性.一旦为@OneToMany,@ManyToMany指定了该属性,则表明当前实体不能控制关联关系,一旦当前实体放弃控制关联关系后,hibernate就不允许使用@JoinColumn或@JoinTable

Hibernate(四) - HQL_QBC查询详解--抓取策略优化机制

Hibernate 的查询方式 在 Hibernate 中提供了很多种的查询的方式.Hibernate 共提供了五种查询方式. 1.Hibernate 的查询方式:OID 查询 OID检索:Hibernate根据对象的OID(主键)进行检索. ① 使用 get 方法 Customer customer = session.get(Customer.class,1l); ② 使用 load 方法 Customer customer = session.load(Customer.class,1l)

Hibernate四

1 Hibernate的查询方式 1.1 Hibernate的查询方式 在Hibernate中有提供了很多种的查询方式. Hibernate一共提供了5种查询方式: OID查询. 对象导航查询. HQL查询. QBC查询. SQL查询. 1.2 OID查询 OID检索:HIbernate根据对象的OID(主键)查询.例如:使用get或load方法查询对象. 1.3 对象导航查询 Hibernate根据一个已经查询到的对象,获取其关联对象的一种查询方式.例如:先查询到了联系人的信息,然后通过联系人

Hibernate 原汁原味的四种抓取策略(转)

原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html     尊重原作者,访问原创地址 最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog 中都没有找到详细 介绍 Hibernate 文档中所说的原汁原味的抓取策略, 综合懒加载等等特性混在了一起, 所 以在这自己在借鉴了他人的基