Hibernate 实体的生命周期与持久性的上下文有关。
持久性的上下文(Session)处于客户端代码与数据存储之间,它类似于暂存区,负责客户端与数据库的交互。
在暂存区的内所有数据的更改都会被跟踪,并在业务结束时将更改同步至数据库
瞬态只是一个实体对象(DO,PO类的实例),它不存在于暂存区中。
不存在于暂存区的对象是不会被跟踪的,所以对瞬态的任何操作都不会影响至数据库!
要使瞬态持久化则需要调用生命周期中的方法:save(),persist(),saveOrUpdate()。
persist() 符合JPA规范
调用 persist() 后,对象就会从瞬态转换为持久态,该对象处于暂存区中,但尚未保存到数据库中。因为只有在提交事务,刷新或关闭会话时才会生成 insert 语句。
persist() 方法返回 void 类型
使用细节:
- 如果对一个已持久化的对象继续调用 persist() 则对这个实例没有任何影响
- 如果对一个处于分离状态的对象调用 persist() 时,提交或刷新会话时得到一个异常
Person person = new Person();
person.setName("John");
session.persist(person);
session.evict(person);
session.persist(person); // PersistenceException!
3.1 save()
save() 方法不符合JPA规范
与 persist() 方法基本一致,不过此方法首先分配生成的标识符,然后返回此标识符的序列值。
Person person = new Person();
person.setName("John");
Long id = (Long) session.save(person);
当尝试保存一个 分离 的实例时,区别就此诞生
Person person = new Person();
person.setName("John");
Long id1 = (Long) session.save(person); // 分配一个新标识符
session.evict(person);
Long id2 = (Long) session.save(person); // 分配一个新标识符
对 分离 实例的保存调用会创建一个新的持久实例并为其分配一个新标识符
saveOrUpdate() 方法不符合JPA规范
saveOrUpdate() 方法的主要区别在于它在应用于 瞬态 实例时不会抛出异常,而是使这个瞬态实例持久化。
Person person = new Person();
person.setName("John");
session.saveOrUpdate(person);
可以将此方法视为一种通用工具,用于使对象持久化,而不管其状态如何,无论是瞬态的还是分离的
处在持久性状态的实例相当于处在暂存区中,对它的所有更改都会传播到数据库
要使处在 瞬态 状态的实例转换至 持久 性状态提供了几种方法:lock(),update(),merge(),saveOrUpdate()
lock() 符合JPA规范
lock() 将 分离 实体重新附加至暂存区
4.2 update()
update() 不符合JPA规范
update() 方法将传递的对象从 分离 状态转换为 持久 状态
将 瞬态 实体传递给此方法,则会引发异常
Person person = new Person();
person.setName("John");
session.update(person); // PersistenceException!
4.2 merge()
merge() 符合JPA规范
merge() 细节:
- 通过从传递的对象获取的 id 查找实体实例(检索持久性上下文中的现有实体实例,或从数据库加载的新实例)
- 将字段从传递的对象复制到此实例
- 返回一个新更新的实例
Person person = new Person();
person.setName("John");
session.save(person);
session.evict(person);
person.setName("Mary");
Person mergedPerson = (Person) session.merge(person);



