【问题标题】:How to delete a @ManyToMany association (joined link) without deleting the actual target entity如何在不删除实际目标实体的情况下删除 @ManyToMany 关联(加入链接)
【发布时间】:2015-04-05 07:42:21
【问题描述】:

我正在开发一个 Spring-MVC 应用程序,其中包含多对多映射。有3张表,一张是GroupAccount、memberjunction、GroupMembers。现在,当我删除 groupMember 时,我只想从 GroupMembers 和与 memberId 对应的 memberjunction 中删除条目。我尝试使用 Cascade.Remove,它也导致 GroupAccount 中的删除。我正在发布我的 sql 代码,以及我到目前为止所拥有的。

SQL 代码:

CREATE TABLE groupaccount
(
  groupid numeric NOT NULL,
  groupname character varying,
  adminusername character varying,
  CONSTRAINT groupid PRIMARY KEY (groupid)
)
CREATE TABLE memberjunction
(
  memberid integer NOT NULL,
  groupid numeric NOT NULL,
  CONSTRAINT membergroupid PRIMARY KEY (memberid, groupid),
  CONSTRAINT groupaccount_memberjunction_fk FOREIGN KEY (groupid)
      REFERENCES groupaccount (groupid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT groupmembers_memberjunction_fk FOREIGN KEY (memberid)
      REFERENCES groupmembers (memberid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
CREATE TABLE groupmembers
(
  memberid integer NOT NULL,
  musername character varying,
  accesslevel boolean DEFAULT true,
  CONSTRAINT memberid PRIMARY KEY (memberid)
)

GroupMembersDAOImpl 删除方法:

@Override
public boolean removeGroupMember(int memberId) {
    session = sessionFactory.getCurrentSession();
    GroupMembers groupMembers = (GroupMembers) session.get(GroupMembers.class, memberId);
    if(!(groupMembers == null)){
        groupMembers.getGroupAccounts().clear();
        session.flush();
        session.delete(groupMembers);
        return true;
    } else {
        return false;
    }
}

GroupAccount 实体:

@Entity
@Table(name="groupaccount")
public class GroupAccount {
 @Id
    @Column(name="groupid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "groupaccount_seq_gen")
    @SequenceGenerator(name = "groupaccount_seq_gen",sequenceName = "groupaccount_seq")
    private Long groupId;
 @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "memberjunction", joinColumns = {@JoinColumn(name = "groupid")},
                inverseJoinColumns = {@JoinColumn(name = "memberid")})
    private Set<GroupMembers> groupMembersSet = new HashSet<>();

    public void setGroupMembersSet(Set<GroupMembers> groupMembersSet){
        this.groupMembersSet = groupMembersSet;
    }

    public Set<GroupMembers> getGroupMembersSet(){
        return this.groupMembersSet;
    }
}

GroupMembers 实体:

@Entity
@Table(name="groupmembers")
public class GroupMembers {

 @Id
    @Column(name="memberid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "groupmembers_seq_gen")
    @SequenceGenerator(name = "groupmembers_seq_gen",sequenceName = "groupmembers_seq")
    private int memberid;
 @ManyToMany(mappedBy = "groupMembersSet")
    private Set<GroupAccount> groupAccounts = new HashSet<>();

    public void setGroupAccounts(Set<GroupAccount> groupAccounts){
        this.groupAccounts = groupAccounts;
    }

    public Set<GroupAccount> getGroupAccounts(){
        return this.groupAccounts;
    }
}

最新错误日志:

org.postgresql.util.PSQLException: ERROR: update or delete on table "groupmembers" violates foreign key constraint "groupmembers_memberjunction_fk" on table "memberjunction"
  Detail: Key (memberid)=(2501) is still referenced from table "memberjunction".
    org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
    org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)

上面的方法不起作用,正如它所说,有对memberJunction的引用。我如何也可以查询 memberJunction 并删除与 memberId 对应的条目。你能帮忙的话,我会很高兴。非常感谢.. :-)

【问题讨论】:

  • 您还需要添加实体映射。
  • @VladMihalcea : 实体添加... :-) 请告诉我.. :-)

标签: java spring hibernate jpa hibernate-mapping


【解决方案1】:

您需要执行以下操作:

for(GroupAccount groupAccount : groupMembers.getGroupAccounts()) {
    groupAccount.getGroupMembersSet().remove(this);
}
groupMembers.getGroupAccounts().clear();
session.flush();
session.delete(groupMembers);

因为您有一个@ManyToMany 关联,所以关联表在运行时不可用。为此,您可以:

  1. 在删除 GroupMembers 之前,从 GroupMembers 中清除 GroupAccounts。确保您刷新,以便确保删除操作doesn't prevent 对可删除实体状态进行更新。

  2. 您可以将@ManyToMany 替换为@OneToMany 关联到MemberJunction 实体(其PK/@Id 是从GroupMembersGroupAccount 构建的)。这样,您可以将删除从GroupMembers 级联到MemberJunction mappedBy Set,因为它会删除关联表行,而不是实际的GroupAccount 实体。

【讨论】:

  • 感谢您的帮助。它没有用。我正在使用更新的代码和错误日志更新我的帖子。非常感谢。 :-)
  • 检查我更新的答案。您应该设置关联的两侧,这意味着您必须从 GroupAccount 实例中删除可删除的 GroupMembers。
  • 我使用了你更新的答案,不幸的是,同样的错误。您是否需要我发布一些代码,但它与您编写的相同。
  • 您需要确保从当前会话中附加的所有实体中删除 GroupMember。它也可以在其他一些实体中。这就是您收到此错误的原因。
  • GroupMember 的唯一关联是关联表。我确定了这一点以进行测试。错误说同样,实体仍然从 memberJunction 引用。有什么想法吗?
猜你喜欢
  • 2021-04-04
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
相关资源
最近更新 更多