hibernate懒加载模式、单表及多表的增删改查

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37942706/article/details/78630015

通过联合查询,获得学生--班级信息,get()方法懒加载,先查询出student的信息,待需要访问其所在班级信息或调用班级方法时才会第二次进行查询,加载班级信息

load()方法懒加载查询本对象包括其具有映射对象的所有信息,而get方法仅仅懒加载其具有映射对象的信息。

iterate()方法,先抛出一个select语句,查询主键信息,,不提内容;提取内容时,再根据主键分别提取,故执行效率不高



Hibernate: select tstudent0_.TNO as col_0_0_, tclass1_.CNO as col_1_0_ from STU.TSTUDENT tstudent0_ inner join STU.TCLASS tclass1_ on tstudent0_.CNO=tclass1_.CNO where tstudent0_.TNO=?
Hibernate: select tstudent0_.TNO as TNO3_0_, tstudent0_.CNO as CNO3_0_, tstudent0_.TNAME as TNAME3_0_, tstudent0_.SEX as SEX3_0_, tstudent0_.BIRTHDAY as BIRTHDAY3_0_, tstudent0_.HEIGHT as HEIGHT3_0_ from STU.TSTUDENT tstudent0_ where tstudent0_.TNO=?
学生 wangkai
Hibernate: select tclass0_.CNO as CNO0_0_, tclass0_.CNAME as CNAME0_0_ from STU.TCLASS tclass0_ where tclass0_.CNO=?
班级 java200班


Iterator的执行特点:
   Query q = this.session.createQuery(hql);
   Iterator it = q.iterate();
   1. 不管是联合查询,还是单表查询,都是抛出一条语句,查询主键信息;
   2. 提取数据时,会根据主键分别提取
多表查询懒加载
    总结: N+1查询,执行效率不高


iterate()先查找缓存,先找一级缓存-->>二级缓存, iterate()执行时先要查找缓存,如果缓存中存在数据,则直接从缓存中提取,否则采取数据库提取

list()不查询缓存,直接查找数据库,但查询结果记录会放到缓存中

若两者配合使用--首次查询使用list()查询,之后再用iterate()进行查询会提高查询效率


Hibernate一级缓存的特点:
    一级缓存是基于hibernate 的 session的,当session关闭时,一级缓存会被清空;(不同的session无法共享一级缓存)
    数据插入--save,先加缓存,再写入数据库
    数据查询--q.list,查询数据,并将数据放入一级缓存
get()、load()、q.iterate()---会先读取一级缓存、一级缓存中存储的是对象
Inner join fetch 用一级缓存不太好用


Hibernate二级缓存的特点:
     二级缓存基于hiberante session factory;即它是跨session对象的,所有session可以共享二级缓存;
      如代码表数据,可以放到二级缓存中 (数据特点:数据可变,但是变化频率很低;数据是所有人共享的)

电影购票系统---地区信息的选择
商品很多类型信息的选择--如商品类型信息、品牌信息等等,可以通过下拉框去选择

这些类型信息可以变,将其放到数据库,用代码表将其管理起来,这些信息可变,但变化的频率很低,且是大家的需要共享的信息

      hibernate的二级缓存,依赖于ehcache(缓存--内存结构,从数据库查询出结果,放到缓存中,但数据最终还是在数据库维护)

当数据发生变化时,从数据库重新reload到二级缓存。
装二级缓存的最好时间--程序启动时,利用servletContextListener将数据装到二级缓存


hibernate三种状态:

瞬时态:

脱管态(游离):

持久态:

瞬时(Transient) - 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 使用Hibernate Session可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句) 


持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。 


脱管(Detached) - 与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。 

总结:
    所谓的Hibernate对象状态,指的是hiberante的映射对象(有映射关系存在)
    
    持久(Persistent): 实体对象通过hibernate写入到数据库后,就称为持久态 
              1. 要有持久化标识  (主键) ,数据库中要有对应的对象
              2. 这个对象要与session关联

    脱管(Detached) :  所谓的托管对象就是脱离了hibernate的session管理,脱离一级缓存的管理

              场景:把一个对象写入数据库,然后关闭session,这时对象就称为了托管对象;
            1. 要有持久化标识  (主键), 数据库中要有对应的对象
            2. 这个对象不要与session关联

   瞬时(Transient):
            1. 这个对象只是内存对象,数据库中没有映射对象
            2. 这个对象不要与session关联 
            
    场景分析:  
            1. 从数据库中读取一个学生对象,这个对象是什么状态?
                      持久态      


            2. 从数据库中读取一个学生对象,然后把session关闭,这个对象是什么状态?
                   托管态

            3. 从数据库中读取一个学生对象,然后把session关闭。(常单元工作机制)
               然后修改对象的属性信息(不能改主键),然后再打开一个新的session,然后把对象update到数据库

                  托管态 -->>  持久态 

            4. 内存中new Tstudent() ;  学生是什么状态?
                   瞬时态

            5.  内存中new Tstudent(),然后打开session,save到数据库;学生是什么状态?
                    持久态

            6. 使用session,delete一个对象,删除成功后,这个对象的状态?
                 答:删除成功后,没有了映射关系,对象由持久态-->>瞬时态


展开阅读全文

没有更多推荐了,返回首页