问题 1
merge
必须在分离的实体上调用该方法。
- 该
merge
方法将返回附加到 entityManager 的合并对象。
这是什么意思 ?
一旦您用来获取实体的实体管理器关闭,实体就会被分离。(即大部分时间是因为您在之前的交易中获取它)。
在您的第二个代码示例中:用户已附加(因为您只是获取它),因此调用合并是无用的。(顺便说一句:不是getReference
但是find
)
在您的第一个示例中:我们不知道用户的状态(分离实体与否?)。如果它是分离的,调用它是有意义的merge
,但要小心merge
不要修改它作为参数传递的对象。所以这是我的第一个示例版本:
/**
* @param user : a detached entity
* @return : the attached updated entity
**/
public User updateUserName(User user, String name) {
user.setName(name);
user.setChangeDate(new Date());
return em.merge(user);
}
问题2
也许一些代码示例来解释 jpa 处理程序的含义可以帮助我们理解您的担忧。无论如何,我会尽力帮助你。
如果您有一个持久用户并且您需要创建一个新组并将其与持久用户相关联:
User user = em.find(User.class, userId);
Group group = new Group();
...
em.persist(group);
user.addToGroups(group);
group.addToUsers(user); //JPA won't update the other side of the relationship
//so you have to do it by hand OR being aware of that
如果您有一个持久用户和一个持久组,并且您需要将它们关联起来:
User user = em.find(User.class, userId);
Group group = em.find(Group.class, groupId);
...
user.addToGroups(group);
group.addToUsers(user);
一般注意事项
关于所有这一切的最佳实践实际上取决于您管理事务(以及 entityManager 的生命周期)与对象的生命周期。
大多数时候:entityManager 是一个非常短时间的活对象。另一方面,您的业务对象可能存在更长的时间,因此您将不得不调用合并(并注意合并不会修改传入参数的对象!!!)。
您可以决定在同一个事务中获取和修改您的业务对象(即使用同一个 entityManager):这意味着更多的数据库访问,并且出于性能原因,该策略通常必须与二级缓存相结合。但在这种情况下,您不必调用合并。
我希望这会有所帮助。