// 查出对象,原来的 name 为 user1
User user = userManager.findOne(1);
// 将userName 设置为 user2 ,用于前端显示,并没有保存
user.setName("user2");
// heibernate 自动进行了保存,库中的 name 为 user2
原因
Heibernate 中对象分为以下几种状态:
瞬时状态:
实际上就是 new 了一个普通的 JavaBean 对象。
托管状态:
当瞬时对象调用了管理器的 persist() 后,即可将一般的 JavaBean 做为了持久 Bean,该 Bean
的任何属性改动都会牵涉到数据库记录的改动。一旦该记录 flush
到数据库之后,并且事务提交了,那么此对象不在持久化上下文中,即:变为了游离(没人管的孩子)状态了。在游离状态的时候调用更新、刷新方法后,游离状态对象就变为了在持久化上下文的托管状态了。通过管理器的 find 方法,将实体从数据库查询出来后,该实体也就变为了托管形态。
持久化状态:
当处在托管状态的实体 Bean 被管理器 flush 了,那么就在极短暂的时间进入了持久化状态, 事务提交之后,立刻变为了游离状态。您可以把持久化状态当做实实在在的数据库记录。
游离状态:
游离状态就是提交到数据库后,事务 commit 后实体的状态,因为事务已经提交了, 此时实体的属性任你如何改变,也不会同步到数据库,因为游离是没人管的孩子,不在持久化上下文中。
销毁对象:
一般要删除一个持久化对象的时候都是先 find 出来,之后调用 remove 方法删之, 此时这个对象就是销毁对象,实际上就是瞬时对象的另一种形态罢了。
根据上面的各种状态,可以得知。通过 find 查出某个对象后,就进入了托管状态,此时对对象的任何属性改动,都会自动保存到数据库中。
解决方法:
1 . 通过 new 一个新的对象出来进行操作,这个新的对象是瞬时状态,不会自动保存。
// 查出对象
User user = userManager.findOne(1);
// new 一个新的对象
User newUser = new User();
// 将需要用到的属性赋予新的对象,对于前端显示
try {
org.springframework.beans.BeanUtils.copyProperties(user, newUser);
} catch (BeansException e) {
e.printStackTrace();
}
// 不要对 newUser 进行保存即可。也不要改变 user 的属性
2. 在 find 查出的对象 set 属性前,将其状态改为游离状态。这样的话会用到 session 的几个方法:
close、clear、evict。
close 方法:关闭 session 这样这个对象肯定是游离态了,因为 session
已经关闭了,但是往往我们实际的开发过程中,session 在后面是要用的到的,所以这个方法可行,但是不一定用得上,分清具体的情况。clear 方法:将 session 中的所有的对象全部清除出缓存,这个方式有点劳师动众,不过 session
清除了全部的对象之后自然就会变为游离态了,这样做不是很好吧我感觉。evict 方法:将某一个对象清除出缓存
session,这个方法是很好的实现方式,推荐使用。调用的时候是这样的,session.evict(Object obj) 这样就可以了。
这边推荐使用 evict 方法,代码如下:
@PersistenceContext
private EntityManager entityManager;
......
// 获取 session
HibernateEntityManager hEntityManager = (HibernateEntityManager)entityManager;
Session session = hEntityManager.getSession();
// 查出对象,原来的 name 为 user1
User user = userManager.findOne(1);
// 将对象清除出缓存 session,这样后面对属性的改变就不会自动保存
session.evict(user);
// 将userName 设置为 user2 ,用于前端显示
user.setName("user2");
// 由于清除出了 session,heibernate 不会对这个对象进行保存,库中的 name 仍为 user1
但是在SpringData JPA 下 注入
@PersistenceContext private EntityManager entityManager;
未能使evict方法,我目前是copy一个新的对象的方式解决的