Hibernate 第 六 天 1 hql(二) 2 hibernate中的一级缓存 3 hibernate中的二级缓存

                                      Hibernate              第 6 天

知识框架

1  hql(二)

1) list和iterate方法的区别(面试的重点)

    当查询对象

    当查询属性的时候

2) count(*)返回的结果必须使用long来保存

2  hibernate中的一级缓存

1) 缓存的基本概念:

2)  一级缓存的内部结构:

3) 一级缓存的生命周期,跟session保存一致

4) get , load ,iterate 支持一级缓存的读写

    list , save 可以写入一级缓存,但不能读

5) 一级缓存的管理

6) 一级缓存注意

3  hibernate中的二级缓存

1)  二级缓存的定义

2) 二级缓存的生命周期

3) 二级缓存内部结构Hashtable

4) 使用二级缓存的步骤

5) ehcache.xml

6) 在hibernate.cfg.xml指定把那个对象放入二级缓中

7) load  , get, iterate支持二级缓存的读写

    list只能写入二级缓存,不能读取二级缓存

8) 管理二级缓存

1  hql(二)

1) list和iterate方法的区别(面试的重点)

查询所有的person对象

当查询对象

 List (): 只发出了一条sql语句,直接查询所有的对象

 iterate(): 首先查询对象的Id(“1”)的sql,然后根据id发出n条sql查询对象(“n”),n+1问题

当查询属性的时候

  list()和 iterate():都只发出了一条查询属性的sql语句

2) count(*)返回的结果必须使用long来保存

案例:hibernate_day06_hql12

package com.tarena.test;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.SQLQuery;

import org.hibernate.Session;

import org.junit.Test;

import com.tarena.po.Person;

import com.tarena.util.HibernateUtils;

public class HqlTest {

@Test

public void testSave(){

Session session = null;

try {

session = HibernateUtils.getSession();

for(int i=1; i<=6 ;i++){

session.beginTransaction();

Person person = new Person();

person.setAge(i+10);

person.setPname("IamNO"+i);

person.setBirthday(new Date());

person.setSalary(i*10000);

session.saveOrUpdate(person);

session.getTransaction().commit();

}

} catch (Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

} finally{

HibernateUtils.closeSession();

}

}

//查询所有的person对象

//当查询对象

// List (): 只发出了一条sql语句,直接查询所有的对象

//iterate(): 首先查询对象的Id(“1”)的sql,然后根据id

//发出n条sql查询对象(“n”),n+1问题

@Test

public void testQueryIteratorObject(){

Session session = HibernateUtils.getSession();

try {

// Iterator<Person> iterator 

// =session.createQuery("from Person").iterate();

// 发出N+1条sql语句

//1 :iterate()首先去数据库中,查询对象的Id

//Hibernate: select person0_.id as col_0_0_ from

//t_person person0_

//N:iterate() 然后根据“1”中查询的id,去数据库发出

//N条sql语句,根据id查询所要的对象

//N:查询id的个数

// Hibernate: select person0_.id as id0_0_,

// person0_.t_pname as t2_0_0_, person0_.age as age0_0_, person0_.salary as salary0_0_, person0_.birthday as birthday0_0_ from t_person person0_ 

// where person0_.id=?

// IamNO1 ,11

List<Person> list = 

session.createQuery("from Person")

.list();

Iterator<Person> iterator = list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname()+" ,"+person.getAge());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//查询所有的person的age属性

//对比list与iterate在查询属性的时候,sql有什么不同

//iterate(): 只发出了一条sql语句,直接查询属性

//list():只发出了一条sql语句,直接查询属性

//查询属性的时候,list与iterate发出一样的sql

@Test

public void testQueryIterateList2(){

Session session = null;

try {

session = HibernateUtils.getSession();

//只发出一条查询属性的SQL语句

// Iterator<Integer> iterator = 

// session.createQuery("select age from Person")

// .iterate();

//只发出一条查询属性的SQL语句

List<Integer> list = 

session.createQuery("select age from Person")

.list();

Iterator<Integer> iterator = list.iterator();

while(iterator.hasNext()){

int age = iterator.next();

System.out.println(age);

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//2 统计查询

//查询t_person表中有多少条数据

@Test

public void testCount(){

Session session = null;

try {

session = HibernateUtils.getSession();

long count =(Long) session.createQuery(

"select count(*) from Person")

.list().get(0);

System.out.println(count);

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

}

2  hibernate中的一级缓存

  1) 缓存的基本概念:

 缓存:是数据库中数据临时的保存到内存中一块区(数据库中的数据在内存中的临时拷贝),位于数据库和访问层之间。

   作用:提高性能,减少对数据库的访问

缓存的使用方式:ORM在进行数据的读取的时候,会根据hibernate中的缓存策略,首先去缓存查询所要查询的数据

如果发现,直接使用,如果没有,发出sql语句,去数据库中查询,避免对数据库无谓的访问

针对对象:hibernate把缓存分成两个层次,一级缓存和二级缓存

一级缓存:为当前这个用户来缓存数据(私有)

二级缓存:跟SessionFactory有关,公有的

2)一级缓存的内部结构: 一级缓存的内部结构,就是一个Map<Key,Value>Map中的key,指的当前的Id,Value

指对应的实体对象,因为是map结构,一级缓存只能保存实体对象,不能保存属性

3)一级缓存的生命周期,跟session保存一致,一级缓存也叫session级缓存,当session关闭的时候,一级缓存清空

4) get , load ,iterate 支持一级缓存的读写

    list , save 可以写入一级缓存,但不能读

       

5) 一级缓存的管理(是否清空一级缓存):

批量插入,必须要时刻管理一级缓存 ,在企业开发中一旦出现批处理的问题,都不会使用hibernate,而是直接使用jdbc

hibernate当中使用jdbc:session.connection()

清理缓存:

session.flush();

session.clear();

6) 一级缓存注意:

