2012-04-07 7 views
2

1対1のマッピングを持つ2つのエンティティプラグアンドソケットがあります。Hibernateと1対1の関係を変更する関係をモデル化する方法

プラグは、プラグインされているソケットと外部キーの関係にあります。

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

10個のプラグに10個のプラグが差し込まれています。

しばらくすると、アレンジの変更についてシステムに通知するアップデートが届きます。

socketAにプラグインされたplugAがSocketBにプラグインされ、socketBにプラグインされたplugBがsocketAにプラグインされるシナリオです。

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

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

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

これはコード

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

中栓 @OneToOne(任意=偽) 公共ソケットgetSocket(){ 戻りソケット

ソケットの内側にあります。 }

+0

なぜあなたはそれを何かするのですか?ソケットの多くのプラグ – kommradHomer

答えて

0

は、私はあなたを示唆していずれかの私は、私が試してみて、それを解決しなければならなかったので、あなたの疑問を気に入っ

first transction : 
set both plug.socket to null 

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

または

使用many-to-one

+0

@kommradHommerチップをありがとう。 –

+0

あなたが描いているのは今私のアプローチです。 しかし、違反のために2番目のトランザクションが失敗した場合はどうなりますか? Hibernateは、最初の状態に戻すことができる、最も重要なトランザクションを持つ方法はありますか? –

0

のような2つのトランザクションを持っています。

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

} 

今、このとのソケットフィールドが重要であり、そのこと:だから私は

だから、あなたが何をする必要があるか、このようなものです:) ..あなたが自分でそれを考え出し、まだしていない願っていますnullable/optional。したがって、optional=trueを削除する必要があります。しかし、それはだから何あなたが行うことは、この..です関係が効果的に多くの1つになると矛盾につながることができますユニークな制約なしにあなたを残します:

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

だから、残された唯一の問題は、あなたが今に許可されていることですソケットなしでプラグを保持する。これは大きな問題ではないはずで、DAOでは簡単に防止/検証できます。