我的A实体<-&燃气轮机;B实体关系通过R实体完成。然而,R有额外的信息阻止使用@ManyToMany:
id | id_a | id_b | previous | ordering_index
----------------------------------------------
1 | 1 | 10 | 2 | 1
2 | 1 | 15 | null | 0
3 | 1 | 18 | 1 | 2
JPA实体
@Entity
// ...
public class A{
// ...
@OneToMany(mappedBy="master", cascade = Cascade.ALL, orphanRemoval = true)
@OrderBy("ordering")
private List<R> bList;
// ....
}
@Entity
// ...
public class B{
// ...
@OneToMany(mappedBy="slave", cascade = Cascade.REMOVE)
private List<R> aList;
// ....
}
@Entity
// ...
public class R{
@Id
// ...
private long id;
@ManyToOne
@JoinColumn(name = "id_a", referencedColumnName = "id")
private A master;
@ManyToOne
@JoinColumn(name = "id_b", referencedColumnName = "id")
private B slave;
@OneToOne
@JoinColumn(name = "previous", referencedColumnName = "id")
private R previous;
@Column(name = "ordering_index")
private int ordering;
}
aList
.
在创建、更新和删除后,R实体被正确地持久化并在数据库中删除
-
如果我把B加在A上,A就正确地把B加在了里面
bList
-
删除B后,R实体被正确删除,但受影响的A实体中仍有B
我试过的
-
为了看一看,我尝试向
slave
属性,这是个坏主意
-
我想为负责B实体的EJB修饰CRUD方法:删除后,找到所有受影响的A实体,并删除中的关系
bList公司
so-far > 1)
:B无法识别与其相关的A实体
-
列表
entityManager.merge()
操作=>JPA错误,因为R已经存在(即使我没有级联合并属性?)
-
列表
无法识别与其相关的实体
编辑:解决方案(草稿)
我附加了解决方案来连接评论和答案的反馈。正如Chris正确提到的,这是关于JPA事务范围的。在继续之前,请先了解一些细节:
-
在R的设计(数据库和实体定义)中,主从之间存在唯一性约束
-
在创建和更新A操作时,也更新B实体
)根据克里斯的回答:
public class aEjb{
// ...
public void update(A a){
// by A -> R cascade, all the bList will be updated
em.merge(a);
// BUT !!!
// as the transaction did not end, the newly created
// relationship do not have a primary key generated
// yet so if I do:
for(R r : a.getBList()){
B b = r.getSlave();
// I'm here adding r = (null, a, b)
b.add(r);
// as r has a null primary key, JPA will try to
// create it, even if I removed all cascade annotation
// on b side => I didn't really understand why though
bEjb.update(b);
// as there is UNIQUE(a,b) constraint, JPA will
// throw an exception
}
// the solution was to fetch a fresh copy of the
// cascaded created R entity. As the primary key
// is not known yet, I have to go through sth like
for(R r : a.getBlist()){
B b = r.getSlave();
R updatedR = rEjb.findByMasterAndSlave(a, b);
// I'm here adding updatedR = (123, a, b)
b.add(updatedR)
// as updatedR primary key is not null, JPA
// won't force any cascade operation, and that's
// great becaues I don't want any cascade here
bEjb.update(b);
}
}
// ...
}
附加说明
目前为止
bList公司
列表
是最新的。如果删除B实体,我有一个可用的
循环通过。然而,又出现了一个问题:如果我从a实体中删除了B实体,但只删除了链接,而不删除这些实体中的任何一个,该怎么办?
解决方案是避免这种选择
orphanRemoval = true
:
之前:
@Entity
// ...
public class A{
// ...
@OneToMany(mappedBy="master", cascade = Cascade.ALL, orphanRemoval = true)
@OrderBy("ordering")
private List<R> bList;
// ....
}
之后:
@Entity
// ...
public class A{
// ...
@OneToMany(mappedBy="master", cascade = Cascade.ALL)
@OrderBy("ordering")
private List<R> bList;
@Transient
private List<R> orphanBList;
// ....
public void addB(B b){
R r = new R(a,b);
bList.add(r);
}
public void removeR(R r){
bList.remove(r);
orphanBList.add(r);
}
}
然后,我继续执行定义的类似EJB操作,以更新受影响的B实体