边肖将分享一些Hibernate三种状态转换的例子。希望大家看完这篇文章后有所收获。我们一起讨论一下吧!
一、遇到的神奇的事情
使用jpa操作数据库,在我使用findAll()方法调查处理了一个list的对象后,我对这个List的实体做了一些操作,没有调用update或者saveOrUpdate方法,但是更改后的数据神奇地保存在了数据库中。
最后,简单粗暴的解决方法是将数据中找到的List复制一份,然后进行操作,然后返回。数据正常,数据库未更新。查找资料后发现jpa是hibernate的封装,底层是hibernate,这是hibernate的持久状态造成的。
二、hibernate 的三种状态
瞬时状态 (Transient)
当我们通过Java的new关键字生成一个实体对象时,这个实体对象处于自由状态,如下所示:
客户客户=新客户(“zx”,27,图片);
此时,客户对象处于自由状态。为什么客户对象处于自由状态?这是因为,此时客户只通过JVM获得了一个内存空间,但是还没有通过Session对象的save()方法保存到数据库中,所以还没有纳入Hibernate的缓存管理,也就是说客户对象还在Hibernate的缓存管理之外自由游荡。所以我们可以看到,free object最大的特点就是数据库中没有与之对应的记录。
瞬时对象特点:
与会话实例不关联
数据库中没有与瞬态对象相关联的记录。
持久状态 (Persistent)
持久对象是已经保存到数据库中的实体对象,这个实体对象仍然在Hibernate的缓存管理中。这是对实体对象的任何修改,当清理缓存时,这些修改将与数据库同步。如下图所示:
客户客户=新客户(“zx”,27,图片);
tx=session . BeginIntrasaction();
session.save(客户);
客户=(客户)会话.加载(客户.类,“1”);
customer . setage(28);
tx.commit();
此时我们并没有显示我们调用了session.update()方法来保存更新,而是将实体对象的修改同步更新到数据库中,因为此时客户对象通过save方法保存到数据库中之后,已经是一个持久对象了,再通过load方法重新加载,仍然是一个持久对象,所以还是在Hibernate cache的管理下。此时,当执行tx.commit()方法时,Hibernate将自动清理缓存,并将持久对象的属性更改自动同步到数据库。
的持久性实例在数据库中有相应的记录,并有一个持久性标识符。
持久对象总是与会话和事务相关联。在Session中,对持久对象的更改不会立即改变数据库,只有在Transaction终止后,即执行commit()后,才能真正在数据库中运行SQL进行更改,持久对象的状态才会与数据库同步。同步前的持久对象称为脏对象。
瞬时对象转为持久对象:
瞬态对象通过Session的save()和saveOrUpdate()方法与数据库相关联,这个瞬态对象成为一个持久对象。
通过fine(),get(),load()和iterater()方法查询的数据对象将成为持久对象。
持久化对象的特点:
和会话实例。
数据库中有与持久对象相关联的记录。
脱管状态 (Detached)
当持久对象从Hibernate的缓存管理中分离出来时,它处于自由状态。自由对象和自由对象最大的区别是数据库中可能还有对应它的记录,但是现在自由对象和Hibernate分离了。
e的缓存管理,而自由对象不会在数据库中出现与它对应的数据记录。如下所示:
Customer customer=new Customer(“zx”,27,images);
tx=session.beginTransaction();
session.save(customer);
customer=(Customer)session.load(Customer.class,”1”);
customer.setAge(28);
tx.commit();
session.close();
当session关闭后,customer对象就不处于Hibernate的缓存管理之中了,但是此时在数据库中还存在一条与customer对象对应的数据记录,所以此时customer对象处于游离态;
与持久对象关联的 Session 被关闭后,对象就变为脱管对象。对脱管对象的引用依然有效,对象可继续被修改。
脱管对象特点:
-
本质上和瞬时对象相同
-
只是比爱瞬时对象多了一个数据库记录标识值 id.
持久对象转为脱管对象:
当执行 close() 或 clear(),evict() 之后,持久对象会变为脱管对象。
瞬时对象转为持久对象:
通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脱管对象变为持久对象。
三、三种状态的转换
四、举例子
结合 save(),update(),saveOrUpdate() 方法说明对象的状态
(1) Save() 方法将瞬时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save()或 update() 方法是没有意义的。如:
Student stu = new Strudnet();
stu.setCarId(“200234567”);
stu.setId(“100”);
// 打开 Session, 开启事务
session.save(stu);
stu.setCardId(“20076548”);
session.save(stu); // 无效
session.update(stu); // 无效
// 提交事务,关闭 Session
(2) update() 方法两种用途重新关联脱管对象为持久化状态对象,显示调用 update() 以更新对象。调用 update() 只为了关联一个脱管对象到持久状态,当对象已经是持久状态时,调用 update() 就没有多大意义了。如:
// 打开 session ,开启事务
stu = (Student)session.get(Student.class,”123456”);
stu.setName(“Body”);
session.update(stu); // 由于 stu 是持久对象,必然位于 Session 缓冲中,
对 stu 所做的变更将 // 被同步到数据库中。所以 update() 是没有意义的,可以不要这句效果一样的。
// 提交事务,关闭 Session
Hibernate 总是执行 update 语句,不管这个脱管对象在离开 Session 之后有没有更改过,在清理缓存时 Hibernate总是发送一条 update 语句,以确保脱管对象和数据库记录的数据一致,如:
Student stu = new Strudnet();
stu.setCarId(“1234”);
// 打开 Session1, 开启事务
session1.save(stu);
// 提交事务,关闭 Session1
stu.set(“4567”); // 对脱管对象进行更改
// 打开 Session2, 开启事务
session2.update(stu);
// 提交事务,关闭 Session2
注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。
如果希望只有脱管对象改变了, Hibernate 才生成 update 语句,可以把映射文件中 <class> 标签的 select-before-update 设为 true, 这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执行 update语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。
(3) saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断其是脱管对象还是临时对象,然后调用合适的方法。
看完了这篇文章,相信你对“Hibernate三种状态的转换示例”有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/136912.html