使用JPA和Hibernate实现状态转换的初学者指南
介绍
Hibernate将开发人员的思维方式从SQL语句转移到实体状态转换。一旦Hibernate主动管理实体,所有更改将自动传播到数据库。
操作域模型实体(及其关联)比编写和维护SQL语句容易得多。如果没有ORM工具,添加新列需要修改所有关联的INSERT / UPDATE语句。
但Hibernate也不是银弹。Hibernate并没有让我们免于担心实际执行的SQL语句。控制Hibernate并不像人们想象的那么简单,并且必须检查 Hibernate代表我们执行的所有SQL语句。
该实体表示
正如我之前提到的,Hibernate监视当前附加的实体。但是对于要管理的实体,它必须处于正确的实体状态。
首先,我们必须定义所有实体状态:
-
新(瞬态)
尚未与Hibernate会话(也称为持久性上下文)关联且未映射到任何数据库表行的新创建的对象被视为处于新(暂停)状态。
要成为持久化,我们需要显式调用EntityManager#persist方法或使用传递持久性机制。
-
持久性(管理)
一个持久的实体已经与数据库表行相关联,它由当前运行管理的持久化上下文。对此类实体所做的任何更改都将被检测并传播到数据库(在会话刷新时间内)。使用Hibernate,我们不再需要执行INSERT / UPDATE / DELETE语句。Hibernate采用事务性后写工作方式,并且在当前会话刷新时间的最后一个负责时刻同步更改。
-
超脱
一旦当前运行的持久性上下文关闭,所有先前管理的实体都将分离。将不再跟踪连续更改,也不会发生自动数据库同步。
要将分离的实体与活动的Hibernate会话相关联,您可以选择以下选项之一:
-
重新连接
Hibernate(但不是JPA 2.1)支持通过Session#update方法重新附加。
一个Hibernate的Session可以只有一个关联实体对于给定的数据库行对象。这是因为持久性上下文充当内存缓存(第一级缓存),并且只有一个值(实体)与给定**(实体类型和数据库标识符)相关联。
仅当没有与当前Hibernate会话关联的其他JVM对象(匹配相同的数据库行)时,才能重新附加实体。
-
合并
该合并operaration是要拷贝脱离实体状态(源)到一个管理实体实例(目标)。如果合并实体在当前会话中没有等效项,则将从数据库中获取一个。
该分离的对象实例将继续,甚至合并操作后仍保持分离。
-
重新连接
-
删除
尽管JPA要求仅允许删除托管实体,但Hibernate还可以删除分离的实体(但只能通过Session#delete方法调用)。
删除的实体仅计划删除,实际的数据库DELETE语句将在会话刷新时执行。
实体状态转换
要更改一个实体状态,我们需要使用以下实体管理接口之一:
- EntityManager
- Session