我有2个实体插件和插座,它们具有一对一的映射。
现在,插件与插入的插座有外键关系。
Hibernate在外键上生成唯一约束,以确保一对一的参与。
我说有10个插头插入10个插座。
一段时间后,会有一个更新,告知系统安排的变化。
方案是plugA插入socketA现在已插入SocketB,而插入SocketB的plugB现已插入socketA。
执行更新时,hibernate首先尝试将plugA的外键列更新为SocketB,这会导致违反唯一约束。这是因为plugB到socketB的关系还没有改变。
建立关系的最正确方法是什么?
请注意,整个更新需要作为单个事务进行。
这是代码
内部插座
@OneToOne(mappedBy="socket")
public Plug getPlug()
{
return plug;
}
内置插头 @OneToOne(可选=假) public Socket getSocket() { 返回套接字; }
答案 0 :(得分:0)
我建议您进行2笔交易,比如
first transction :
set both plug.socket to null
second transaction:
set both plug.socket to what you eventually want
或
使用many-to-one
答案 1 :(得分:0)
我喜欢你的问题,所以我不得不尝试解决它。所以我希望你自己没有想出来......:)
所以你需要做的是这样的事情:
@Override
public void swap(Socket s1, Socket s2) {
s1 = em.find(Socket.class, s1.getId());
s2 = em.find(Socket.class, s2.getId());
Plug plug1 = s1.getPlug();
Plug plug2 = s2.getPlug();
plug1.setSocket(null); //This is to avoid duplicate key exception
plug2.setSocket(null);
em.flush(); //Without this the nullifying will just be overwritten by the next change.
plug1.setSocket(s2);
plug2.setSocket(s1);
}
现在,重要的是套接字字段是可空的/可选的。所以你必须删除optional=true
。但这会让你没有一个独特的约束,这可能导致不一致,因为这种关系实际上变成了一对多......所以你要做的就是:
@OneToOne
@JoinColumn(nullable=true, unique=true)
private Socket socket;
所以剩下的唯一问题就是你现在可以在没有插座的情况下坚持插件。这不应该是一个大问题,可以在DAO中轻松预防/验证。