2

1対1のマッピングを持つ2つのエンティティプラグとソケットがあります。

現在、 plug は、プラグインされているソケットとの外部キー関係を持っています。

Hibernate は、1 対 1 の参加を保証するために、外部キーに一意の制約を生成します。

私は、10個のソケットに差し込まれている10個のプラグを持っています。

しばらくすると、配置の変更についてシステムに通知する更新が行われます。

シナリオは、socketA にプラグインされた plugA が SocketB にプラグインされ、SocketB にプラグインされた plugB が socketA にプラグインされるというものです。

更新を行うとき、hibernate は最初に plugA の外部キー列を SocketB に更新しようとしますが、その結果、一意の制約に違反します。これは、plugB と socketB の関係がまだ変更されていないためです。

関係をモデル化する最も正しい方法は何ですか?

更新全体が単一のトランザクションとして発生する必要があることに注意してください。

これがコードです

ソケット内

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

内部プラグ @OneToOne(optional=false) public Socket getSocket() { return socket; }

4

2 に答える 2

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);

}

これで、ソケットフィールドがnull許容/オプションであることが重要になります。したがって、を削除する必要がありますoptional=true。しかし、それでは、関係が事実上1対多になるため、不整合につながる可能性のある固有の制約がなくなります。

@OneToOne
@JoinColumn(nullable=true, unique=true)
private Socket socket;

したがって、残っている唯一の問題は、ソケットなしでプラグを永続化できるようになったことです。これは大きな問題ではなく、DAOで簡単に防止/検証できます。

于 2012-04-08T08:59:35.687 に答える
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 に答える