【发布时间】:2018-03-19 22:16:19
【问题描述】:
我正在使用 Spring Data JPA 并拥有 Player、Score 实体。 Player 与 Score 具有 @OneToMany 关系(以及从 Score 到 Player 的 @ManyToOne)。我将Player 保存到数据库中而不指定相关分数。之后,我将Score 保存到数据库中,将指向Player 的链接传递给构造函数。然后在同一个函数中,我读取了Player 条目,但它还没有指向Score 条目的链接。
我的OneToMany 关系中有FetchType.LAZY,所以我需要在该函数中使用注释@Transactional。我还尝试在内部事务中保存玩家和分数(使用propogation=Propogation.REQUIRES_NEW)并在外部事务中读取玩家条目,但这没有帮助。我还尝试添加CascadeType.ALL - 没有效果。我使用了来自JpaRepository 的flush() 方法 - 也没有帮助。
但是,如果我将播放器和得分保存在一个控制器方法中(使用 spring MVC),然后读入另一个,播放器将有一个指向得分的链接。
编辑:添加代码,得分代码是 GamePlayerScore。所有类都有lombok注解@Getter和@ToString。
播放器
@Temporal(TemporalType.DATE)
@NonNull
@Column(updatable = false)
private Date createdAt;
@Setter
@NonNull
@Column(unique = true)
private String nickname;
@OneToMany(mappedBy = "winner", cascade = CascadeType.REFRESH)
private Set<GameStatistic> gamesWon;
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.REFRESH}, optional = false)
@JoinColumn
private PlayerStatistic stat;
@OneToMany(mappedBy = "player", cascade = CascadeType.REFRESH)
private Set<GamePlayerScore> scores;
@ManyToOne
@JoinColumn
private Game currentGame;
public Player(String nickname, Date createdAt) {
this.nickname = nickname;
this.createdAt = createdAt;
stat = new PlayerStatistic(0, 0, 0, this);
}
GamePlayerScore
@ManyToOne(optional = false)
@JoinColumn
@NonNull
@JsonIgnore
private GameStatistic game;
@ManyToOne(optional = false)
@JoinColumn
@NonNull
@JsonIgnore
private Player player;
@NonNull
private Integer score;
@PrePersist
private void updatePlayerStat() {
player.getStat().incrementTotalGames();
player.getStat().addTotalScore(score);
}
游戏统计
@Column(updatable = false)
@NonNull
private Integer durationMinutes;
@Temporal(TemporalType.TIMESTAMP)
@NonNull
private Date startedAt;
@ManyToOne(optional = false)
@JoinColumn
@NonNull
@JsonIgnore
private Player winner;
@OneToMany(mappedBy = "game")
private Set<GamePlayerScore> scores;
@PrePersist
private void update() {
winner.getStat().incrementTotalWins();
}
以及我如何存储条目
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void prepossess() {
Date date = new Date();
Player john = new Player("john", date);
GameStatistic game = new GameStatistic(35, new Date(), john);
GamePlayerScore johnScore = new GamePlayerScore(game, john, 100);
playerRepository.save(player);
gameRepository.save(game);
scoreRepository.save(johnScore);
}
以及我如何阅读条目
@Transactional
public void insertAndRead() {
preprocess();
Player player = playerRepository.findByNickname("john");
System.out.println(player.getScores());
}
【问题讨论】:
-
请发布
Player和Score类的代码以及您尝试持久化它们的方式。将其作为散文阅读时,真的很难理解发生了什么。此外,所需的确切注释等重要细节也很容易丢失。 -
好的,我添加了代码
-
解决的关键是重新读入数据。该链接仅在您加载
player时由 JPA 填充,而不是神奇地... -
什么意思?我应该在同一个函数中再次从存储库中读取?好像也没有用
标签: java database hibernate spring-data-jpa hibernate-onetomany