在hibernate/jpa最佳实践问题中将分离的或新的实体与现有实体合并

D P*_*sin 10 java persistence design-patterns hibernate jpa

当业务层创建一个新实体时,逻辑上表示应该更新的现有实体的实例(比如它们共享相同的业务键),这种合并错误做法的方法是什么?

public User add(User user){

    User existingUser = getUserDao().findByBusinessKey(user.getBusinessKey(), false);
    user.setId(existingUser.getId());

    user = getUserDao().merge(user);

    return user;
}
Run Code Online (Sandbox Code Playgroud)

我问,因为在分离的实体上显式设置ID对我来说感觉很奇怪,但即使User实体的equals和hashcode方法被适当地实现,在这里设置ID是确保合并发生的唯一方法.

有更好的做法吗?

这种方法有什么特殊的缺点,以后会咬我吗?

谢谢参观!

Jos*_*vis 3

该代码可以工作,但不需要在分离的实体上显式设置 ID。典型的 Hibernate 应用程序有一个“保存”方法,可以处理两种情况:

  1. 用户想要创建一个新的 User,因此应用程序创建一个 ID 为“null”的 User 对象。
  2. 用户查询用户列表,并选择一个进行编辑。在这种情况下,应用程序会执行查询并将对象传播到“保存”方法。该对象将有一个 ID,代码将对其应用新值。

看起来您的代码中的某些内容没有以典型的方式执行第二种情况。如果“用户”对象来自某个先​​前的 Hibernate 查询(由用户单击“编辑用户”或类似的操作触发),那么它已经有一个 ID。因此,只merge(user)需要调用即可。

我通常会做这样的事情:

if (user.getId() == null)
  em.persist(user);
else
  user = em.merge(user);
Run Code Online (Sandbox Code Playgroud)

然后,我添加代码来处理乐观锁定问题(另一个会话更新了对象)和唯一约束问题(另一个会话尝试使用相同的业务密钥保留某些内容)。

像 Seam 这样的框架可以使这一切变得更加简单,因为它们在控制器 bean 方法之间传播 Hibernate 会话。所以甚至不需要“合并”。