Hibernate缓存的evictclear和flush方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate缓存的evictclear和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先执行。

本文出自 “銅鑼衛門” 博客,请务必保留此出处http://jaeger.blog.51cto.com/11064196/1757270

以上是关于Hibernate缓存的evictclear和flush方法的主要内容,如果未能解决你的问题,请参考以下文章

hibernate里,get方法会访问二级缓存吗

hibernate开发都不用缓存吧

hibernate一级和二级缓存介绍

hibernate 一级缓存和二级缓存

HIbernate缓存

Hibernate 缓存介绍