0

我有

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public Linf getLinf() {
    return linf;
}

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = MessageEntry.class)
public Set<MessageEntry> getMessageEntries() {
    return messageEntries;
}

我需要从数据库中删除单个 messageEntry。如果我说 sess.delete(messageEntry),那么我会得到索引异常,因为它在 Linf.messageEntries 集合中。无状态会话无法加载集合,因此我必须手动加载 Linf.messageEntries 的元素,然后删除其中一个:

            List linfs = sess.createQuery(
                    "SELECT l FROM Linf l " +
                            "JOIN l.messageEntries e WHERE e=:e")
                    .setParameter("e", messageEntry).list();

            if (linfs.size()>1) throw new RuntimeException();

            Linf linf = (Linf) linfs.get(0);

            List<MessageEntry> curEntries =
                    sess.createQuery(
                            "SELECT e FROM Linf l " +
                            "JOIN l.messageEntries e WHERE l=:l")
                            .setParameter("l", linf).list();

            for (int i = 0; i < curEntries.size(); i++) {
                if (curEntries.get(i).getId().equals(messageEntry.getId())) {
                    curEntries.remove(i);
                    break;
                }
            }

            Set<MessageEntry> cur = new HashSet<MessageEntry>();
            cur.addAll(curEntries);
            linf.setMessageEntries(cur);

            messageEntry.setLinf(null);
            sess.update(messageEntry);
            sess.update(linf);
            sess.delete(messageEntry);

我得到 ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint failed ( db. linf_messageentry, CONSTRAINT FK5039A8B5E770809AFOREIGN KEY ( messageEntries_id) REFERENCES messageentry( id))。我该如何执行此任务?谢谢你。

4

1 回答 1

1

你的映射是错误的。与使用 MessageEntry 中的外键的双向一对多关联不同,您拥有使用连接表 ( linf_messageentry) 的 OneToMany 关联,以及使用外键的另一个不同的 ManyToOne 关联。

mappedBy必须使用以下属性将一侧标记为多侧的倒数:

// This is the owner side of the association, because it doesn't have 
// the mappedBy attribute.
// it uses a join column by default
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public Linf getLinf() {
    return linf;
}

// This is the inverse side, because it has the mappedBy attribute
// since it's mappedBy linf, hibernate uses the same mapping as the one
// described on the linf property: a join column
@OneToMany(mappedBy = "linf", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public Set<MessageEntry> getMessageEntries() {
    return messageEntries;
}

另外,请注意:

  • targetEntity属性是完全多余的:Hibernate 从集合的类型中知道目标实体:Set<MessageEntry>
  • ManyToOne 上的 cascade = CascadeType.ALL 没有多大意义。如果你删除一个 MessageEntry,你不希望它的 Linf 被删除。
于 2012-12-02T13:56:40.293 回答