我有下面的代码,想知道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 ?
}
}
答案 0 :(得分:2)
简而言之: 受管实体通常在事务提交时与数据库同步。 JPA实现负责跟踪更改的 managed 实体并更新数据库。就您而言,调用user.setNickname(...)
将通知JPA此特定用户对象已损坏。默认情况下,事务在调用会话EJB的业务方法时处于活动状态。
注意,以上是可以通过配置更改的默认行为!
更悠久的故事,并引用了JEE 8子规范(有关JEE 6的问题,尽管适用于不同的章节号,但它们仍然适用):
(JPA 2.1)第3.2.4节:与数据库同步
在事务提交时,持久实体的状态将同步到数据库。这种同步 涉及将对持久性实体及其关系的任何更新写入数据库(如指定) 以上。
[...]允许持久性提供程序运行时在其他时间与数据库执行同步 以及当事务处于活动状态并且持久性上下文已加入到事务中时。同花顺 应用程序可以使用此方法来强制同步。
本章还有其他有趣的细节,但是请注意,merge()
不必不需要调用,以便在事务结束时保存被管理实体。
将我们带入下一个细节,即交易。由于这是会话EJB的一种方法,因此默认情况下,它在事务的上下文中运行:
(EJB核心3.2)第8.3.6节:Bean事务管理类型的规范
默认情况下,如果未指定事务管理类型,则会话Bean或消息驱动的Bean具有容器管理的事务划分。 [...]
(EJB核心3.2)第8.3.7节:Bean方法的事务属性规范
具有容器管理的事务划分的企业Bean的Bean Provider可以为企业Bean的方法指定事务属性。默认情况下,具有容器管理的事务划分的Bean方法的事务属性的值是REQUIRED事务属性,在这种情况下不需要显式指定事务属性。
一个重要的细节是实体是实际管理的。在这种情况下,这是因为它们是从JPA本身返回的,并且是因为JPQL查询"UserEntity.getAllUsers"
的结构如何。通常,实体可能不受管理或分离,在这种情况下,必须调用merge()
或persist()
。