2012-10-05 14 views
5

私は新しいオブジェクトを持っています。私はそれを保存する前にIDを知りたい。出来ますか?それとも別の方法がありますか?私はデータベースとしてormとoracleとしてjpaを使用しています。オブジェクトをjpaに保存する前にIDを知る方法

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

私のエンティティにはコードフィールドがあります。ユーザーがcodeフィールドの値を入力しない場合は、コードをエンティティのIDとして設定する必要があります。私がエンティティを永続させるならば、IDとIDのコード値をidとして取得できますが、これは追加のクエリデータベースです。

私はあなたが(実際にそれを書き込む前に)事前にその値を知ることができません@GeneratedValueタイプのIDを持つこと

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

あなたが「手動」の値を取得し、エンティティにそれを設定するために発電機を自分で使用し、@GeneratedValueを避けることができ – SJuan76

+0

私がdontエンティティに手動で設定したい場合は、oracleからidの次の値を取得し、新しいエンティティのIDに設定します。合理的ですか? – mstzn

答えて

5

これで、私は解決策を見つけました。実際には

あなたはJPAでシーケンスジェネレータを使用する場合は次のIDは、データベース配列によって割り当てられますので、確かにあなたは、データベースに保存する前に、エンティティのIDを取得することはできません。

あなたはカスタムジェネレータを使用する場合は、保存する前に、IDを取得することができますIDを取得するための一つの方法があります。ここに簡単な実装です:

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

idフィールドのためCustomGeneratorの使用:

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8

のような何かをしたいです。ただし、Beanを永続化すると、そのBeanインスタンスにidフィールドが設定され、追加のクエリを実行することなく取得できます。言い換えれば:

また
MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

、あなたのEntityManagerが設定されている方法に応じて、あなたはそのIDを取得することができます前にも、最初の(手動)、トランザクションをコミットする必要がある場合があります。コメント

あたりとして

更新あなたはそれを保存および/または更新される前にエンティティに何かを傍受して行いたい場合は(あなたはJPAのバージョン2を使用している場合)、あなたはJPAライフサイクルリスナを使用することができます。Handling JPA lifecycle event using listeners and callbacks

は、基本的には、あなたの豆でvalidate()方法を作る@PrePersistと​​でそれに注釈を付けると第二のコメントあたり

アップデート(コードは、IDの値に空のセットそれがあれば)、それに検証を行うことができ

はい、私は正直言ってちょうど今考えました:idが自動生成された場合、pre-persistイベントの後にデータが生成される可能性があります。そのため、pre-persistコードが実行されたときに、 (この例では、IDにリンクすると自動生成されず手動で設定されていることに気付くかもしれません)。 この場合、isCodeEmptyという名前のエンティティ(@Transientの注釈が付いているので、永続化されません)にブール値フィールドを追加します(これは、特に初期化されていなければfalseです)。次に@PrePersist注釈付きメソッドでは、codeフィールドの値が空であるかどうかをチェックし、そうであればbooleanをtrueに設定します。そして、あなたはそれがこのブール値をチェックします(idフィールドを設定することは別として)そのように、あなたのsetId(...)方法をリファクタリングし、trueを設定するidフィールドとコードフィールドの値:長さ約研究した後

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

返信ありがとうございます。質問を更新しました。確認できますか? – mstzn

+0

私はエンティティlistener.butを試していますprepersist idの値はnullです。私はnull.Iなぜそれが= http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htmのように実装するのか分からない提案やアイデア?ありがとうございました – mstzn

+1

あなたのアイデアは優れていますが、prePersistのsetId()メソッドが機能していないといいです。あなたの言うことをしました。私はそれをデバッグしますが、setIdメソッドは実行されず、コードフィールドは設定されません.Prepersistは動作しています。 – mstzn

関連する問題