0

我有PrincipalPrincipalRoles实体类。它们具有如下定义的双向“父子”关系:

校长有:

@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.identityHashCodenull

4

1 回答 1

0

我所要做的就是将PrincipalRoles@ManyToOne的字段从更改为。我仍然不明白为什么,但它有效!再次感谢@crizzis 和@Chris。他们的问题让我找到了答案。principal@ManyToOne(fetch = FetchType.LAZY)@ManyToOne(fetch = FetchType.EAGER)

于 2021-04-05T18:48:53.627 回答