5

私は次の非常に単純な1対多の関係を持っています:

チームには選手のセットがあります:

@Entity(name = "TEAM")
@Access(AccessType.PROPERTY)
public class Team{
    private Integer id;
    private String name;
    private Set<Player> players ;

    @Id
    @Column(name = "id")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "team_name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(cascade = {CascadeType.ALL},orphanRemoval=true)
    @JoinColumn(name = "TEAM_ID")
    public Set<Player> getPlayers() {
        return players;
    }

    public void setPlayers(Set<Player> players) {
        this.players = players;
    }       
}

また、各プレイヤーには固有の ID と名前があります。

@Entity(name = "PLAYER")
@Access(AccessType.PROPERTY)
public class Player implements Serializable{

    private int id;
    private String name;

    @Id
    @Column(name = "id")
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "player_name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
    return id == ((Player)obj).id;
    }
    @Override
    public int hashCode() {
        return id;
    }
}

私は非常に単純なコードを実行します:

Team team = createTeam(3) // creates team with 3 players ids={1,2,3}
session.saveOrUpdate(team);
...

private Team createTeam(int players) {
    Team team = new Team();
    team.setName("Bears");
    team.setId(1);
    for(int i=1 ; i<=players; ++ i){
        Player player = new Player();
        player.setId(i);
        player.setName("Player"+i);
        team.addPlayer(player);
    }
    return team;
}

そして、期待どおりに次の結果が得られます。

  • 休止状態: TEAM team_ から team2_0_ として team_.id、team_.team_name を選択します。ここで team_.id=?
  • 休止状態: PLAYER player_ から player_.id、player_.player_name を player2_1_ として選択します。ここで、player_.id=?
  • 休止状態: PLAYER player_ から player_.id、player_.player_name を player2_1_ として選択します。ここで、player_.id=?
  • 休止状態: PLAYER player_ から player_.id、player_.player_name を player2_1_ として選択します。ここで、player_.id=?
  • Hibernate: TEAM (team_name, id) 値 (?, ?) に挿入
  • Hibernate: PLAYER (player_name, id) 値 (?, ?) に挿入
  • Hibernate: PLAYER (player_name, id) 値 (?, ?) に挿入
  • Hibernate: PLAYER (player_name, id) 値 (?, ?) に挿入
  • 休止状態: PLAYER セット TEAM_ID=? を更新します。id=? 休止状態: PLAYER セット TEAM_ID=? を更新します。id=? 休止状態: PLAYER セット TEAM_ID=? を更新します。id=?

その後、私は次のことを行います。

Team team = createTeam(2) // creates team with 2 player ids={1,2}
session.saveOrUpdate(team);

孤立したプレイヤーが削除されることを期待していますが、次のようになります。

  • 休止状態: TEAM team_ から team2_0_ として team_.id、team_.team_name を選択します。ここで team_.id=?
  • 休止状態: PLAYER player_ から player_.id、player_.player_name を player2_1_ として選択します。ここで、player_.id=?
  • 休止状態: PLAYER player_ から player_.id、player_.player_name を player2_1_ として選択します。ここで、player_.id=?
  • Hibernate: update PLAYER set TEAM_ID=null where TEAM_ID=?
  • 休止状態: PLAYER セット TEAM_ID=? を更新します。id=?
  • 休止状態: PLAYER セット TEAM_ID=? を更新します。id=?

孤立したプレーヤー (id = 3) が切断されたままになりますが、削除されません...私が間違っているアイデアはありますか?

4

3 に答える 3

3

プレイヤーを孤立削除として削除したい場合は、プレイヤーがチームへの参照を失い、チームを保存する必要があります。

あなたがしていることは次のとおりです。

  • 新しいオブジェクト チームを作成します。
  • 3 人のプレーヤーでチームを養う
  • しつこい

その後、各プレーヤーの行には、チーム (id=1) への FK が含まれます。

次に、コードは同じ ID で新しいチームを作成し、2 人のプレーヤーにフィードして永続化します。

その時点で、チーム 1 を参照する DB にはまだプレイヤーが存在します。

私の POV から、すべての異なるビジネス オブジェクトは独自のビジネス キーを持つ必要があります。チーム 1 のプレーヤーを上書きする場合は、最初に id = 1 のチームを取得してから、プレーヤーにフィードする必要があります。

private Team createTeam(int players) {
    Team team = session.get(Team.class, 1);
    if (team == null) {
       team = new Team();
       team.setName("Bears");
       team.setId(1);
    }
    team.clearPlayers();

    for(int i=1 ; i<=players; ++ i){
        Player player = new Player();
        player.setId(i);
        player.setName("Player"+i);
        team.addPlayer(player);
    }
    return team;
}

// Team.java
private void clearPlayers() {
   players.clear();
}

ところで、別のアドバイス。プレーヤーを直接変更することを許可しないでください。これにより、「コレクションへの参照を変更しないでください...」などの HibernateErrors が発生する可能性があります。setPlayers() の代わりに、addPlayer()およびのメソッドを追加します。removePlayer()

private void adddPlayer(Player player) {
   player.setTeam(this);
   players.add(player);
}

private void removePlayer(Player player) {
   player.setTeam(null);
   players.remove(player);
}

また、コレクションは可変であるため、getPlayers() で変更不可能なコレクションを返すようにします。

private Set<Player> getPlayers() {
   return Collections.unmodifiableSet(players);
}

これがいくつかの光を当てることを願っています:)

于 2012-10-03T21:09:28.847 に答える
1

このタグを使用できます: @org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)。したがって、次のようになります。

@OneToMany(cascade = {CascadeType.ALL},orphanRemoval=true) @org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @JoinColumn(name = "TEAM_ID")

于 2013-04-23T14:40:11.157 に答える
0

両方のエンティティの関係にmappedBy属性を追加します。

プレーヤーにチームを追加します。

// in Player.java
@ManyToOne(mappedBy="players")
private Team team;

そしてPlayerのMappeedBy。

//In Team.java
@OneToMany(cascade = {CascadeType.ALL},orphanRemoval=true,mappedBy="team")
    @JoinColumn(name = "TEAM_ID")
    public Set<Player> getPlayers() {
        return players;
    }

1対Mの関係にある場合、子には親の参照が必要です。次に、hibernateは内部で親のIDを子テーブルの外部として使用します。

子テーブルには次の3つの列があります。

id , player_name,team_id
于 2012-09-27T12:28:40.917 に答える