🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 简介 Hibernate为了更好管理持久化类,将持久化类分成三种状态. **分别是瞬时状态,持久态,托管态** **Hb框架使用cglib代理生成代理对象.代理对象是继承被代理对象.如果被final修饰就无法使用** # 瞬时状态(transient) 临时态或者自由态,瞬时态的实例是由new命令创建,开辟内存空间的对象, **不存在持久化标识OID(相当于主键值),尚未与`hibernate Session`关联.** **在数据库中没有记录,失去引用会被JVM回收.** 在内存中是孤立的,在数据库中的数据无任何关联,仅是一个信息携带的载体 # 持久态(persistent) **存在持久化标识OID,加入到Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录.** 每条记录只对应唯一的持久化对象,需要注意的是,持久化对象是在事务还没提交前变为持久态的 oid就是数据库主键 用hb,表必须有主键,没有主键就用不了 # 托管态(detached) 托管态也叫离线态或者游离态,当某个持久态状态实例与session的关联被关闭就变成托管态. **托管态存在持久化表示OID,并且仍然与数据库中的数据存在关联,只是失去了与当前session的关联,托管状态对象发生改变时Hibernate不能检测到** # 区分对象的三种状态 customer对象由new关键字创建,此时还未与session关联,他的状态称为瞬时态. 在执行了`session.save(customer);`操作后, 对象纳入了session的管理范围. 这时customer对象变成了持久态对象,此时session的事务还没有被提交. 程序执行完commit()操作并关闭了session后,customer对象与session的关联被关闭,此时customer对象变成了托管态 ~~~ @Test public void fun2() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 瞬时状态没有持久化表示oid,没有被session管理 Customer customer = new Customer(); customer.setCust_name("老王"); // 持久化对象:有持久化表示oid,被session管理 Serializable id = session.save(customer); tx.commit(); session.close(); // 托管状态,有持久化表示oid,没有被session管理 System.out.println(customer); } ~~~ # 转换 new对象是瞬时态,当执行Session的save()或者saveOrUpdate()方法后, 该对象将被放入session的一级缓存,对象进入持久态. 当进入持久态的对象执行evict(),close()或者clear()操作后,对象进入托管态. 当直接执行session的get(),load(),find()或者iterate()等方法从数据库里查询对象时,查询到的对象也处于持久态. 当对数据库中的记录进行update(),saveOrUpdate()以及lock()等操作后,此时托管态的对象就过渡到持久态. 由于瞬时态和托管态不在session管理范围内,会被jvm回收 ![](https://img.kancloud.cn/c3/89/c389be9fd4d7553bd533fcee585546a0_616x398.png) 1. 瞬时态转换到其他状态 * 瞬时态转换为持久态:执行 Session的 save或 saveOrUpdateO方法。 * 瞬时态转换为托管态:为瞬时态对象设置持久化标识OD。 由于持久化对象状态演化图中没有涉及到瞬时态转换到脱管态的情况,这里做下简要的说明, 脱管态对象存在OD,但是没有 Session的关联,也就是说脱管态和瞬时态的区别就是oD有没有值,所以可以通过为瞬时态对象设置OD,使其变成脱管态对象。 ~~~ Customer customer= new Customer();//瞬时态 customer setCust id(1); //脱管态 ~~~ 2. 持久态对象转换到其他状态 持久化对象可以直接通过 Hibernate中 Session的get()、 load()方法,或者 Query查询从数据库 中获得: * 持久态转换为瞬时态:执行 Session的delete方法,需要注意的是被删除的持久化对象,不 建议再次使用 * 持久态转换为托管态:执行 Session的 evict、 closed或 clear方法。 evict()方法用于清除一 级缓存中某一个对象; close()方法用于关闭 Session,清除一级缓存; clear方法用于清除 级缓存的所有对象。 3. 脱管态对象转换到其他状态 脱管态对象无法直接获得,是由其他状态对象转换而来的 * 脱管态转换为持久态: 执行 Session的 update()、 saveOrUpdate()或 lock()方法。 * 脱管态转换为瞬时态:将脱管态对象的持久化标识OD设置为null 由于持久化对象状态演化图中没有涉及到脱管态转换到瞬时态的情况,这里做下简要的说明 跟瞬时态转换到脱管态的情况相似,脱管态和瞬时态的区别就是OD有没有值,所以可以通过将脱 管态对象的oD设置为null,使其变成瞬时态对象。例如在 session.close()操作后,加入代码 `customer.setCust_id(null)`, customer对象将由脱管态转换为瞬时态。 ## 总结 1. 瞬时态(new出来的) 瞬时--->持久 save, saveOrUpdat 瞬时--->脱管(游离)手动设置oid 2. 持久态它是由 session管理 ~~~ 持久--->瞬时 delete()被删除后持久化对象不在建议使用 ~~~ ~~~ 持久--->脱管 注意 session它的缓存就是所说的一级缓存 evct(清除一级缓存中指定的一个对象 clear(清空一级缓存 cose(关闭,清空一级缓存) ~~~ 3. 脱管态(它是无法直接获取) 脱管--->瞬时直接将oid删除 脱管--->持久 `update, saveOrUpdate lock(过时)` ![](https://img.kancloud.cn/e0/6d/e06dbe927231e898e08f97d574addbe1_861x576.png) # 自动更新数据库 其实我们主要去研究持久态对象就够了, **持久态对象其实有一个非常重要的特性:持久态对象可以自动更新数据库** ~~~ @Test //测试持久化类的持久态对象有自动更新数据库的能力 public void demo2() { Session session= HibernateUtils.openSession(); Transaction tx session beginTransaction(); //获得持久态的对象 Customer customer= session.get(Customer. class,1L);//持久态对象 customer.setCust_name("王五”) // session.update(customer);//不用手动调用update方法就可以更新 tx.commit(); session.close(); } ~~~ 执行测试我们会发现,我们并没有手动调用update方法, Hibernate就可以将数据自动更新了。 持久态对象就有这样的一个功能。 持久态对象之所以有这样的功能其实都依赖了 Hibernate的一级缓存