Hibernate 中对象的状态:
在Java中,当new了一个对象时,该对象的生命周期就开始了,当没有一个变量引用它的时候,他的生命周期
也就随之而结束,Java垃圾回收器就会清理被它占用的内存。
在Hibernate中,对于需要被持久化的对象,在它的生命周期中有三种状态:
临时态 transient:(也叫 瞬时态,自由态)刚刚创建出来的对象,还没有被持久化,不处于Session的缓存当中,
处于临时状态的Java对象被称为 临时对象。
持久化状态 persistent:已经被持久化的对象,已经加入到Session的缓存当中,与数据库记录对应
的Java对象称为 持久化对象。
游离状态 detached :(也叫 脱管态)已经被持久化,但不存在与 Session 的缓存当中处于游离态的
对象,称为游离态对象。
方法对应对象的不同状态:
new,delete 临时状态(瞬时态,自由态)
save 转变为持久化状态
update,load,get,saveOrUpdate,lock,find,iterate... 处于持久化状态
close,clear,evict 转变为 游离态(脱管态)
临时态:
不属于任何一个Session的缓存,数据库中无记录与之对应。
new语句创建的对象处于临时状态
delete 是一个 持久化 或 游离态 的对象变为 临时态。
delete 方法将 游离态 对象对应的数据库记录删除。
delete 方法将 持久化 对象对应的数据库记录删除,并且从Session的缓存中移除。
持久化状态:
处于一个Session的缓存当中,与数据库中的一条记录对应。
Session在清理缓存时,会根据对象状态的变化来更新到数据库。
save方法 将 临时态对象 转化为 持久态对象。
load,get,find 方法从数据库中查询对象,这些对象都是持久化状态的对象。
update,saveOrUpdate,lock 方法将 游离态 对象转化为 持久态对象。
当一个持久态对象关联一个临时对象,在允许级联保存的情况下,Session在清理缓存时,会将
所关联的临时态的对象也转变为持久态对象。
对于两个Session,即使两个Session中存在与同一条数据库记录对应的对象,因为它们存在于不同的
Session中它们的内存地址是不相同的。
如果两个Session共同处理同一个对象,就会发生重复的操作。
Person p1 = session1.get(Person.class, 1);
session2.update(p1);
p1.setName("new Name");
session1.commit();
session2.commit();
这样会生成两个update的SQL语句,对于Session1在提交事物时会根据对象改变的状态来生成SQL语句。
对于Session2来说,p1是处于Session1的缓存中还没有与Session2关联,因此对于Session2 来说,p1
还处于游离态。当Session2调用 update方法与p1发生关联时,p1也会变成 Session2 中的持久化状态。
接着改变了p1的状态,那么Session2在提交的时候也会根据改变的状态生成相应的SQL语句。
在实际的应用程序中,我们应该避免这样的情况出现,应为一个对象与两个Session关联,会导致
冗余的SQL,而且还会引发一些不必要的错误。
游离状态:
游离状态的对象不与Session发生关联。
游离状态的对象是由持久态转化而来的,因此在没有其它程序删除该条记录的情况下还是有与之对应的
数据库记录。
游离对象 与 临时对象 相同之处在于,都没有与之关联的Session对象,因此Hibernate不会保证它们
的属性变化会同步更新到数据库。
不同之处在于,游离对象是从持久态转变而来的,因此还有可能有与之对应的数据库记录,而临时对象
则没有与之对应的数据库记录。
close 方法会清空Session的缓存,缓存中的所有持久化对象都会编程游离态,如果这时没有任何变量
引用它们,它们就结束了生命周期,会被垃圾回收器清理。
evict 方法能够从缓存中删除一个持久化的对象,使它变为游离态。当Session中关联了大量的持久化
状态的对象时,我们可以及时使用该方法清理掉一些不需要的对象,以节省内存。但不推荐这样操作,
应该通过查询语言或显示的导航来控制对象图的深度。
原文链接:https://blog.csdn.net/y540968398/article/details/84296325