实体监听器上没有更新实体@PostPersist(Spring data jpa)

时间:2018-03-14 13:07:26

标签: java database hibernate jpa spring-data-jpa

我有下一张ER图 enter image description here
我想在每次保存 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?

4 个答案:

答案 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方法的确切点。