2011-08-18 8 views
7

私は、Oracle XE 10g、Hibernate 3.5、JPA 2.0の設定をしています。挿入時にデータベース・トリガーによって生成される主キーを持つシンプルな表があります。トリガはシーケンスから値を取得します。トリガー/シーケンスの構成はOracle XEによって行われました。トリガーによって値が生成された場合、Id列に注釈を付けるにはどうすればよいですか?

実際の質問は次のとおりです。EntityManager.persistの後に、自分のエンティティでIdの現在の値を取得するにはどうすればよいですか?
私が試み:

@Id 
private long id; 

- > idは0です。

@Id 
@Generated(GenerationTime.ALWAYS) 
@Column(insertable = false, updatable = false) 
private long id; 

- > idは0です。

@Id 
@GeneratedValue(strategy=GenerationType.AUTO) 
private long id; 

- > Hibernateが(存在しない)シーケンスを直接照会しようとしているため、失敗します。

最初の2つのアプローチではIDがデータベースに生成されますが、私のオブジェクトには値がありません

答えて

2

トリガーにバインドされていない限り、これはシーケンス上の難読化レベルのようであり、通常のHibernateライフサイクルの外にあるようです。なぜ直接シーケンスを呼び出さない:

@SequenceGenerator(name="alias_for_my_sequence", sequenceName="seq_name_in_oracle") 
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="alias_for_my_sequence") 
@Id 
private Long id; 

Hibernateは世代に直接関与しており、事実の後に起こって何かがないと、あなたは、戻って値を取得します。

+0

ありがとうございますが、トリガーは増分するPK値を自動的に生成するOracleの方法です。私がそれを取り除くと、私はデータベースに直接クエリで簡単に行を挿入する可能性が失われます。第二に、あなたの提案のように注釈を付けると、単体テストのためにDerbyに簡単に切り替えることはできません。(... DBが生成したものだけを取るというアノテーションが必要です。 – Zeemee

+0

これをグーグルで詳細な調査に基づいて、他のユーザーがHibernateからOracleのシーケンスを参照して成功しているように見えます。例を示します:https://forum.hibernate.org/viewtopic.php?p=2442821 Derbyの問題については、 – atrain

+2

@Mulmoth:行を一意に識別する別のフィールドがない限り、Hibernateはどのようにしてその行を取得するのでしょうか?つまり、挿入されたばかりの行を識別する唯一の方法はIDであり、それはわからないからです。つまりIDを取得するにはIDが必要です。トリガーは本当に悪い考えです。 –

1

Oracleセッション内でdb生成キーを交換できます。このために、挿入トリガーは、クエリで新しいキー値を取得することができ、あなたのコードから

dbms_session.set_identifier(new_id) 

を呼び出す必要があります

String sql = "SELECT sys_context('USERENV', 'CLIENT_IDENTIFIER') FROM dual"; 
Query query = em.createNativeQuery(sql); 
String new_id = (String) query.getSingleResult(); 

新しいエンティティを永続化するために同じEntityManagerインスタンスを使用することが重要です生成されたキー値を取り出す。

7

@ JB Nizetのコメントとは対照的に、私は実際にはトリガにIDを割り当てることができる多くの理由を考えることができます:ストアドプロシージャの実行、SQLの手動実行、およびHibernateでのネイティブクエリの実行。

私は個人的に次の解決策を見いだしました。 Hibernateは最大IDを見つけ出し、insert文が呼ばれるたびにインクリメントさせます。文はデータベースに当たったときしかし、IDは無視され、トリガによって生成された1で上書きするので、何uniqueness in a cluster problemありませんされています

@Id 
    @GeneratedValue(generator="increment") 
    @GenericGenerator(name="increment", strategy = "increment") 
    private Long id; 

最大の欠点は@GenericGeneratorであるHibernateの注釈がされ、あなたがJPAの移植性を失うので、 。プログラマーには、このIDが実際にシーケンスにリンクされていることも明確ではありません。

もう1つの方法は、IDがnullの場合にトリガを増分シーケンスだけに変更する方法です。 「Hibernate issue with Oracle Trigger for generating id from a sequence」を参照してください。ほとんどの場合、IDがシーケンスにリンクされていることが明確に示されているため、これが最適なソリューションです。私の唯一の不満は、最初の場所でシーケンスを実際に照会することなくIDを挿入するオプションをユーザ/休止状態に与えることです。

+0

この例を見てください:http://developer-should-know.com/post/82479486933/how-to-use-oracle-before-insert-trigger-for-idそれは、カストムの休止状態を実装する方法を示していますid post insertを取得するジェネレータ。 –

関連する問題