em.persist() 或 em.merge() 是否不需要更新?
Is em.persist() or em.merge() not needed or not for update?
我有下面的代码,想知道 JPA 是如何知道持久化这个更新的。我预计需要 em.merge() 才能执行更新。这真的安全吗?
@Stateless
class User {
...
public void generateRandomNicknames() {
List<UserEntity> users = em.createNamedQuery("UserEntity.getAllUsers", UserEntity.class)
.getResultList();
for (UserEntity user : users) {
user.setNickname(generateRandomNickname());
}
// em.merge(user) or em.persist(user) not needed ?
}
}
简而言之:托管实体通常在事务提交时与数据库同步。 JPA 实现负责跟踪已更改的 managed 实体并更新数据库。在您的情况下,调用 user.setNickname(...)
将通知 JPA 这个特定的用户对象是脏的。事务在调用会话 EJB 的业务方法时默认处于活动状态。
注意以上是可以通过配置更改的默认行为!
更长的故事,参考了 JEE 8 子规范(问题是关于 JEE 6,这些仍然适用,尽管在不同的章节号中):
(JPA 2.1) Section 3.2.4: Synchronization to the Database
The state of persistent entities is synchronized to the database at transaction commit. This synchronization
involves writing to the database any updates to persistent entities and their relationships as specified
above.
[...]The persistence provider runtime is permitted to perform synchronization to the database at other times
as well when a transaction is active and the persistence context is joined to the transaction. The flush
method can be used by the application to force synchronization.
本章还有其他有趣的细节,但请注意 merge()
NOT 必须调用,以便在末尾保存托管实体交易。
这让我们进入下一个细节,即交易。由于这是 Session EJB 的方法,因此在事务上下文中默认为 运行:
(EJB core 3.2) Section 8.3.6: Specification of a Bean’s Transaction Management Type
By default, a session bean or message-driven bean has container managed transaction demarcation if the transaction management type is not specified. [...]
(EJB core 3.2) Section 8.3.7: Specification of the Transaction Attributes for a Bean’s Methods
The Bean Provider of an enterprise bean with container-managed transaction demarcation may specify the transaction attributes for the enterprise bean’s methods. By default, the value of the transaction attribute for a method of a bean with container-managed transaction demarcation is the REQUIRED transaction attribute, and the transaction attribute does not need to be explicitly specified in this case.
一个重要的细节是实体实际上是被管理的。在这种情况下,这是因为它们是从 JPA 本身返回的,并且由于 JPQL 查询 "UserEntity.getAllUsers"
的结构。通常实体可能是非托管或分离的,在这种情况下调用 merge()
或 persist()
是必要的。
我有下面的代码,想知道 JPA 是如何知道持久化这个更新的。我预计需要 em.merge() 才能执行更新。这真的安全吗?
@Stateless
class User {
...
public void generateRandomNicknames() {
List<UserEntity> users = em.createNamedQuery("UserEntity.getAllUsers", UserEntity.class)
.getResultList();
for (UserEntity user : users) {
user.setNickname(generateRandomNickname());
}
// em.merge(user) or em.persist(user) not needed ?
}
}
简而言之:托管实体通常在事务提交时与数据库同步。 JPA 实现负责跟踪已更改的 managed 实体并更新数据库。在您的情况下,调用 user.setNickname(...)
将通知 JPA 这个特定的用户对象是脏的。事务在调用会话 EJB 的业务方法时默认处于活动状态。
注意以上是可以通过配置更改的默认行为!
更长的故事,参考了 JEE 8 子规范(问题是关于 JEE 6,这些仍然适用,尽管在不同的章节号中):
(JPA 2.1) Section 3.2.4: Synchronization to the Database
The state of persistent entities is synchronized to the database at transaction commit. This synchronization involves writing to the database any updates to persistent entities and their relationships as specified above.
[...]The persistence provider runtime is permitted to perform synchronization to the database at other times as well when a transaction is active and the persistence context is joined to the transaction. The flush method can be used by the application to force synchronization.
本章还有其他有趣的细节,但请注意 merge()
NOT 必须调用,以便在末尾保存托管实体交易。
这让我们进入下一个细节,即交易。由于这是 Session EJB 的方法,因此在事务上下文中默认为 运行:
(EJB core 3.2) Section 8.3.6: Specification of a Bean’s Transaction Management Type
By default, a session bean or message-driven bean has container managed transaction demarcation if the transaction management type is not specified. [...]
(EJB core 3.2) Section 8.3.7: Specification of the Transaction Attributes for a Bean’s Methods
The Bean Provider of an enterprise bean with container-managed transaction demarcation may specify the transaction attributes for the enterprise bean’s methods. By default, the value of the transaction attribute for a method of a bean with container-managed transaction demarcation is the REQUIRED transaction attribute, and the transaction attribute does not need to be explicitly specified in this case.
一个重要的细节是实体实际上是被管理的。在这种情况下,这是因为它们是从 JPA 本身返回的,并且由于 JPQL 查询 "UserEntity.getAllUsers"
的结构。通常实体可能是非托管或分离的,在这种情况下调用 merge()
或 persist()
是必要的。