Hibernate学习笔记10

 

Hibernate学习笔记10

学习课程:

一级缓存

Hibernate_Cache_Level_1

二级缓存

Hibernate_Cache_Level_2

查询缓存

Hibernate_Cache_Query

 1.一级缓存

一级缓存又称session级的缓存或事务级缓存,可以提高性能

生命周期很短和session一致

一级缓存无法清除但是可以管理,管理方法

session.clear();//清空缓存

session.evict();//清除以及缓存中指定的实体

testQuery1

在一个session中发出两次load查询

  1. //会发出sql
  2. Student student1 = (Student) session.load
  3. (Student.class1);
  4. System.out.println(student1.getName());
  5. //不会发出sql,load使用缓存
  6. Student student2 = (Student) session.load
  7. (Student.class1);
  8. System.out.println(student2.getName());

 

testQuery2

在一个session中发出两次get查询,get使用一级缓存

  1. //会发出sql
  2. Student student1 = (Student) session.get
  3. (Student.class, 1);
  4. System.out.println(student1.getName());
  5. //不会发出sql,load使用缓存
  6. Student student2 = (Student) session.get
  7. (Student.class, 1);
  8. System.out.println(student2.getName());

 

 

testQuery3

在同一个session中发出两次iterate查询实体对象

会发出查询id的sql,不会发出查询实体对象的sql,因为iterate使用缓存

发出id查询列表

发出查询id语句

  1. Student student1 = (Student) session
  2. .createQuery(
  3. "from Student s where s.id = 1").iterate().next();
  4. System.out.println(student1.getName());
  5. //发出查询id语句
  6. Student student2 = (Student) session
  7. .createQuery(
  8. "from Student s where s.id = 1").iterate().next();
  9. System.out.println(student2.getName());

 

 

testQuery4

在同一个session中发出两次iterate查询普通属性

会发出两次查询语句,因为

一级缓存只存放实体对象,对于普通属性不会放到一级缓存中,对于普通属性放到查询缓存中

  1. Query query1 = session
  2. .createQuery("select s.name from Student s where s.id = 1");
  3. String name1 = (String) query1
  4. .uniqueResult();
  5. System.out.println(name1);
  6. Query query2 = session
  7. .createQuery("select s.name from Student s where s.id = 1");
  8. String name2 = (String) query2
  9. .uniqueResult();
  10. System.out.println(name2);

 

 

testQuery5

开启两个session,在不同的session中发出load查询

//一个方法中连接两个session

//会发出两次查询语句

//这与session的生命周期有关

//session间不能共享一级缓存的数据,因为它会伴随session的生命周期存在和消亡

  1. //两个session中的查询代码几乎一样
  2. //只是变量名有区别
  3. Student s1 = (Student) session1
  4. .load(Student.class, 1);
  5. System.out.println(s1.getName());

 

 

testQuery6

同一个session中先save,再发出load查询save过的语句

  1. Student s = new Student();
  2. s.setName("李贺");
  3. Serializable id = session.save(s);
  4. //不会发出sql,因为save使用缓存
  5. Student s1 = (Student) session
  6. .load(Student.class, id);
  7. System.out.println(s1.getName());

 

 

testQuery7

在同一个session中,先调用load查询,执行session.clear() 或 session.evict()

,再调用load查询

  1. Student s1 = (Student) session
  2. .load(Student.class, 1);
  3. System.out.println(s1.getName());
  4. session.clear();//清空缓存
  5. Student s2 = (Student) session
  6. .load(Student.class, 1);
  7. System.out.println(s2.getName());

 

 

testQuery8

大批量数据更新

放弃操作

向数据库中加入1000条数据

为了避免一次性大量的实体数据入库导致内存溢出,

当加入一定的实体数据后

先flush

clear

如果数据量特别大,考虑采用JDBC实现,如果jdbc不能满足要求可以考虑数据库本身的特定导入工具放弃Hibernate

 2.二级缓存

二级缓存,进程级缓存,SessionFactory级缓存

只缓存实体对象,缓存间可以共享

二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存

//SessionFactory factory = HibernateUtils.getSessionFactory();

//factory.evict( Student.class );清空

//factory.evict( Student.class , 1 );清除二级缓存中指定的实体

配置信息:

Student.hbm.xml

  1. <!-- 指定实体使用缓存,并且设置二级缓存的使用策略,在id标签之前 -->
  2. <cache usage="read-only"/>

Hibernate.cfg.xml

  1. <!-- 指定缓存提供商 -->
  2. <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
  3. <!-- 显示开启二级缓存,默认开启 -->
  4. <property name="hibernate.cache.use_second_level_cache">true</property>
  5. <class-cache class="entity.Student" usage="read-only"/>

testQuery1

开启两个session,在不同的session中发出load查询

