本文主要讲解:

1 级联 cascade 关键字

2 级联删除

3 inverse 关键字

4 懒加载

5 缓存的模拟

6 Hibernate 的一级缓存

7 Hibernate 的二级缓存

一、级联 cascade 关键字

  1. public static void add(){
  2. NiGuAn niguan=new NiGuAn();
  3. niguan.setName("九峰寺");
  4.  
  5. NiGu nigu1=new NiGu();
  6. nigu1.setNiguan(niguan);
  7. nigu1.setFahao("空空大师");
  8.  
  9. NiGu nigu2=new NiGu();
  10. nigu2.setNiguan(niguan);
  11. nigu2.setFahao("玄玄");
  12.  
  13. NiGu nigu3=new NiGu();
  14. nigu3.setNiguan(niguan);
  15. nigu3.setFahao("灭绝");
  16.  
  17. try{
  18. Session s=HibUtil.getSession();
  19. Transaction tx=s.beginTransaction();
  20.  
  21. List<NiGu> niguList=new ArrayList<NiGu>();
  22. niguList.add(nigu1);
  23. niguList.add(nigu2);
  24. niguList.add(nigu3);
  25.  
  26. niguan.setNiguList(niguList);
  27.  
  28. s.save(niguan);
  29.  
  30. /*s.save(nigu1);
  31. s.save(nigu2);
  32. s.save(nigu3); 如果这里不写,将出错 */
  33.  
  34. tx.commit();
  35. }

可以使用 cascade (级联) 的方式进行处理

在 NiGuAn.hbm.xml 中 添加

  1. <bag name="niguList" cascade="save-update"> //添加的是级联保存
  2. <key column="niguan_id" />
  3. <one-to-many class="NiGu" />
  4. </bag>

级联 cascade 的几个配置

-- none // 忽略其他关联的对象,默认值

-- all  //级联删除, 级联更新,但解除父子关系时不会自动删除子对象.

-- save-update //当session通过save(),update(),saveOrUpdate()方法来保存或更新对象时,级联保存所有关联的新建的临时对象,并且级联更新所有关联的游离对象

-- delete  //级联删除, 但不具备级联保存和更新

-- lock //通过lock()把当前游离对象加入session缓存时,会把所有的游离对象也加入Session缓存中。

-- refresh //:通过refresh()刷新当前对象时,会级联刷新所有关联的对象。(刷新是指同步更新session缓存中数据)

-- evict //通过evict()清除session缓存中对象时,会级联清除所有关联的对象

-- replicate //通过replicate()复制当前对象时,会级联复制所有关联的对象

-- persist //当session通过persist()方法来保存当前对象时,会级联保存所有关联的新建的临时对象。

-- merge //通过Session的merge()方法来保存当前对象时,会级联融合所有关联的游离对象。

-- delege-orphan(one-to-many)  //删除所有和当前对象时,解除关联行为的对象。

二、级联删除

  1. //删除尼姑庵
  2. public static void delNiGuAn(){
  3. try{
  4. Session s=HibUtil.getSession();
  5. Transaction tx= s.beginTransaction();
  6. NiGuAn niguan=new NiGuAn();
  7. niguan.setId(13); //删除13号 尼姑庵,并且将其关联的所有的尼姑删除
  8. s.delete(niguan);
  9. tx.commit();
  10.  
  11. }finally{
  12. HibUtil.closeSession();
  13. }
  14.  
  15. }
  1. //在 NiGuAn.hbm.xml 中 添加
  2. <bag name="niguList" cascade="delete" > //这里指明要级联删除
  3. <key column="niguan_id" />
  4. <one-to-many class="NiGu" />
  5. </bag>

运行发现.它生成两条sql语句

  1. Hibernate: update NiGu set niguan_id=null where niguan_id=?
  2.  
  3. Hibernate: delete from NiGuAn where id=?

可以看到,并没有真正的级联删除

  1. //真正的级联删除
  2. public static void delNiGuAn(){
  3. try{
  4. Session s=HibUtil.getSession();
  5. Transaction tx= s.beginTransaction();
  6. NiGuAn niguan =(NiGuAn) s.get(NiGuAn.class, 11); //要把主对象查询出来再删除
  7. s.delete(niguan);
  8. tx.commit();
  9. }
  10. }

三、inverse 关键字

inverse 关键字 表示是否放弃关联关系,(在java对象上建立关联的时候,对数据库产生的影响)

在 one-to-manay 和 many-to-many 这两个集合中定义,在 many -to -one 中不可以

inverse = true  表示对象不维护关联关系

维护 one-to-manay 的时候就是更新外键

维护 many-to-many  就是往中间表里添数据

例如: 多对多映射中

  1. <set name="teacherList" table= "teacher_student" inverse="true" > //让学生放弃关联关系的维护
  2. <key column="student_id" />
  3. <many-to-many class="Teacher" column="teacher_id" />
  4. </set>

在Many2Many 的save方法中,写上下面的内容,也不会出错 ,因为学生已经放弃了关联关系,它不会再产生sql语句了

  1. //////////////////////
  2. stu1.setTeacherList(teacherList);
  3. stu2.setTeacherList(teacherList);
  4. //////////////////////

说明:它不允许在多对一映射的时候,在多的一方,放弃关联关系。

四、懒加载

  1. public static NiGuAn search2(){
  2. try{
  3. Session s=HibUtil.getSession();
  4. NiGuAn niguan= (NiGuAn) s.get(NiGuAn.class, 4);
  5. Hibernate.initialize(niguan.getNiguList()); //因为它默认是用懒加载的
  6. return niguan;
  7.  
  8. }finally{
  9. HibUtil.closeSession();
  10. }
  11. }

如果默认想不使用懒加载可以在配置文件中

NiGuAn.hbm.xml 中

  1. <bag name="niguList" lazy="false" >
  2. <key column="niguan_id" />
  3. <one-to-many class="NiGu" />
  4. </bag>
  5.  
  6. //默认:
  7. <bag name="niguList" >
  8. <key column="niguan_id" />
  9. <one-to-many class="NiGu" />
  10. </bag>
  11.  
  12. //相当于
  13. <bag name="niguList" lazy="true" fetch="select" > // fetch 抓取策略
  14. <key column="niguan_id" />
  15. <one-to-many class="NiGu" />
  16. </bag>

fetch="select" 它的另一个取值是 join  ,如果  fetch="join" 则它是以关联查询的方式查询数据,即始 lazy="true" 它也能把从对象的数据查询出来

五、缓存的模拟

  1. public class CacheDemo {
  2. private static Map userCache=new HashMap(); //缓存容器
  3.  
  4. public static Userinfo getUserById(int id){
  5. Userinfo userInfo =null;
  6.  
  7. //先到缓存中去查询用
  8. String key=Userinfo.class.getName()+id;
  9. userInfo=(Userinfo)userCache.get(key);
  10.  
  11. //如果缓存中没有查到,就去数据库中查
  12. if(userInfo==null){
  13. userInfo=(Userinfo) HibUtil.get(Userinfo.class, id);
  14. userCache.put(key,userInfo);
  15. System.out.println("从数据库中查的");
  16. }
  17. else{
  18. System.out.println("命中缓存 ,从缓存中查的");
  19. }
  20.  
  21. return userInfo;
  22. }
  23.  
  24. //在进行update的时候对缓存进行更新
  25. public static void update(Userinfo user){
  26. HibUtil.update(user);
  27. String key=Userinfo.class.getName()+user.getId();
  28. // userCache.remove(key); //把对应的对象从缓存中移除
  29. userCache.put(key, user) ; //也可以这样,以新换旧,也可以
  30. }
  31.  
  32. //在删除的时候对缓存进行更新
  33. public static void delete(Userinfo user){
  34. HibUtil.del(user);
  35. String key=Userinfo.class.getName()+user.getId();
  36. userCache.remove(key); //移除
  37. }
  38.  
  39. //在添加的时候对缓存进行更新
  40. public static void add(Userinfo user){
  41. HibUtil.add(user);
  42. String key=Userinfo.class.getName()+user.getId();
  43. userCache.put(key, user);
  44. }
  45.  
  46. public static void main(String[] args) {
  47. getUserById(101); //从数据库中查的
  48. getUserById(101); //命中缓存 ,从缓存中查的
  49. Userinfo user= getUserById(101); //命中缓存 ,从缓存中查的
  50. user.setUserName("这是换过之后的名字");
  51. HibUtil.update(user); //更新用户信息
  52.  
  53. Userinfo user2=getUserById(101); //命中缓存 ,从缓存中查的
  54. System.out.println(user2.getUserName()); //这是换过之后的名字
  55.  
  56. getUserById(101); //命中缓存 ,从缓存中查的
  57. }
  58. }

六、Hibernate 的一级缓存

Hibernate 中的缓存有两种, 一级缓存,二级缓存

一级缓存 Session 范围内的

二级缓存 SessionFactory 范围内的

  1. //例 一
  2. public static void test(){
  3. Session s=HibUtil.getSession();
  4.  
  5. Userinfo user=(Userinfo) s.get(Userinfo.class, 1); //会添充一级缓存
  6. Userinfo user2=(Userinfo) s.get(Userinfo.class, 1);
  7. Userinfo user3=(Userinfo) s.get(Userinfo.class, 1);
  8. Userinfo user4=(Userinfo) s.get(Userinfo.class, 1);
  9.  
  10. s.close();
  11.  
  12. //可以发现,最后只输出一条sql语句,因为后面的都是从一级缓存中取的
  13. }

关于一级缓存的说明

1) 它的 key Userinfo.class+id

