gpt4 book ai didi

java - JPA - @PreRemove 方法行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:50:50 25 4
gpt4 key购买 nike

我有 2 个具有多对多关系的实体。 Movie 实体是此关系的所有者,因此当我想删除 Actor 实体时,我使用注释为 @PreRemove 的方法删除 Movie cast 中出现的任何 Actor ID 以避免“外键违规异常”。

电影课

@Entity
public class Movie extends AbstractBusinessObject{

@ManyToMany
private Map<String, Actor> cast;

// setters and getters

public void removeCastMember(Actor actor){

for (Entry<String, Actor> e : cast.entrySet()) {
if(e.getValue().id.equals(actor.id)){
cast.remove(e.getKey());
}
}

} // removeCastMember()

}

Actor类

@Entity
public class Actor extends AbstractBusinessObject{

@ManyToMany(mappedBy = "cast")
private Set<Movie> movies;

// setters and getters

@PreRemove
private void removeActorFromMovies() {
for (Movie m : movies) {
m.removeCastMember(this);
}
}

}

明确地说,根据我的测试,它有效 - 电影对象在数据库中正确更新。但是,我不明白当没有调用 saveOrUpdate() 或保留/合并这些对象时怎么可能。

最佳答案

这是 JPA/Hibernate 的一个基本特性。对附加实体所做的所有更改都会自动持久化:Hibernate 管理它们,因此它将它们的当前状态与初始状态进行比较,并自动使所有更改持久化。

这非常有用,因为您不必跟踪在修改大量实体的复杂业务方法中修改的所有实体。而且它也很高效,因为 Hibernate 不会执行不必​​要的 SQL:如果实体在事务期间没有更改,则不会为此实体执行任何 SQL 更新查询。如果您修改实体然后抛出异常回滚事务,Hibernate 将跳过更新。

因此,典型的 JPA 代码如下所示:

void transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) {
Account from = em.find(Account.class, fromAccountId); // from is managed by JPA
Account to = em.find(Account.class, ftoAccountId); // to is managed by JPA
from.remove(amount);
to.add(amount);

// now the transaction ends, Hibernate sees that the state of from and to
// has changed, and it saves the entities automatically before the commit
}

persist() 用于使新实体持久化,即使其由 Hibernate 管理。

merge() 用于获取分离的实体(即不受 Hibernate 管理但已经具有 ID 和状态的实体)并将其状态复制到具有相同的 ID。

关于java - JPA - @PreRemove 方法行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19751465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com