首页 > 技术文章 > Hibernate笔记④--一级二级缓存、N+1问题、saveorupdate、实例代码

chengzhipcx 2015-07-28 17:33 原文

一级缓存及二级缓存

一级缓存也是Session 缓存

    一个链接用户的多次查询使用缓存

    跨用户 则无缓存

    hibernate自带的

get和load都会填充并利用一级缓存

二级缓存(需要我们自己配置)

    SessionFactory 缓存

    可以跨用户的

 

list 方法会使用一级缓存 ,但是不会填充一级缓存

iterator会填充过一级缓存 耗时的

 

N+1问题

当我们使用iterate 进行迭代 又要使用内部的数据,则会发送1+nsql

第一条先load 拿到id 对象改变对象则会改变

再取get每一个的id

 

 

Saveor update

/*

     * 如果一个对先查找出来的,则会调用update语句

     * 如果没有查 则调用insert语句

     */

    public static void testSaveorUpdate(Emp e){

        Session session=HibernateSessionFactory.getSession();

        Transaction tx=session.beginTransaction();

        session.saveOrUpdate(e);

        tx.commit();

        HibernateSessionFactory.closeSession();

    }

 

 

例子代码

package com.pcx.dao;

 

import java.util.Iterator;

import java.util.List;

 

import org.hibernate.Session;

 

import com.pcx.model1.Dept;

import com.pcx.model1.Emp;

import com.pcx.util.HibernateSessionFactory;

 

public class CacheTest {

    public static void main(String[] args) {

        Emp e=fetchTest2();

        System.out.println(e.getDept());

    }

    //

    public static void cacheTest(){

        Session session=HibernateSessionFactory.getSession();

        Emp emp=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp.getName());

        

        Emp emp1=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp1.getName());

        HibernateSessionFactory.closeSession();

        

    }

    //getload都是會填充一级缓存的

    public static void cacheTest2(){

        Session session=HibernateSessionFactory.getSession();

        Emp emp=(Emp) session.load(Emp.class, 1);

        

        System.out.println(emp.getName());

        

        Emp emp1=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp1.getName());

        HibernateSessionFactory.closeSession();

        

    }

    

    public static void cacheTest3(){

        Session session=HibernateSessionFactory.getSession();

        String hql="from Emp e where e.id=1";

          

          

        

        List<Emp> emps=session.createQuery(hql).list();

        for (Emp emp : emps) {

            System.out.println(emp.getName());

        }

        

        //这儿没有用上一级缓存

        List<Emp> emps2=session.createQuery(hql).list();

        for (Emp emp : emps2) {

            System.out.println(emp.getName());

        }

        HibernateSessionFactory.closeSession();

        

    }

    public static void testload(){

        Session session=HibernateSessionFactory.getSession();

        Emp e=(Emp) session.load(Emp.class, 2);

        

        System.out.println(e.getId());

        System.out.println(e.getName());

        e.setName("lllll");

        HibernateSessionFactory.closeSession();

    }

    //n+1问题

    //当我们使用iterate 进行迭代 又要使用内部的数据,则会发送1+nsql

    //第一条先load拿到id 对象改变9对象则会改变

    

//    再取get每一个的id

    /**

     *

     */

    public static void cacheTest4(){

        Session session=HibernateSessionFactory.getSession();

        String hql="from Emp";

        

        Iterator<Emp> iter=session.createQuery(hql).iterate();

        while (iter.hasNext()) {

            Emp e=iter.next();

            System.out.println(e.getName());

            

        }

        HibernateSessionFactory.closeSession();

        

    }

    /**

     * 配置二级缓存最好的方式是在每个类的配置 添加 <cache usage="read-only"/>标记

     */

    public static void cacheTest5(){

        Session session=HibernateSessionFactory.getSession();

        Emp emp=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp.getName());

        session.evict(emp);//清理一级缓存 //如果二级缓存关闭的话会查询两次

        Emp emp1=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp1.getName());

        HibernateSessionFactory.closeSession();

    }

    public static void cacheTest6(){

        Session session=HibernateSessionFactory.getSession();

        Emp emp=(Emp) session.get(Emp.class, 1);

        

        System.out.println(emp.getName());

        session.evict(emp);//清理一级缓存 //如果二级缓存关闭的话会查询两次

        Session session2=HibernateSessionFactory.getSession();

        Emp emp1=(Emp) session2.get(Emp.class, 1);

        

        System.out.println(emp1.getName());

        HibernateSessionFactory.closeSession();

    }

    /*

     * 抓取策略

     * Fetch join的话 就没有lazy 就直接把dept对象都加载了

     */

    public static Emp fetchTest2(){

        Session session=HibernateSessionFactory.getSession();

        Emp emp=(Emp) session.load(Emp.class, 1);

        Dept d=emp.getDept();

        

        

//        System.out.println(emp.getName());

//        System.out.println(d.getName());

        HibernateSessionFactory.closeSession();

        return emp;

    }

}

 

 

Fecat="join"

fatch 默认只就是select

    join 也将关联的对象一并加载进

来了,并不管是否懒加载

 

错误:No row with the given identifier exists: [com.pcx.model1.Emp#1000]

    at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:386)

说明表中没有本条数据

推荐阅读