2) 一级缓存是 Session范围的,生命周期短,不实用

3) save ,update ,saveOrUpdate,load,get,list,lock,iterator 等方法都会把对象添到一级缓存中

4) 可以用  Session 的 evict,  clear 等方法清除一级缓存

s.evict(user)  //接收参数,只请一个

s.clear();  //不用传参.会把所有的都清掉

5) 一级缓存不能控制缓存对象的个数,所以有大量操作的时候,可能会造成内存溢出,要注意处理

  1. for(int i=0;i<910000000;i++){
  2. if(i%1000==0){
  3. s.flush(); //同步一级缓存中的数据到数据库中
  4. s.clear();
  5. }
  6. s.save(useri ...)
  7. }

七、Hibernate 的二级缓存

SessionFactory 范围的

Hibernate 把缓存交给别的缓存框架实现 (  有  对应的jar )

配置文件

hibernate.cache.use_second_level_cache   false  //是否合用二级缓存

  1. ## choose a cache implementation 请选择缓存提供者
  2. #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
  3. #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
  1. hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider  //hibernate 默认使用
  1. #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
  2. #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
  3. #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

在hibernet中使用  EhCacheProvider 二级缓存

1) 导包 ehcache-1.2.3.jar

2) 配置主配置文件

  1. <property name="hibernate.cache.use_second_level_cache">true</property> //声明打开二级缓存,默认就是打开
  2. <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> //指明缓存提供者
  3. <property name="hibernate.generate_statistics">true</property> //生成关于缓存的统计信息
  4. 省略....
  5. <class-cache usage="read-only" class="cat.beans.Userinfo"/>
  6. //在后面加这句,指明哪个类使用二级缓存
  7. //不写这句也可以 ,可以加在映射文件Userinfo.hbm.xml 中, <cache usage="read-write"/>

