2

I have 2 entities plug and socket which have one to one mapping.

Now, plug has a foreign key relationship to the socket it is plugged in to.

Hibernate generates unique constraint on the foreign key so as to ensure a one-to-one particpation.

I have say 10 plugs which are plugged into 10 sockets.

After some time, an update comes which informs the system about the change in arrangement.

The scenario is plugA which was plugged in to socketA is now plugged into SocketB and plugB which was plugged into SocketB is now plugged into socketA.

When doing the update, hibernate first tries to update plugA's foreign key column to SocketB which results in the violation of unique constraint. This is because the plugB to socketB relationship has not yet ben altered.

What is the most correct way to model the relationship?

Note that entire update needs to occur as a single transaction.

This is the code

Inside socket

@OneToOne(mappedBy="socket")
public Plug getPlug()
{
   return plug;
}

Inside Plug @OneToOne(optional=false) public Socket getSocket() { return socket; }

4

2 回答 2

0

我建议你要么有 2 笔交易,如

first transction :  
set both plug.socket to null

second transaction:  
set both plug.socket to what you eventually want

或者

利用many-to-one

于 2012-04-07T11:42:22.300 回答
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 中轻松预防/验证。

于 2012-04-08T08:59:35.687 回答