JPA + Hibernate - переподключение сущностей из отношения @OneToMany - PullRequest
4 голосов
/ 17 февраля 2010

Рассмотрим следующий простой пример: В одной команде много игроков, и игрок может принадлежать только одной команде.

@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 (здесь: "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 ]

1 голос
/ 18 февраля 2010

Вы пробовали:

team2.setPlayers(team1.getPlayers();
team1.setPlayers(null);
for (Player player : team2.getPlayers() {
   player.setTeam(team2);
}
0 голосов
/ 18 февраля 2010

Я думаю, что после того, как вы смените команду игроков, вы должны вызвать flush (), затем вызвать refresh () для teamA и затем вызвать remove () для teamA.

0 голосов
/ 17 февраля 2010

Я думаю, что виновником является DELETE_ORPHAN. Из ссылки Аннотации:

DELETE_ORPHAN применяется только к ассоциациям @OneToMany и указывает, что операция delete () / remove () должна применяться к любому дочернему объекту, который удален из ассоциации. Другими словами, если постоянный родительский объект разыменовывает дочерний элемент и если используется DELETE_ORPHAN, «потерянный» дочерний элемент удаляется.

Но это не то, что вы хотите, так как вы «переучиваете» игрока.

0 голосов
/ 17 февраля 2010

Я думаю, что вы должны очистить набор перед вызовом удаления в teamA. Но ты сказал, что пробовал это?

Является ли новая команда настойчивой?

...