开发者

JPA+Hibernate - Reconnecting entities from a @OneToMany relationship

Consider the following simple example: One team has many players and a player may only belong to one team.

@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;

}

What I want to achive is moving all players of team A to team B and delete team A afterwards. I do a loop over the players from team A and set their team to team B (here: "this"):

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

The flush is done after that (autoflush), but I also tried to flush before teamA.remove(). This code runs without an error, but afterwards the players from team A are removed from my datasource due to the cascade configuration, as teamA.remove() leads to the removal of all players from team A.

I wonder why they are still associated with team A, becaus开发者_开发百科e I also tried (and checked in the debugger) to remove all players from the Set, so when teamA.remove() is called, the set is empty. The exceptions thrown in those cases either stated "deleted entity passed to persist" or "detached entity passed to persist". It does work of course, if I create a new transient player, copy all properties and .persist().

How to do this by simply "relinking" the relationship?


Have you tried:

team2.setPlayers(team1.getPlayers();
team1.setPlayers(null);
for (Player player : team2.getPlayers() {
   player.setTeam(team2);
}


I think you have to empty the set before calling remove on teamA. But you said you tried that?

Is the new team a persisted entiy?


I think the culprit is the DELETE_ORPHAN. From the Annotations reference:

DELETE_ORPHAN applies only to @OneToMany associations, and indicates that the delete()/remove() operation should be applied to any child object that is removed from the association. In other words, if a child is dereferenced by a persistent parent and if DELETE_ORPHAN is used, the "orphaned" child is deleted.

But this isn't what you want since you're "reparenting" the Player.


I think that after you change the team of the players, you should call flush(), then call refresh() on teamA and then call remove() on teamA.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