如果你也不是太理解Hibernate 什么时候要save,什么时候要用update,merge,什么时候可以直接set一下字段就能够将实体类存储到数据库中,这篇文章或许能解开你的迷雾。本文翻译自《A beginner’s guide to JPA/Hibernate entity state transitions

引言

Hibernate帮助开发者的将SQL语句的转变成了实体类的状态转变。一旦Hibernate存储了一个实体类,它的所有变化都将会自动传播到数据库中。
管理领域模型实体类以及他们的关联关系比写SQL语句管理SQL语句来说简单多了。如果没有Hibernate这样的ORM工具,增加一个字段会需要改写所有关联的 INSERT/UPDATE语句。
但是Hibernate也并不是银弹。Hibernate也不能让我们完全不关心所最终执行的SQL语句。完全的掌握Hibernate也不是我们所想的那么简单直接,我们有时候也需要亲自检查所产生的SQL语句。

实体类状态

如之前所说,Hibernate监管了当前存储着的实体类。但是在一个实体类要被存储下来,我们需要知道它处于什么状态。
首先我们必须定义所有实体类状态:

New(Transient)瞬态

一个新创建的对象,在还没有进入Hibernate Session(也即持久化上下文),同时没有域数据库表中的行对应起来时的状态称为瞬态。
想要对处于这个状态的对象进行持久化,我们需要明确的执行EnittyManager的persist或者使用是实体类持久化的传播机制(CasCade)。

Persistent(Managed)持久态

持久态的实体类已经和数据表中的行关联起来,并且被当前的持久化上下文所管理。所有该实体类的变化都会被检测到然后在事务flush的时候,将这些变化存储到数据库中。有了Hibernate,我们就不在需要执行增删改查的SQL语句。Hibernate使用了Transactional write-behind的工作方式。在当前事务flush时间的最后一个将实体类的改变同步到数据库中。

detached 分离态

一旦当前的跑着的事务关闭,所有当前状态下管理着的实体类就编程了分离太。后续的实体类中的变化将不会被检测到,并且也不会和自动和数据库去同步。
如果想在一个当前事务关联一个将分离态的实体类,你可以选着下面的几种方式:

  • Reattaching(重新关联)
    Hibernate支持通过Session的update方法来重新关联实体类。

  • Merging
    合并操作会将分离态的实体类(源头)拷贝一份给到持久太的实体类(目标)。如果持久化的实体类在当前事务中不存在,那么就回去数据库中查一份。
    但是分类态的实体类(源头人就会保持分离态)。

removed 删除态

尽管JPA需要只有持久态的实体类才能够被删除,hibernate通用可以通过Session的delete方法删除分离态的实体类。

实体类状态转换

想要改变一个实体类的状态,我们需要使用下面之中的实体类管理接口:

  • EntityManager


*Session

总结

以上这些接口是我们在实体类状态转变时候需要明确调用的,这些调用通知hibernate在事务刷新的时候将这些变换转换成SQL语句,最终去操作数据库。