我有Principal和PrincipalRoles实体类。它们具有如下定义的双向“父子”关系:
校长有:
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, orphanRemoval = true, mappedBy = "principal")
Collection<PrincipalRoles> rolesByPrincipalCollection;
PrincipalRoles具有:
@JoinColumn(name = "principal", referencedColumnName = "id", nullable = false, insertable = true, updatable = true, unique = false)
@ManyToOne(fetch = FetchType.LAZY)
Principal principal;
我还在 Java EE 应用程序的 Web 模块中有一个主从网页。该页面使用应用程序的 EJB 模块中包含的实体类及其对应的外观。
该页面获取Principal对象,然后使用无状态 EJB 的方法PrincipalFacadeBean对其进行更新,该方法基本上执行实体管理器的查找和合并方法。持久性上下文是容器管理的。
该页面可以添加和删除多个PrincipalRoles,然后成功合并Principal。它还可以添加和删除几个PrincipalRoles,更新之前添加的一个,然后合并Principal;但是当尝试在单个合并操作中更新多个时它总是失败。在这些情况下,不会引发异常,但不会在数据库中更新任何内容。甚至没有Principal的其他字段,例如姓名、电子邮件等。
该应用程序在 GlassFish 5.1.0、Java 1.8.0_281、EclipseLink 2.7.4、PostgreSQL 13 上运行。
我已经处理这个问题几天了,我的想法已经不多了。您能提供的任何帮助将不胜感激。
回答@crizzis问题的附录:
我不确定服务方法是什么。页面 bean 直接使用此方法调用外观:
@Override
public List<Principal> merge(List<Principal> list) {
return principalFacade.merge(list);
}
在主从页面中,列表仅包含主页面。这是外观的合并方法:
@Override
public List<Principal> merge(List<Principal> list) {
List<Principal> m = new ArrayList<>();
for (Principal o : list) {
m.add(_manager.merge(o));
}
return m;
}
这些是PrincipalRolesequals
的和hashCode
方法。实际上,这些方法在所有实体类中都有相同的模板。
@Override
public boolean equals(Object obj) {
if (obj instanceof PrincipalRoles) {
PrincipalRoles that = (PrincipalRoles) obj;
return that == this || ObjUtils.equals(id, that.id);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
这是ObjUtils.equals
:
public static boolean equals(Object a, Object b) {
return (a == b) || (a == null && b == null) || (a != null && b != null && a.equals(b));
}
更新后的PrincipalRoles的主要字段是被合并的Principal对象(至少是它们的匹配项)。我还检查了未修改的PrincipalRoles的值。那是。System.identityHashCode
null