结果:只在第一个session中发出sql语句

  1. //两个session中的查询代码几乎一样
  2. //只是变量名有区别
  3. Student s1 = (Student) session1
  4. .load(Student.class1);
  5. System.out.println(s1.getName());

 

testQuery2

开启两个Session,分别调用get查询

结果只在第一个session中发出sql

  1. //两个session中的查询代码几乎一样
  2. //只是变量名有区别
  3. Student s1 = (Student) session1
  4. .get(Student.class1);
  5. System.out.println(s1.getName());

 

 

testQuery3

开启两个session,先调用load查询,再使用SessionFactory清除二级缓存,再调用load查询

结果:两个session都发出sql

  1. //两个session中的查询代码几乎一样
  2. //只是变量名有区别
  3. Student s1 = (Student) session1
  4. .get(Student.class1);
  5. System.out.println(s1.getName());
  6. //在两个session间加入,清空二级缓存
  7. factory.evict( Student.class );

 

testQuery4

 一级缓存和二级缓存的交互

在加载数据前进行session设置

  1. session1.setCacheMode( CacheMode.GET );
  2. Student s1 = (Student) session1
  3. .load(Student.class1);
  4. System.out.println(s1.getName());
  5. //CacheMode.NORMAL  默认情况,可以想二级缓存中读/写数据
  6. //CacheMode.GET 仅向二级缓存中读数据
  7. //CccheMode.PUT 仅向二级缓存中写数据

 

 3.查询缓存

查询缓存针对普通属性结果集

缓存普通属性

当查询实体的时候,缓存实体的ID

查询缓存的生命周期:当前关联的表(更新,删除,插入)发生修改,那么查询缓存生命周期结束

配置信息:

Hibernate.cfg.xml

  1. <!-- 开启查询缓存 -->
  2. <property name="hibernate.cache.use_query_cache">true</property>

注:打开查询缓存不仅仅需要配置hibernate.cfg.xml还需要在代码中打开

query.setCacheable(true);

testQuery1

开启查询缓存,关闭二级缓存

开启一个session,分别调用query.list

  1. Query query = session.createQuery("select s.name from Student s");
  2. //启用查询查询缓存
  3. query.setCacheable(true);
  4. List names = query.list();
  5. System.out.println("------------------");
  6. query = session.createQuery(
  7. "select s.name from Student s");
  8. //启用查询查询缓存
  9. query.setCacheable(true);
  10. //没有发出查询sql,因为启用了查询缓存
  11. names = query.list();

testQuery2

开启查询缓存,关闭二级缓存

开启两个session,分别调用query.list

查询缓存只对query.list()起作用,query.iterate不起作用,也就是query.iterate不使用

查询缓存

 

  1. //两个session中对数据的查询一样
  2. Query query = session.createQuery("select s.name from Student s");
  3. //启用查询查询缓存
  4. query.setCacheable(true);
  5. //第一个session
  6. for (Iterator iter = query.iterate(); iter.hasNext();)
  7. //第二个session
  8. for (Iterator iter = query.iterate(); iter.hasNext();)

 

testQuery3

开启查询缓存,关闭二级缓存

开启两个session,分别调用query.list

第二个session不会发出查询sql,因为查询缓存的生命周期和session无关

 

  1. //两个session的查询代码一样
  2. Query query = session.createQuery("select s.name from Student s");
  3. //启用查询查询缓存
  4. query.setCacheable(true);
  5. List names = query.list();

 

testQuery4

关闭查询缓存,关闭二级缓存

开启两个session,分别调用query.list查询实体对象

 

  1. Query query = session.createQuery("select s from Student s");
  2. //启用查询查询缓存
  3. //query.setCacheable(true);
  4. List students = query.list();
  5. //第二个session,会发出查询sql,因为list默认每次都会发出查询sql

 

testQuery5

开启查询缓存,关闭二级缓存

开启两个session,分别调用query.list查询实体对象

 

  1. Query query = session.createQuery("select s from Student s");
  2. //启用查询查询缓存
  3. query.setCacheable(true);
  4. 会发出n条查询语句,因为开启了查询缓存,关闭了二级缓存,那么查询缓存会缓存实体对象的id,所以hibernate会根据实体对象的id去查询相应的实体,如果缓存中不存在相应的实体那么将发出根据实体id查询的sql语句,否则不会发出sql使用缓存中的数据

 

testQuery6

开启查询缓存,开启二级缓存

开启两个session,分别调用query.list查询实体对象

 

  1. Query query = session.createQuery("select s from Student s");
  2. 启用查询查询缓存
  3. query.setCacheable(true);
  4. //第二个session不会发出查询sql,因为开启了二级缓存和查询缓存,查询缓存缓存了实体对象的id列表hibernate会根据实体对象的id列表到二级缓存中取得相应的数据

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值