a)一定要注意关闭session,不然很容易出现内存泄露

b) 一级缓存不能关闭,是hibernate默认就使用的,要时刻注意一级缓存的管理      

案例:hibernate_day06_Cache1  

package com.tarena.test;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.SQLQuery;

import org.hibernate.Session;

import org.junit.Test;

import com.tarena.po.Person;

import com.tarena.util.HibernateUtils;

public class CacheTest {

@Test

public void testSave(){

Session session = null;

try {

session = HibernateUtils.getSession();

session.beginTransaction();

Person person = new Person();

person.setAge(23);

person.setBirthday(new Date());

person.setPname("li");

person.setSalary(12000);

session.saveOrUpdate(person);

session.getTransaction().commit();

} catch (Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

} finally{

HibernateUtils.closeSession();

}

}

//一级缓存:是默认打开的

//在同一个session中,使用load方法连续查询同一个对象

//load方法可以读写一级缓存

//读: 能从一级缓存中读取数据

//写:能把数据写入到一级缓存中

@Test

public void testCacheLoad1(){

Session session = null;

try {

session = HibernateUtils.getSession();

Person person = (Person) session.load(Person.class, 1);

System.out.println(person.getAge()+","+person.getPname());

System.out.println("------------------------------");

//没有发出sql,因为上次调用load 方法的时候,就该

//写入一级缓存中,当第2次再查询同一个对象的时候

//hibernate首先会去一级缓存中,查询该对象,有,

//则直接使用

Person person2 = (Person) session.load(Person.class, 1);

System.out.println(person2.getAge()+","+person2.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在一个session内部两次调用get查询同一个对象

// get依然支持一级缓存,可以读写一级缓存

@Test

public  void testCacheGet1(){

Session session = null;

try {

session = HibernateUtils.getSession();

Person person = (Person) session.get(Person.class, 1);

System.out.println(person.getPname());

System.out.println("---------------------------------");

Person person2 = (Person) session.get(Person.class, 1);

System.out.println(person2.getPname());

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在两个session中调用分别调用load查询同一个对象

//Session 关闭,则一级缓存清空,一级缓存的生命

//周期跟session一致,一级缓存也叫session级缓存

@Test

public void testCacheLoad2(){

Session session = null;

try {

session = HibernateUtils.getSession();

Person person = (Person) session.load(Person.class, 1);

System.out.println(person.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("---------------------------------");

try {

session = HibernateUtils.getSession();

Person person = (Person) session.load(Person.class, 1);

//发出sql语句,上次查询的时候,是person对象放入

//一级缓存当中,但随着session的关闭,一级缓存

//清空,而内部保存的person对象也随之消失

//当再次查询同一个Person对象的时候,缓存没有

//与之对应对象,只能发出sql语句,去数据库中

//查询

System.out.println(person.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在一个session中调用两次Iterate方法查询同一个

//对象

//iterate()读写一级缓存

@Test

public void testQueryIterate1(){

Session session = null;

try {

session = HibernateUtils.getSession();

Iterator<Person> iterator =

session.createQuery("from Person").iterate();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

System.out.println("---------------------------------");

//只发出一条查询id的sql,iterate读写一级缓存,

//上次使用iterate查询出来的对象保存到一级缓存中

//但是一级缓存保存的是对象,id没有保存

//当第2次再使用iterate查询对象的时候,hibernate

//首先会先发出查询id的sql语句,然后根据id,去

//一级缓存中查询,看是否有与之匹配的对象,有

//直接使用

Iterator<Person> iterator2 =

session.createQuery("from Person").iterate();

while(iterator2.hasNext()){

Person person = iterator2.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在一个session中两次调用iterate来查询同一个person

//对象同的age属性

//一级缓存只能保存对象,不能保存属性

@Test

public void testCacheIterate(){

Session session = null;

try {

session = HibernateUtils.getSession();

Iterator<Integer> iterator =

session.createQuery("select age from Person")

.iterate();

while(iterator.hasNext()){

int age = iterator.next();

System.out.println(age);

}

System.out.println("-------------------");

Iterator<Integer> iterator2 =

session.createQuery("select age from Person")

.iterate();

while(iterator2.hasNext()){

int age = iterator2.next();

System.out.println(age);

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在一个session中调用两次list方法来查询同样的对象

@Test

public void testList1(){

Session  session = null;

try {

session = HibernateUtils.getSession();

List<Person> list =

session.createQuery("from Person").list();

Iterator<Person> iterator = list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

System.out.println("---------------------------");

//发出sql,不能确定list是否读写一级缓存

List<Person> list2 =

session.createQuery("from Person").list();

Iterator<Person> iterator2 = list2.iterator();

while(iterator2.hasNext()){

Person person = iterator2.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

// list 可以写入一级缓存,不能读取一级缓存

// 能写不能读

//在一个session中,首先使用list先查询对象,然后再

//使用iterate查询同样的对象,确定list对一级缓存

//支持情况

@Test

public  void testListIterate(){

Session session = null;

try {

session = HibernateUtils.getSession();

List<Person> list = 

session.createQuery("from Person").list();

Iterator<Person> iterator =  list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

//只发出了一条查询id的sql语句,上次使用list查询

//对象的时候,list可以写入一级缓存,则把查询

//出来的对象放入了一级缓存当中,而iterate方法

//可以读写一级缓存,但先发出查询id的sql语句,

//然后根据id来查询缓存中的对象

System.out.println("-----------------------------");

Iterator<Person> iterator2 = 

session.createQuery("from Person").iterate();

while(iterator2.hasNext()){

Person person = iterator2.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//save可以写入一级缓存

// 在同一个session中,先使用save保存一个对象,

//调用get来查询该对象

@Test

public void testSaveGet(){

Session session = null;

try {

session = HibernateUtils.getSession();

session.beginTransaction();

Person person = new Person();

person.setAge(18);

person.setPname("wang");

session.save(person);

session.getTransaction().commit();

//没有发出sql语句,save把person在保存到数据库

//的同时,也把person对象放入一级缓存当中

System.out.println("-------------------------------");

Person person2 = (Person) session.get(Person.class, 3);

System.out.println(person2.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//一级缓存的管理:

//插入200条person对象,每隔20条,清理一下一级

//缓存

@Test

public void testManager(){

Session session = null;

try {

session = HibernateUtils.getSession();

session.beginTransaction();

for(int i =1;i<=200;i++){

Person person = new Person();

person.setAge(i);

session.saveOrUpdate(person);

if(i%20==0){

System.out.println("清理缓存");

session.flush();

session.clear();

}

}

session.getTransaction().commit();

} catch (Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

} finally{

HibernateUtils.closeSession();

}

}

}

     

3  hibernate中的二级缓存

   1) 二级缓存的定义:二级缓存也叫进程级缓存还叫SessionFactory级缓存,二级缓存可以让所有的session共享

   2)二级缓存的生命周期:二级缓存的生命周期跟SessionFactory的生命周期一致,SessionFactory可以管理二级缓存

   3)二级缓存内部结构Hashtable,二级缓存也是只能保存对象,不能保存属性,而且需要第3方的插件才可以使用二级缓存

   4) 使用二级缓存的步骤:

          a) 导入第3方jar:ehcache-1.2.3.jar

          b) 修改hibernate.cfg.xml文件

                (1)开启二级缓存

                (2)声明二级缓存的提供商

<!-- 开启二级缓存 -->

<property name="hibernate.cache.use_second_level_cache">

true</property>

<!-- 指明二级缓存的提供商 -->

<property name="hibernate.cache.provider_class">

org.hibernate.cache.EhCacheProvider

  c)提供二级缓存的配置文件:

   src/ehcache.xml

5) ehcache.xml

  maxElementsInMemory="10000"

  // 二级缓存中能保存的对象的数量最大值

        eternal="false"

      // 二级缓存中保存的对象是否永远有效,

      false : 不是永远都有效(企业开发一般配置false)

      true: 永远有效

        timeToIdleSeconds="120"

      // 两次访问该对象的最大的间隔时间,超过此时间

      // 该缓存中的对象消失  

        timeToLiveSeconds="120"

      //缓存中的对象的最大生命周期为120秒,超过

      //该时间,该对象消失

        overflowToDisk="true"

      //当二级缓存的对象太多了以后,可以临时

      //把对象保存到硬盘当中  

    6)在hibernate.cfg.xml指定把那个对象放入二级缓存

    中

     <class-cache usage="read-only" 

class="com.tarena.po.Person"/>

   7) load  , get, iterate支持二级缓存的读写

       list只能写入二级缓存,不能读取二级缓存

   8) 管理二级缓存

   二级缓存需要使用SessionFactory来进行管理

   evict(po类.class, id):根据id删除二级缓存中的对象

   evict(po类.class):删除二级缓存中所有的po类的对象

案例:hibernate_day06_Cache2

package com.tarena.test;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.SQLQuery;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.junit.Test;

import com.tarena.po.Person;

import com.tarena.util.HibernateUtils;

public class Cache2Test {

@Test

public void testSave(){

Session session = null;

try {

session = HibernateUtils.getSession();

for(int i=1; i<=6 ;i++){

session.beginTransaction();

Person person = new Person();

person.setAge(i+10);

person.setPname("IamNO"+i);

person.setBirthday(new Date());

person.setSalary(i*10000);

session.saveOrUpdate(person);

session.getTransaction().commit();

}

} catch (Exception e) {

e.printStackTrace();

session.getTransaction().rollback();

} finally{

HibernateUtils.closeSession();

}

}

//load方法可以读写二级缓存

//在两个session中,调用load查询同一个对象

@Test

public void testCache2Load1(){

Session session = null;

try {

session = HibernateUtils.getSession();

Person person =  (Person) session.load(Person.class, 1);

System.out.println(person.getAge());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("________________________");

try {

session = HibernateUtils.getSession();

Person person =  (Person) session.load(Person.class, 1);

//没有发出sql语句,上次使用load查询person对象的时候

//把person对象放入一级缓存当中,又把person对象放入

//而且缓存当中,当session关闭的时候,一级缓存

//清空,person在一级缓存中不存在了,但二级缓存

//的生命周期跟session无关,二级缓存中依然保存

//person对象,当再次使用load查找同一个person对象

//首先去缓存查找,有则使用,没有,去数据库中查询

System.out.println(person.getAge());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//get方法支持读写二级缓存

// 在两个session中调用get方法查询同一个person对象

@Test

public void testCacheGet1(){

Session session = null;

try {

session = HibernateUtils.getSession();

Person person =  (Person) session.get(Person.class, 1);

System.out.println(person.getAge());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("-------------------------------------");

try {

session = HibernateUtils.getSession();

// 没有发出sql语句

Person person =  (Person) session.get(Person.class, 1);

System.out.println(person.getAge());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//iterate支持二级缓存的读写

//在两个session中调用iterate查询一样的person对象

@Test

public void testCache2Iterate(){

Session session = null;

try {

session = HibernateUtils.getSession();

Iterator<Person> iterator = 

session.createQuery("from Person")

.iterate();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getAge());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("------------------------------");

try {

session = HibernateUtils.getSession();

Iterator<Person> iterator = 

session.createQuery("from Person")

.iterate();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getAge());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

// 在两个session使用iterate来查询属性

//二级缓存不支持对属性的保存

@Test

public void testCache2Iterate2(){

Session session = null;

try {

session = HibernateUtils.getSession();

Iterator<String> iterator = 

session.createQuery("select pname from Person")

.iterate();

while(iterator.hasNext()){

String name = iterator.next();

System.out.println(name);

}

  } catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("---------------------------");

//发出sql语句,二级缓存不保存属性

try {

session = HibernateUtils.getSession();

Iterator<String> iterator = 

session.createQuery("select pname from Person")

.iterate();

while(iterator.hasNext()){

String name = iterator.next();

System.out.println(name);

}

  } catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在两个session中两次使用list来查询同样的person对象

@Test

public void testCache2List1(){

Session session = null;

try {

session = HibernateUtils.getSession();

List<Person> list = 

session.createQuery("from Person")

.list();

Iterator<Person> iterator = list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("_____________________");

try {

session = HibernateUtils.getSession();

List<Person> list = 

session.createQuery("from Person")

.list();

Iterator<Person> iterator = list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

//在两个session中,先使用list查询person对象,然后

//在使用iterate查询同样的person对象

@Test

public void testListIterate(){

Session session = null;

try {

session = HibernateUtils.getSession();

List<Person> list = 

session.createQuery("from Person")

.list();

Iterator<Person> iterator = list.iterator();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("---------------------------");

//发出查询id的sql语句,上次使用list查询的时候,

//把person对象放入二级缓存当中,当再使用

//iterate查询同样的对象的时候,hibernate会先

//发出查询id的sql语句,然后根据id去二级缓存中

//查询所要的person对象

try {

session = HibernateUtils.getSession();

Iterator<Person> iterator = 

session.createQuery("from Person").iterate();

while(iterator.hasNext()){

Person person = iterator.next();

System.out.println(person.getPname());

}

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

// 管理二级缓存

// 在两个session中,第1个session,使用load方法

// 查询id = 1,id =2的person对象,

//  管理二级缓存

//第2个session中,也使用load方法查询id =1,id=2的

//person对象

@Test

public void testManage(){

Session  session = null;

try {

session = HibernateUtils.getSession();

Person person1 = (Person) session.load(Person.class, 1);

System.out.println(person1.getPname());

Person person2 = (Person) session.load(Person.class, 2);

System.out.println(person2.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

System.out.println("------------------------------------");

SessionFactory factory = HibernateUtils.getSessionFactroy();

//去掉二级缓存中id = 2的person对象

//evict(po类.class, id):根据id删除二级缓存中的对象

//factory.evict(Person.class, 2);

//去掉二级缓存中所有的person对象

factory.evict(Person.class);

try {

session = HibernateUtils.getSession();

Person person1 = (Person) session.load(Person.class, 1);

System.out.println(person1.getPname());

Person person2 = (Person) session.load(Person.class, 2);

System.out.println(person2.getPname());

} catch (Exception e) {

e.printStackTrace();

} finally{

HibernateUtils.closeSession();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值