【问题标题】:Problem with OneToMany mapping and updates/deletesOneToMany 映射和更新/删除问题
【发布时间】:2019-08-13 22:34:18
【问题描述】:

在连接到 Postgres 11 数据库的 Wildfly 14.0.1 中运行我们的应用程序。

我有两个实体定义如下:

@Entity
@IdClass(WorkingSetEntryId.class)
public class WorkingSetEntry implements Serializable {
    @Id
    private String workingsetname;
    @Id
    private String handlename;
    @Id
    private String workingsettype;
    private Long handleid;
    ...
}

@Entity
@IdClass(WorkingSetId.class)
@Table(name="WORKINGSET")
public class WorkingSetDTO implements Comparable<WorkingSetDTO>, Serializable
{
   @Id
   private String name;
   @Id
   private String type;

   @OneToMany(cascade = {CascadeType.ALL}, fetch= FetchType.EAGER)
   @JoinColumns({
           @JoinColumn(name="workingsetname", referencedColumnName = "name"),
           @JoinColumn(name="workingsettype", referencedColumnName = "type")
   })
   private List<WorkingSetEntry> entries;
   ...
}

在检索数据时,它工作得非常好。父母和孩子的所有字段都填写了。

但是,当我尝试以下操作时:

     EntityManager em = emf.createEntityManager();
     WorkingSetDTO ws = em.createNamedQuery("WorkingSetDTO.findByNameAndType", WorkingSetDTO.class)
                .setParameter("name", wsId)
                .setParameter("type", wsType)
                .getSingleResult();
     em.remove(ws);

我收到以下错误:

Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "workingsetname" violates not-null constraint
  Detail: Failing row contains (null, null, DV_POSTBURN_SCS_SIDEA, 0).
    at org.postgresql@42.2.5//org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
    at org.postgresql@42.2.5//org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
    at org.postgresql@42.2.5//org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
    at org.postgresql@42.2.5//org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
    at org.postgresql@42.2.5//org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
    at org.postgresql@42.2.5//org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143)
    at org.postgresql@42.2.5//org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:120)
    at org.jboss.ironjacamar.jdbcadapters@1.4.11.Final//org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
    at org.hibernate@5.3.6.Final//org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
    ... 132 more

我也无法使用以下代码更新实体:

     EntityManager em = emf.createEntityManager();
     WorkingSetDTO ws = em.createNamedQuery("WorkingSetDTO.findByNameAndType", WorkingSetDTO.class)
                .setParameter("name", wsId)
                .setParameter("type", wsType)
                .getSingleResult();
     List<WorkingSetEntry> curEntries = current.getEntries();
     List<WorkingSetEntry> newEntries = workingSet.getEntries();
     curEntries.removeIf(e -> !newEntries.contains(e));
     curEntries.addAll(newEntries.stream().filter(e -> !curEntries.contains(e)).collect(Collectors.toList()));

没有以下错误:

EntityExistsException: A different object with the same identifier value was already associated with the session : [com.rsc.mmpl.dto.workingset.WorkingSetEntry#com.rsc.mmpl.dto.workingset.WorkingSetEntryId@5dbced55]

所以很明显,即使是这样的基本实体,我也做错了。我有其他实体工作得非常好,但它们只有一个 ID 字段与之关联,所以我猜这是我对具有多个字段 ID 的表的误解。

任何建议/指针/帮助将不胜感激。我总是可以为每个实体生成一个新的单一 ID,但我试图尽可能多地重用现有代码而不进行架构更新等。

谢谢!

【问题讨论】:

    标签: jakarta-ee jpa-2.1


    【解决方案1】:

    我最终解决了这个问题,只需生成一个 ID 并将其填充给孩子们,一旦持续存在,就可以正常工作。我还稍微修复了列表更新,以确保我 EntityManager.remove 不再是列表一部分的子项,而不是仅将它们从父项中删除。

    我仍然很好奇为什么在使用 JoinColumns 对父级执行 remove() 后会导致空更新。我有一些其他实体也在做同样的事情,但现在只是更简单地使用删除语句,或者创建一个新的 ID 列并远离代码当前拥有的所有多字段 ID 和 JoinColumns。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      相关资源
      最近更新 更多