我有下一张ER图
我想在每次保存 Score 实体时更新 PlayerStat 实体。所以我尝试使用@PostPersist
注释。当我保存 Score 实体时,使用该注释调用函数,但是我在此函数中执行的更改不会保留。我的实现如下。所有实体类都为构造函数提供了lombok注释
的播放器
@Id
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(name = "custom-uuid", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@Temporal(TemporalType.DATE)
@Getter
@NonNull
private Date createdAt;
@Column(unique = true)
@Getter
@Setter
@NonNull
private String nickname;
@OneToMany(mappedBy = "winner")
@Getter
@NonNull
private Set<Game> gamesWon;
@Getter
@OneToOne(cascade = CascadeType.PERSIST, optional = false)
@JoinColumn
private PlayerStat stat;
@OneToMany(mappedBy = "player")
@Getter
@NonNull
private Set<Score> scores;
public Player(String nickname, Date createdAt) {
this.nickname = nickname;
this.createdAt = createdAt;
stat = new PlayerStat(0, 0, 0, this);
}
游戏
@Id
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(name = "custom-uuid", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@Getter
@NonNull
@Column(updatable = false)
private Integer durationMinutes;
@Temporal(TemporalType.DATE)
@Getter
@NonNull
private Date dateStarted;
@ManyToOne(optional = false)
@JoinColumn
@Getter
@NonNull
private Player winner;
@OneToMany(mappedBy = "game")
@Getter
private Set<Score> scores;
@PostPersist
private void update(){
System.out.println("On game post persist");
winner.getStat().incrementTotalWins();
}
PlayerStat
@Id
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(name = "custom-uuid", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@Getter
@Setter
@NonNull
private Integer totalScore;
@Getter
@NonNull
private Integer totalWins;
@Getter
@NonNull
private Integer totalGames;
@Getter
@OneToOne(mappedBy = "stat", optional = false)
@NonNull
private Player player;
public void incrementTotalWins() {
totalWins++;
}
public void incrementTotalGames() {
totalGames++;
}
得分
@Id
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(name = "custom-uuid", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
@ManyToOne(optional = false)
@JoinColumn(name = "game_id")
@Getter
@NonNull
private Game game;
@ManyToOne(optional = false)
@JoinColumn
@Getter
@NonNull
private Player player;
@Getter
@NonNull
private Integer score;
@PostPersist
void updatePlayerStat(){
System.out.println("On score post persist");
player.getStat().incrementTotalGames();
player.getStat().setTotalScore(player.getStat().getTotalScore() + score);
System.out.println(player);
}
因此,我尝试使用该播放器保存单个播放器,游戏,并使用该游戏和播放器评分。两个函数,注释为@PostPersist
。然后在另一个请求中我读了这个播放器。应用了游戏功能中的更改,但分数功能中的更改未执行。但是,如果我像这样单独请求(它与实体监听器无关)
score.getPlayer().getStat().incrementTotalGames();
score.getPlayer().getStat().incrementTotalWins();
score.getPlayer().getStat().setTotalScore(100);
scoreRepository.save(score);
将应用所有更改
我还尝试使用单独的EntityListener类并进入该类库,保存修改后的对象,但这也不起作用。我尝试在每个关系中添加CascadeType.ALL
,但仍然没有变化。那么我应该做什么来自动更新PlayerStat?
答案 0 :(得分:1)
在我看来,你想要的是 @PrePersist ?
你确实想在游戏中向玩家添加级联,
答案 1 :(得分:1)
如果您使用@PostPersist
,信息将在持久性后更新,因此您将无法在数据库中获取信息,因此您应该在将结果保存到dataBase之前在服务层中执行此增量,您也可以尝试:
1- @PrePersist
因为PrePersist执行之前实体管理器持久操作实际执行或级联。此调用与持久操作同步。
2 - @PreUpdate
因为PreUpdate在数据更新操作之前执行了 。
答案 2 :(得分:0)
@PostPersist
- 和其他回调方法 - 有局限性,从中无法更新实体状态
答案 3 :(得分:0)
根据我的经验(在WildFly中),您必须手动刷新保存语句,否则更改将丢失。另请参见JPA规范中的注释(JPA 2.2第3.5.3节)。似乎没有非常精确地定义与事务划分有关的调用postpersist方法的确切点。