测试代码:

  1. public class SecondCacheTest {
  2. public static void main(String[] args) {
  3. HibUtil.get(Userinfo.class, 1);
  4. HibUtil.get(Userinfo.class, 1);
  5. HibUtil.get(Userinfo.class, 2); //如果为null不会往缓存中放
  6. HibUtil.get(Userinfo.class, 1);
  7. HibUtil.get(Userinfo.class, 1);
  8. HibUtil.get(Userinfo.class, 2);
  9.  
  10. //得到统计信息
  11. Statistics totalInfo=HibUtil.getSessionFactory().getStatistics();
  12. System.out.println(totalInfo);
  13.  
  14. System.out.println("二级缓存放入 "+totalInfo.getSecondLevelCachePutCount()+"次");
  15. System.out.println("二级缓存命中 "+totalInfo.getSecondLevelCacheHitCount()+"次");
  16. System.out.println("二级缓存msiss "+totalInfo.getSecondLevelCacheMissCount()+"次");
  17. }
  18. }

二级缓存放入 2次   //前题是查出来的对象都不为null

二级缓存命中 4次

二级缓存msiss 2次

正常来说,还要有缓存配置文件  ehcache.xml

  1. <diskStore path="java.io.tmpdir"/> //用来指定缓存的存放位置 <diskStore path="c:/cache/xxx" />
  2. ...
  3.  
  4. <defaultCache
  5. maxElementsInMemory="10000" //内存中最多可以少多少个对象
  6. eternal="false" //指定缓存是不是永不过期
  7. timeToIdleSeconds="120" //指的是缓存在空闲时间(秒) 过期以后会被删除
  8. timeToLiveSeconds="120" //指的是缓存对象一共存在的时间
  9. diskPersistent="true" //指定jvm 结束的时候是不是要把缓存存到磁盘上
  10. overflowToDisk="true" //超出个数(maxElementsInMemory 指定的) 以后,是不是往磁盘上存
  11. diskExpiryThreadIntervalSeconds ="60" //清除过期缓存的线程的轮循时间
  12. />

