如何建模关系改变与Hibernate的一对一关系

时间:2012-04-07 11:18:58

标签: hibernate orm data-modeling foreign-key-relationship

我有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()     {        返回套接字;     }

2 个答案:

答案 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中轻松预防/验证。