2009-09-24 7 views
1

Взгляните на следующие классы (однонаправленный @OneToMany)Hibernate потерял ссылку после вызова save. Ты знаешь почему?

@Entity 
public class Team { 

    private Integer id = -1; 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return this.id; 
    } 

    private List<Player> playerList; 


    @OneToMany 
    @Cascade(CascadeType.SAVE_UPDATE) 
    @JoinColumn(name="TEAM_ID", insertable=false, updateable=false) 
    public List<Player> getPlayerList() { 
     return this.playerList; 
    } 

    public void addPlayer(Player player) { 
     player.setId(new PlayerId(getId(), getPlayerList().size())); 

     playerList.add(player); 
    } 

} 

Уведомление addPlayer: идентификатор команды и TeamID игрока ссылается на тот же экземпляр,

AssertEquals(team.getId(), player.getPlayerId().getTeamId()); 

должны работать, не?

Hibernate не будет сохранять значение -1, потому что я объявил стратегию генератора (по умолчанию для авто). Если генератор идентификатора объявлен, Hibernate выполняет задание значения первичного ключа. Я assined -1 к идентификатору команды ЧТОБЫ ПОДЕЛИТЬСЯ СВОЮ ССЫЛКУ в ид игрока (при вызове addPlayer метода) следующим образом

@Embeddable 
public class PlayerId implements Serializable { 

    private Integer teamId; 

    private Integer playerIndex; 

    // required no-arg constructor 
    public PlayerId() {} 

    public PlayerId(Integer teamId, Integer playerIndex) { 
     this.teamId = teamId; 
     this.playerIndex = playerIndex; 
    } 

    @Column(name="TEAM_ID", nullable=false) 
    public Integer getTeamId() { 
     return this.teamId; 
    } 

    @Column(name="PLAYER_INDEX", nullable=false) 
    public Integer getPlayerIndex() { 
     return this.playerIndex; 
    } 

    // getters and setters 

    public boolean equals(Object o) { 
     if(o == null) 
      return false; 

     if(!(o instanceof PlayerId)) 
      return false; 

     PlayerId other = (PlayerId) o; 
     if(!(getTeamId().equals(other.getTeamId())) 
      return false; 

     if(!(getPlayerIndex().equals(other.getPlayerIndex())) 
      return false; 

     return true; 
    } 

} 

Но когда я называю (Take особого взгляда на addPlayer)

Team team = new Team(); 

Player player = new Player(); 

// teamId property in PlayerId references Team id 
team.addPlayer(player); 

session.save(team); 

И я вижу в базе данных я получаю

PLAYER 
TEAM_ID  PLAYER_INDEX 
-1   0 

TEAM 
ID 
1 

И когда я сравниваю после сохранения

AssertEquals(team.getId(), player.getPLayerId().getTeamId()); // It does not works! why ? 

бревенчатых выходы

INSERT INTO TEAM VALUES() 

// SELECT BEFORE SAVING OR UPDATING WHEN USING A COMPOUND PRIMARY KEY 
SELECT * FROM PLAYER WHERE TEAM_ID = ? AND PLAYER_INDEX = ? 

INSERT INTO PLAYER (TEAM_ID, PLAYER_INDEX) VALUES (?, ?) 

Так что вы знаете, почему Hibernate потерял реф.номер команды в собственности TeamID игрока после сохранения команды и ее игроков?

ответ

1

Я не уверен, что вы подразумеваете под «поддержкой ссылок»? Я тоже не совсем понятно, на что вы пытаетесь сделать здесь ...

Ожидали ли вы Hibernate использовать TEAM_ID вновь созданного Team объекта (например, 1, в данном случае), чтобы вставить Player экземпляров? Если это так, вы специально предотвратили это, указав insertable/updatable как false в объявлении @JoinColumn - вам нужно переместить их в метод getTeamId() в классе Player.

Выясните, что вы пытаетесь достичь здесь?

+0

Hi Chss, добавленный к вопросу. –

+0

Вы не можете «поделиться» ссылкой на Integer. Это неизменно, поэтому, когда значение TeamId изменяется (и оно изменяется Hibernate при сохранении экземпляра команды), создается новый экземпляр Integer. Таким образом, вы получаете «1» в Team.id и свой старый «-1» в PlayerId.teamId. Способ исправить это, как я сказал в своем ответе, - это переместить insertable = "false", updatable = "false" в аннотацию PlayerId.getTeamId(). – ChssPly76

+0

Это не должно быть потому, что это сложный идентификатор (что означает его назначение), и teamId будет установлен (и вставлен/обновлен) по ассоциации. Но я не уверен в этом на 100% - я склонен всегда придерживаться суррогатных ключей, поскольку они представляют гораздо меньшую головную боль; вдвойне для ассоциаций. – ChssPly76