关于二级缓存的说明

1) 哪些方法可以填充二级缓存

get  , save (它不适合于native 主键的类 ,因为这样的主键,不把数据存到数据库的时候是得不到的,所以没有办法生成key,但 uuid,hilo 都可以)

update,saveOrupdate, get, load,list,iterator ,以及 Query,Cirteria 都会填充二级缓存。

但查询的时候,只有 session iterator ,get,load 会从二级缓存中取数据。

iterator 可能会存在 N+1 查询的问题

Query,Cirteria 缓存的命中率比较低, 在hibernate默认是关闭 ,因为它的查询条件复杂,而且缓存的数据量大

可以用

  1. <property name="hibernate.cache.use_query_cache">true</property> // 可以打开Query,Cirteria 查询的二级缓存支持

2) 清除二级缓存

  1. HibUtil.getSessionFactory().evict(Userinfo.class,1); //清id为1的 Userinfo 对象的缓存
  2. HibUtil.getSessionFactory().evict(Userinfo.class,); //清除所有的 Userinfo 对象的缓存
  3.  
  4. //注意:它没有清除所有的缓存的方法

3) 关于Query 的缓存

  1. public static void main(String[] args) {
  2. QueryCacheTest(1);
  3. QueryCacheTest(1);
  4. QueryCacheTest(1);
  5.  
  6. // ...打印缓存命中信息
  7.  
  8. public static UserInfo QueryCacheTest(int id){
  9. Session s=HibUtil.getSession();
  10. Query q=s.createQuery("from UserInfo as u where u.id="+id); //它会把查询条件当做Key
  11. q.setCacheable(true); //注意要有这句
  12. UserInfo u=(UserInfo)q.uniqueResult();
  13.  
  14. s.close();
  15. return u;
  16. }

说明,Query q=s.createQuery("from UserInfo as u where u.id="+id)  这种,它会把查询条件当做key,把 usersId 列表做为一个key

然后再根据key中的 user id 去缓存中找 UserInfo的信息,最差的情况是它失效了,如果有一百个id 就会去数据库中找一百次。

Java框架之Hibernate(三)的更多相关文章

  1. java框架篇---hibernate入门

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDB ...

  2. Java框架之Hibernate(一)

    一.Hibernate - 核心接口 它是  JBoss Community team (社区团队) 开发的.Hibernate 是一个开源的,对象关系模型框架 (ORM),它对JDBC进行了轻量的封 ...

  3. java框架之Hibernate(2)-持久化类&主键生成策略&缓存&事务&查询

    持久化类 概述 持久化:将内存中的对象持久化到数据库中的过程就是持久化.Hibernate 就是用来进行持久化的框架. 持久化类:一个 Java 对象与数据库的表建立了映射关系,那么这个类在 Hibe ...

  4. java框架篇---hibernate之缓存机制

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  5. Java框架之Hibernate(四)

    本文主要介绍: 1 悲观锁和乐观锁 2 使用版本号控制并发访问 3 flush方法和批量更新的问题 4 DetachedCriteria 5 N + 1 次查询 6 使用sql进行查询 7 注解方式 ...

  6. Java框架之Hibernate(二)

    本文主要介绍: 1 Criteria 接口 2 用 myeclipse 反向生成 3 hibernate  主键生成策略 4 多对一 5 一对多 6 使用List 集合的一对多 7 多对多 一.Cri ...

  7. SSH框架之-hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...

  8. JAVA框架之Hibernate框架的学习步骤

    首先介绍一下Java三大框架的关系 以CRM项目即客户关系管理项目示例 hibernate框架的学习路线: 1.学习框架入门,自己搭建框架,完成增删改查的操作 2.学习一级缓存,事物管理和基本查询 3 ...

  9. java框架之Hibernate(1)-简介及初使用

    简介 hibernate 是一个开源 ORM ( Object / Relationship Mipping ) 框架,它是对象关联关系映射的持久层框架,它对 JDBC 做了轻量级的封装,而我们 ja ...

随机推荐

  1. js模拟静态方法

    //模拟静态 var Animal = function(name){ this.name = name; Animal.instanceCounter ++; }; Animal.instanceC ...

  2. 相似QQ对话框上下部分可拖动代码

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. 二叉排序树(BST)构造与应用

             二叉排序树(BST)构造与应用       本文取自<数据结构与算法>(C语言版)(第三版).出版社是清华大学出版社.       本博文作为学习资料整理. 源码是VC+ ...

  4. IT运维如何防止陷入“中年油腻”和频繁被动地打“遭遇战”?

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:陈峻近期,我拜访了一家文化传播公司的 IT 运维总监 Tim,他向我讲述了他的团队是如何像当年玩<大航海时代>那样将 IT ...

  5. cs231n --- 1:线性svm与softmax

    cs231n:线性svm与softmax 参数信息: 权重 W:(D,C) 训练集 X:(N,D),标签 y:(N,1) 偏置量bias b:(C,1) N:训练样本数:  D:样本Xi 的特征维度, ...

  6. Python 项目实践二(生成数据)第一篇

    上面那个小游戏教程写不下去了,以后再写吧,今天学点新东西,了解的越多,发现python越强大啊! 数据可视化指的是通过可视化表示来探索数据,它与数据挖掘紧密相关,而数据挖掘指的是使用代码来探索数据集的 ...

  7. margin相关

    1.图片与文字对齐问题 如果图片和文字差不多大时,使用兼容性强的margin负值方法. 方法:img{margin:0 3px -3px 0;} 2.div嵌套后margin出现失效(转移)问题 原因 ...

  8. iOS 5个Xcode开发调试技巧

    转自Joywii的博客,原文:Four Tips for Debugging in XCode Like a Bro    1.Enable NSZombie Objects(开启僵尸对象) Enab ...

  9. HTML+DIV+CSS+JSweb前端基础

    HTML+DIV+CSS+JSweb前端基础 1.<html>和</html> 标签限定了文档的开始和结束点. 属性: (1)  dir: 文本的显示方向,默认是从左向右 (2 ...

  10. go实例之线程池

    go语言使用goroutines和channel实现一个工作池相当简单.使用goroutines开指定书目线程,通道分别传递任务和任务结果.简单的线程池代码如下: package main impor ...