我正在使用eclipselink进行基本的JPA设置。我有一个实体来管理物品的库存量。我想跟踪这些项目的库存历史记录,因此我希望每次更新金额也可以创建新的历史记录条目。
问题是当我在@PreUpdate
方法中将新的历史记录实体添加到历史列表时,它将不会与Wine实体一起保留。在调用merge()
或@PrePersist
方法之前手动添加历史记录实体可以按预期工作。
以下是我的代码:
Wine.java
@Entity
public class Wine implements Serializable {
@Id
@GeneratedValue
private long id;
@Transient
private int oldAmount;
@Column
private int amount;
@OneToMany(mappedBy = "wine", cascade = CascadeType.ALL)
private List<AmountHistory> history;
//getters & setters
@PostLoad
@PostUpdate
@PostPersist
private void onLoad() {
oldAmount = amount;
}
@PrePersist
private void onPersist() {
final History history = new History();
history.setOldAmount(0);
history.setNewAmount(amount);
history.setWine(this);
this.history = new ArrayList<>();
this.history.add(history);
}
@PreUpdate
private void onUpdate() {
if (oldAmount != amount) {
final History history = new History();
history.setOldAmount(oldAmount);
history.setNewAmount(amount);
history.setWine(this);
this.history.add(history);
}
}
}
History.java
@Entity
public class History implements Serializable {
@Id
@GeneratedValue
private long id;
@Column
private int oldAmount;
@Column
private int newAmount;
@ManyToOne(cascade = CascadeType.ALL)
private Wine wine;
//getters & setters
}
我目前通过在金额的setter方法中添加历史记录条目来解决这个问题,但我不相信这个解决方案,因为它还会在未调用merge()
时创建历史记录实体。
我需要做些什么来解决这个问题?或者有人可以解释为什么会这样吗?
答案 0 :(得分:1)
您需要在History实体/表中添加一个外键列,以创建两个表之间的关系,如下所示。
@Entity
public class History implements Serializable {
@Id
@GeneratedValue
private long id;
@Column(name="WINE_ID", updateable=false, insertable=false)
private long wineId;
@Column
private int oldAmount;
@Column
private int newAmount;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="WINE_ID", referencedColumnName="ID")
private Wine wine;
//getters & setters
}
答案 1 :(得分:1)
从JPA规范的第3.5节开始: &#34;通常,可移植应用程序的生命周期方法不应调用EntityManager 或查询操作,访问其他实体实例或修改其中的关系 相同的持久性背景。[43]生命周期回调方法可以修改非关系 调用它的实体的状态。&#34;
因此,您不应该尝试修改preUpdate回调中的关系。在这种情况下,它无法正常工作,因为preUpdate发生在合并已经发生并在关系上级联之后 - JPA没有提供一种方法来触发合并再次发生而无需手动调用它。
解决方案是使用您的访问者方法跟踪已有的更改。而不是跟踪oldAmount,还添加新的历史记录实例。这样,您的合并将获取关系以及更改的金额。