2017-10-03 16 views
0

である必要があります:私は、次の2つのエンティティ持って同じ

@Entity 
@Table(name="user") 
public class User { 
    @Id 
    @Column("id") 
    private long id; 

    @Column(name="code", nullable = false) 
    private String code; 

    @Column(name="session_id", nullable = false) 
    private long sessionId; 
} 

@Entity 
@Table(name="task") 
public class Task { 
    @Id 
    @Column("id", nullable = false) 
    private long id; 

    @ManyToOne(optional = false) 
    @JoinColumn(name="primary_user_code", referencedColumnName = "code", nullable = "false") 
    private User primaryUser; 

    @ManyToOne(optional = true) 
    @JoinColumn(name="secondary_user_code", referencedColumnName = "code", nullable = "true") 
    private User secondaryUser; 
} 

を問題はTaskで2つのUserのオブジェクトが有していなければならないことです同じsessionId。休止状態の注釈を使用してこれを強制する方法はありますか?あるいは、弾丸を噛んでコードで強制するだけですか?

私はおそらくUserすでにことを言及している必要があります更新

@Where@WhereJoinTable注釈に探してみましたが、このバグレポート、linkを休止状態に応じて、それが@ManyToOne


のためにサポートされていません。存在し、変更することはできません。私がコントロールしているのは、私が追加しているTaskクラスです。

コードは一意ではなく、session_idとともに一意のユーザーを識別します。 session_idは別のテーブルを参照していますが、@OneToOneの関係が付いていません。これは単純な列であり、Sessionテーブルとの関係はコードで処理されます。本質的に各Userにはコードがあり、複数のSessionsにリンクされています。私は追加していタスクテーブルの場合

、私は可能であれば

+0

あなたがここで達成しようとしていることはわかりませんが、あなたが書いたことはまったく問題ないと思います。あなたはTASKテーブルに追加される外部キー列について心配する必要があります。関連する2つのユーザーエンティティの場合、2つの差分があります。外部キー列名、すなわち名前の競合のないprimary_user_codeおよびsecondary_user_code。 UserエンティティのsessionId属性はTASKテーブルにマッピングされないため、名前の競合はありません。 – Ish

+1

質問には直接関係しませんが、あなたの外部キーはユーザの 'code'カラムを指しています。この列はユニークですか?あなたの質問によると、私はあなたの要件が標準のJPAで解決できるとは思わない。関与するエンティティを永続化/マージする前にチェックする必要があります – Al1

+0

これは、カラム定義にunique = trueを追加すると、ほとんどのRDBMでのみ機能します。それでも、それは悪い習慣だと思う:FKは常にPKを指すべきである。 – fhossfel

答えて

0

これは、古典的なSQLには可能ではない、それに注釈を付けたかったのです。検査制約は行ごとに適用され、2つのsession_idが2つの異なる行に表示されるため、検査制約は役に立ちません。オラクルでは、このような状況のための制約を伴う最新のMVをコミットすることができますが、それはここでは範囲外です。

@PrePersist @PreUpdateコールバックを使用して、Java側でこの条件をチェックすることをお勧めします。

@PrePersist @PreUpdate 
public void checkSessionId() { 
    if (primaryUser.getSessionId() != secondaryUser.getSessionId()) 
     throw new IllegalStateException("Mismatch of sessionId between primary and secondaryIser"); // Better to define your own exception here 

} 

もちろん、難しい部分は例外を正しく処理することです。 entityManagerは、トランザクションをロールバックとしてマークします。したがって、ビジネスロジックのチェックが失敗した場合には、これが本当に最後の防衛線になるはずです。

+0

ありがとう、私はこれを試してみます。 –

+0

残念ながら、私たちはHibernate Sessionを使用しているので、 '@ PrePersist'と' @ PreUpdate'を使用することはできません。これは 'EntityManager'を使用している場合にのみ有効です https://stackoverflow.com/a/4133629/8712057 –

+0

純粋なHibernateでは、本質的に同じことをするインターセプタを登録することができます。詳細については、[Hibernate documentation](https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events)を参照してください。 – fhossfel

0

カスタム検証アノテーションとConstraintValidatorを実装するクラスを記述できます。 isValidメソッドをオーバーライドすることにより、カスタムロジックをカスタムアノテーションに追加できます。 thisの例をご覧ください。

+0

ありがとう、私はこれを試してみます。 –

関連する問題