Взгляните на следующие классы (однонаправленный @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 игрока после сохранения команды и ее игроков?
Hi Chss, добавленный к вопросу. –
Вы не можете «поделиться» ссылкой на Integer. Это неизменно, поэтому, когда значение TeamId изменяется (и оно изменяется Hibernate при сохранении экземпляра команды), создается новый экземпляр Integer. Таким образом, вы получаете «1» в Team.id и свой старый «-1» в PlayerId.teamId. Способ исправить это, как я сказал в своем ответе, - это переместить insertable = "false", updatable = "false" в аннотацию PlayerId.getTeamId(). – ChssPly76
Это не должно быть потому, что это сложный идентификатор (что означает его назначение), и teamId будет установлен (и вставлен/обновлен) по ассоциации. Но я не уверен в этом на 100% - я склонен всегда придерживаться суррогатных ключей, поскольку они представляют гораздо меньшую головную боль; вдвойне для ассоциаций. – ChssPly76