hibernate学习之旅之二级缓存

最近学习的缓存,感觉有了进一步的认识,也感觉到自己只是浅浅的利用缓存,如果真正能够的能够优化hibernate的性能,还需要更加深入(对于项目而言)

好了废话不说了。

讲到Hibernate的二级缓存,当时我在想为什么要有二级缓存?二级缓存的用途是什么呢?有人肯定说缓存就是在磁盘存放临时数据嘛。其实大概的意思的确是。

但是我们仔细想想,当开启一个session去读取一个一条数据的时候(load),如果再发一条load,则必然不会发送两条SQL语句,因为session的一级缓存

内存读取了相应的缓存记录。如果session一级缓存检索几条记录还行,那上百条,上万条,甚至是几十万条,这个内存可想而知。还有就是每个session之间

的数据是不能共享的。于是我们引入二级缓存,解决了上面的两种问题。这个对于数据的检索得到了大大的优化。接下来看一个例子。


使用二级缓存的方法是:在hibernate.cfg.xml中添加一个启动缓存的配置,<property name="cache.use_second_level_cache">true</property>,添加一个二级缓存的

提供者    <property name="hibernate.cache.region.factory_class"> net.sf.ehcache.hibernate.EhCacheRegionFactory</property>(我用的是hiberanet3.0的)
          

我们现在看的是一个双向一对多的关系,所以缓存配置就更简单了


@Entity
@Table(name="t_department")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Department implements java.io.Serializable{
    /**
     *
     */
    private static final long serialVersionUID = 1853313501485307077L;
    
    private Integer id;
    private String deptName;
    private Set<Employee> employees = new HashSet<Employee>();

    public Department(){
        
    }
    
    public Department(Integer id,String deptName){
        this.id = id;
        this.deptName = deptName;
    }
    
    public Department(Integer id,String deptName,Set<Employee> employeess){
        this.id = id;
        this.deptName = deptName;
        this.employees = employeess;
    }
    
    @Id
    @GeneratedValue(generator="generator")
    @GenericGenerator(name="generator",strategy="native")
    @Column(name="id")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name="dept_name")
    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @OneToMany(mappedBy="department",cascade=CascadeType.ALL)
    @BatchSize(size=5)
    @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
    public Set<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Set<Employee> employees) {
        this.employees = employees;
    }

}


@Entity
@Table(name="t_employee")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Employee implements java.io.Serializable{
    /**
     *
     */
    private static final long serialVersionUID = 8568295685039740847L;
    
    private Integer id;
    private String empName;
    private Department department;

    public Employee(){
        
    }
    @Id
    @GeneratedValue(generator="generator")
    @GenericGenerator(name="generator",strategy="native")
    @Column(name="id")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name="emp_name")
    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    @ManyToOne()
    @JoinColumn(name="dep_id")
    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

}


单元测试:

@Test

public void testQuery() {
        Department department = (Department) session.get(Department.class, 1);
        System.out.println(department.getDeptName());
        session.close();

        session = sessionFactory.openSession();
        Department department2 = (Department) session.get(Department.class, 1);
        System.out.println(department2.getDeptName());
        session.close();

        session = sessionFactory.openSession();
        Department department3 = (Department) session.get(Department.class, 1);
        System.out.println(department3.getDeptName());
        session.close();

        session = sessionFactory.openSession();
        Department department4 = (Department) session.get(Department.class, 1);
        System.out.println(department4.getDeptName());
        session.close();
        System.out.println("sesseionFactory即将关闭");
        sessionFactory.close();
    }

在打印语句处设置断点,hiberante的二级缓存的生命周期sessionFactory级别的,所以我们sessionFacory.close()执行后,缓存也会被清除,为此,

我们要加断点。


测试结果显示,只是发送了1条语句,这就是缓存的效果,他们会帮我们第一次查询数据缓,如果下一次,执行相同的查询则不发一条语句。


当进行查询的是一个list的话,只会填充缓存,为此我们需要在添加一个配置查询缓存<property name="cache.use_query_cache">true</property> 这样可以解决



还有就是要注意的是,如果是接下来的这种情况,我们就需要注意的是,在一个事务范围内,如果将一个数据作update的操作(被缓存的一条数据)

则,下一次执行相同查询的时候会发现没有该条记录缓存会帮我们删除该条记录,我也觉得很奇怪,为什么要这样,hibernate的内部就是这样操作,

至于为什么我们以后再说。先看代码。



public void testQuery2() {
        Query query = session.createQuery("from Employee");
        query.setCacheable(true);
        List<Employee> departments = query.list();
        System.out.println(departments.size());

        Employee employee = (Employee) session.get(Employee.class, 1);
        employee.setEmpName("哈喽");
        Criteria criteria = session.createCriteria(Employee.class);
        criteria.setCacheable(true);
        departments = criteria.list();
        System.out.println(departments.size());
    }



代码结果显示:第一次显示的department.size()的结果为:4,在这个事务中进行修改某个数据,第二次显示的department.size()变为:3。


总结:hiberante 的list ,iterator,load,get都会填充缓存但是list不会使用缓存,使用缓存的话需要添加查询缓存

并且每次查询的时候要添加如:query.setCacheable(true)获取criter.setCacheable(true)


有不对的地方还请读者们不吝赐教,共同进步。吐舌头







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值