Hibernate缓存的evict、clear和flush方法

evict()、clear()和flush()方法是Hibernate缓存的3种基本操作方法,本文主要介绍这3种方法的使用方式和具体区别。

Company表:

Company实体类:

import java.util.Set;

public class Company {
    private int companyId;
    private String companyName;
    private Set<Employee> companyEmployees;
    public int getCompanyId() {
        return companyId;
    }
    public void setCompanyId(int companyId) {
        this.companyId = companyId;
    }
    public String getCompanyName() {
        return companyName;
    }
    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }
    public Set<Employee> getCompanyEmployees() {
        return companyEmployees;
    }
    public void setCompanyEmployees(Set<Employee> companyEmployees) {
        this.companyEmployees = companyEmployees;
    }
}

Company hbm配置:

<hibernate-mapping>
    <class name="com.jaeger.hibernatetest.day7.lazy.Company" table="company">
        <id name="companyId" column="company_id">
            <generator class="native"></generator>
        </id>

        <property name="companyName" column="company_name"/>
        <set name="companyEmployees">
            <key column="employee_company_id"></key>
            <one-to-many class="com.jaeger.hibernatetest.day7.lazy.Employee"/>
        </set>
    </class>
</hibernate-mapping>


1. evict()和clear()方法
evict()和clear()方法都是从session中清除缓存,evict()是清除单个对象的缓存,而clear()是清除所有缓存。测试方法如下:

Company company = (Company)session.get(Company.class, 1); //A
System.out.println(company.getCompanyName()); //B
company = (Company)session.get(Company.class, 1);  //C
System.out.println(company.getCompanyName()); //D

A:此处发出SQL去数据库查询。
B:此处打印出:KONAMI。
C:此处取缓存,不会发SQL。
D:此处打印出:KONAMI。
下面我们在第二次get之前先清除缓存:

Company company = (Company)session.get(Company.class, 1); //A
System.out.println(company.getCompanyName());
session.evict(company); //B
company = (Company)session.get(Company.class, 1);  //C
System.out.println(company.getCompanyName());

A、C:这两处都会发相同的SQL去数据库查询。因为B处清除了缓存,调用clear()方法效果也是一样。



2. flush()方法

flush()方法会根据缓存中对象的操作生成相应的SQL语句去操作数据库。没有调用flush()的测试方法如下:

Company company = (Company)session.get(Company.class, 1);
company.setCompanyName("Santa Monica");
session.update(company); //A

Company newCompany = new Company();
newCompany.setCompanyName("UBISOFT");
session.save(newCompany); //B
transaction.commit(); //C
session.close();

A:此处不会发出SQL去更新数据库。

B:此处会发出insert语句去更新数据库,但数据是未提交的状态,如果数据库的隔离级别是Read Committed的话就可以看到。

insert  
  into
     company
         (company_name) 
values
         (?)

C:此处会发出update语句去更新company信息。

update
     company 
   set
     company_name=? 
 where
     company_id=?

这里之所以会发出SQL语句,因为transaction.commit()会调用flush()方法。

下面我们自己来调用flush()方法:

Company company = (Company)session.get(Company.class, 1);
company.setCompanyName("Santa Monica");
session.update(company);
session.flush(); //A
        
Company newCompany = new Company();
newCompany.setCompanyName("UBISOFT");
session.save(newCompany);
transaction.commit(); //B
session.close();

A:此处立刻会发出update语句去更新company信息。数据是未提交的状态。

B:此处会发出insert语句去更新数据库。数据是未提交的状态。

注意:Hibernate使用的主键生成策略为uuid时情况会有所不同,我们把Company实体类的companyId属性的类型改为String,再把Company hbm配置修改为<generator class="uuid">。下面还是使用上面的测试方法:

Company company = (Company)session.get(Company.class, 1);
company.setCompanyName("Santa Monica");
session.update(company); //A

Company newCompany = new Company();
newCompany.setCompanyName("UBISOFT");
session.save(newCompany); //B
transaction.commit(); //C
session.close();

A、B:这时update()和save()都不会向数据库发SQL语句,第一次测试中save()方法会发SQL语句是因为我们使用的是native主键生成策略,要拿到主键就必须先向数据库插入数据。而uuid是Hibernate自己生成的,所以只会加入缓存,而不会发出SQL语句。

