4

考虑以下简单示例:一支球队有很多球员,而一名球员可能只属于一支球队。

@Entity
public class Team {

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
    @Cascade({  org.hibernate.annotations.CascadeType.ALL,
                org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    private Set<Player> player = new HashSet<Player>();

}

@Entity
public class Player {

    @NotNull
    @ManyToOne(targetEntity = Team.class)
    @JoinColumn(name = "team_id")
    private Team team;

}

我想要实现的是将 A 队的所有球员转移到 B 队,然后删除 A 队。我对 A 队的球员进行循环,并将他们的球队设置为 B 队(这里:“this”):

Iterator<Player> iterator = teamA.getPlayer().iterator();
while(iterator.hasNext()){
 Player player = iterator.next();
 player.setTeam(this);
    player.merge();
}
teamA.remove();

之后完成刷新(自动刷新),但我也尝试在 teamA.remove() 之前刷新。此代码运行没有错误,但之后由于级联配置,来自我的数据源的 A 队的球员被删除,因为 teamA.remove() 导致从 A 队的所有球员被删除。

我想知道为什么他们仍然与团队 A 相关联,因为我也尝试(并在调试器中检查)从集合中删除所有玩家,所以当调用 teamA.remove() 时,集合是空的。在这些情况下抛出的异常要么说明“已删除的实体传递给持久化”,要么是“分离的实体传递给持久化”。当然,如果我创建一个新的瞬态播放器,复制所有属性和 .persist(),它确实有效。

如何通过简单地“重新链接”关系来做到这一点?

4

4 回答 4

1

你有没有尝试过:

team2.setPlayers(team1.getPlayers();
team1.setPlayers(null);
for (Player player : team2.getPlayers() {
   player.setTeam(team2);
}
于 2010-02-18T06:43:09.763 回答
0

我认为您必须先清空集合,然后再调用teamA 上的remove。但是你说你试过了?

新团队是一个持久的实体吗?

于 2010-02-17T17:48:08.093 回答
0

我认为罪魁祸首是DELETE_ORPHAN。从注释参考:

DELETE_ORPHAN 仅适用于 @OneToMany 关联,并指示 delete()/remove() 操作应应用于从关联中删除的任何子对象。换句话说,如果一个孩子被一个持久的父母取消引用并且如果使用了 DELETE_ORPHAN,那么“孤立”的孩子将被删除。

但这不是您想要的,因为您正在“重新养育”播放器。

于 2010-02-17T18:08:52.167 回答
0

我认为在你改变球员的球队之后,你应该调用flush(),然后在teamA上调用refresh(),然后在teamA上调用remove()。

于 2010-02-18T06:51:40.883 回答