java - hibernate什么时候会更新相关实体?

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

我正在使用 spring data JPA 并拥有 PlayerScore 实体。 PlayerScore 具有 @OneToMany 关系(并且 @ManyToOneScore玩家)。我将 Player 保存到数据库中,但没有指定相关分数。之后,我将 Score 保存到数据库,并将指向 Player 的链接传递给构造函数。然后在同一个函数中,我读取了 Player 条目,但它还没有指向 Score 条目的链接。
我的 OneToMany 关系中有 FetchType.LAZY,因此我需要在该函数中使用注释 @Transactional。我还尝试在内部事务中保存玩家和得分(使用 propogation=Propogation.REQUIRES_NEW )并在外部事务中读取玩家条目,但这没有帮助。我还尝试添加 CascadeType.ALL - 没有效果。我使用了 JpaRepository 中的 flush() 方法 - 也没有帮助。
但是,如果我在一个 Controller 方法(使用 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 的 session 重新加载 Player 将调出旧的 Player 实例,而不会使用来自数据库。

因此,为了查看更改后的 Player,您需要刷新 session 并从 session 中删除 Player,然后重新加载它。或者,您可以直接关闭 session 。

您似乎试图通过单独的事务方法来实现这一目标。 原则上这应该可行,但我几乎 100% 确定,您有一个事务在保存和加载方法上运行。 您可以启用事务日志记录以便进一步调查:Spring hibernate Transaction Logging

您真正想做的可能是通过编写自定义 setter 来保持两个 java 对象同步。

关于java - hibernate什么时候会更新相关实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49373280/

相关文章:

java - 抛出操作数的子句中的 Spring JPA 应包含 1 列

java - 使用 Spring Boot 初始化 hibernate、jpa 和 MysqlApp?

hibernate - 如何使用 JPA 在表中查找值

java - Aviarc 中 aviarc.engine.aviarcData 的默认/故障转移值

MySQL 查询 : ID not equal and with multiple LIKE operator not working

JavaFX FileChooser 在窗口为 "closed"后停止所有其他代码

database - 在集中设置中需要 redis 服务器

sql-server - MVC 5,App_Data 为空,尽管显示所有文件。

java - 尝试在 Java 中构建

java - 当对话框中有动态文本时如何验证对话框中的文本