C:这个地方很关键,我们先看看Hibernate生成的SQL语句:

insert 
  into
     company
         (company_name, company_id) 
values
         (?, ?)
         
update
     company 
   set
     company_name=? 
 where
     company_id=?

从上面可以看出:Hibernate在用缓存中的对象去操作数据库时,并不是按照我们程序的顺序去执行,而是先执行insert,然后才执行update和delete。这就有可能让执行结果跟我们所期待的不一样。这个时候就应该使用flush()方法手动的让Hibernate及时去发送SQL语句。上面的例子中,我们如果在A步骤后面加入session.flush()方法,则update就会比insert先执行。

时间: 2024-11-03 14:07:25

Hibernate缓存的evict、clear和flush方法的相关文章

Hibernate强制清除Session缓存 Clear与Flush方法 FlushMode设置

一.Session中FlushMode的设置: 在事务开启前设置FlushMode属性,方法session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL). FlushMode有5个值可选:Always:任何代码都会Flush.AUTO:默认方式–自动.Commit:COMMIT时.Never:始终不.MANUAL:手动方式. 二.Session中flush()方法说明: 可以强制进行从内存到数据库的同步,方法session.flu

hibernate学习6_session之clear与flush

1.session的clear()方法  hibernate从数据库中get或load记录时,或先去session一级缓存中查找对应数据,如果缓存中没有记录,则去对应数据库中查询, 如果有记录则直接从缓存中获取. public void testClear() { Session session1 = sf.getCurrentSession(); session1.beginTransaction(); Student t1 = (Student) session1.get(Student.c

Hibernate缓存应用的积累与总结

Hibernate缓存一直比较难掌握,下面就分析和总结原因,相信你就会慢慢清楚了原来Hibernate缓存也是可以轻松掌握的,但前提要求大家必须跟着动手去验证一下,再用心体会,光看是没有用的 一.hibernate一级缓存(Session 级别的缓存) hibernate是一个线程对应一个session,一个线程可以看成一个用户.也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了.hibernate一级缓存生命周期很短,和session生命周期一样

面试中对Hibernate缓存机制的回答

这是面试中经常问到的一个问题,可以按照下面的思路回答,准你回答得很完美.首先说下Hibernate缓存的作用(即为什么要用缓存机制),然后再具体说说Hibernate中缓存的分类情况,最后可以举个具体的例子.Hibernate缓存的作用: Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据Hibernat

Hibernate缓存何时使用和如何使用?

Hibernate缓存分为二级,第一级存放于session中称为一级缓存,默认带有且不能卸载.第二级是由sessionFactory控制的进程级缓存.是全局共享的缓存,凡是会调用二级缓存的查询方法 都会从中受益. 1. 关于hibernate缓存的问题: 1.1. 基本的缓存原理 Hibernate缓存分为二级, 第一级存放于session中称为一级缓存,默认带有且不能卸载. 第二级是由sessionFactory控制的进程级缓存.是全局共享的缓存,凡是会调用二级缓存的查询方法 都会从中受益.只

Hibernate 缓存机制

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

Hibernate缓存

一.Hibernate缓存概述 Hibernate中提供两个级别的缓存,一级缓存和二级缓存. 1.一级缓存是Session级别的缓存,它属于事物范围的缓存,一级缓存有hibernate进行管理. 2.二级缓存是sessionFactory级别的缓存,它属于进程范围的缓存,二级缓存又可分为"内置缓存"和"外置缓存",内置缓存:是hibernate在创建sessionFactory时会加载.hbn.xml文件并会在内存中初始化一些默认的sql语句,该内置缓存是只读的:外

Hibernate缓存、组件、继承映射

Hibernate缓存.组件.继承映射 三种状态: 临时状态:不受session管理,没有提交到数据库:没有执行sql之前,new对象的时候: 持久化状态:受session管理,提交到数据库:正在执行sql 游离状态:不受session管理,提交到数据库:session关闭后 Cache缓存:会先看看缓存里有没有,有就取出来,没有就到数据库取数据. Session的三个方法:flush.evict.clear 不同session不会共享数据. List与iterator的区别: List是直接到

Hibernate 缓存机制详细解析

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的