17

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

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

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

そんなことしたい

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

4 に答える 4

13

@GeneratedValueタイプIDを使用すると、(実際に書き込む前に)その値を事前に知ることはできません。ただし、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ライフサイクルリスナーを使用できます(JPAバージョン2を使用している場合):リスナーとコールバックを使用してJPAライフサイクルイベントを処理します

基本的validate()に、Beanでメソッドを作成し、それに注釈を付けて @PrePersist検証@PreUpdateを行うことができます(コードが空の場合は、IDの値に設定します)

2番目のコメントごとに更新

はい、正直なところ、今考えたところです。IDが自動生成された場合、pre-persistイベントの後にデータが入力される可能性があるため、pre-persistコードを実行しても、IDが何であるかがわかりません。 (この例では、IDにリンクするのは自動生成されておらず、手動で設定されていることにも気付くかもしれません)。この場合にできることは、(@Transient永続化されないように注釈が付けられた)ブールフィールドをエンティティに追加することisCodeEmptyです(特に初期化されていない場合、デフォルトではfalseです)。次に、@PrePersist注釈付きメソッドで、コードフィールドの値が空かどうかを確認し、空の場合はブール値をtrueに設定します。setId(...)次に、(idフィールドの設定は別として)このブール値をチェックするようにメソッドをリファクタリングし、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;
 }

}


}
于 2012-10-05T09:02:09.447 に答える
13

これについて長い間研究した後、最終的に私は解決策を見つけました。

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

カスタムジェネレータを使用する場合にIDを取得する方法は1つあり、保存する前に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;
于 2013-02-07T16:44:11.627 に答える
1

これが私のために働く解決策です:

    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "my_seq" )
    @SequenceGenerator( name = "my_seq", sequenceName = "my_seq" )
    @Access( AccessType.PROPERTY )
    private Long id;

    @Column( name = "CODE", nullable = false, updatable = false )
    private Long code;

    public void setId(Long id) {
        this.id = id;
        if (code == null) {
            code = id;
        }
    }

重要な部分は@javax.persistence.Access( AccessType.PROPERTY )アノテーションを配置することです。これにより、Hibernateはゲッターとセッターを使用してidフィールドにアクセスします。これがないと、@ Idアノテーションがフィールドゲッターではなくフィールドに直接配置される場合、Hibernateはフィールドベースのアクセス戦略を使用します(ゲッターとセッターは使用されません)。リンク:https ://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/domain/access.htmlhiber

于 2021-07-05T17:38:44.987 に答える
0

これらの手順に従うだけで、トランザクションを完了する前にIDを取得できます。

最初のステップでは、と呼ばれるアノテーションを使用して、エンティティレベルでエンティティリスナーを追加します@EntityListeners

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

2番目のステップ

public class SomeLinstener{
    
    @PostPersist
    public void userPostPersist(YourEntity obj) {
        
        try {
            obj.getId();
        }catch(Exception e) {
            
        }
    } 

これにより、ジェネレーターによって生成されたIDが作成され、必要な場所で再利用でき、単一のトランザクションで提供されます。

これが他の誰かに役立つことを願っています。

于 2019-08-28T09:03:02.740 に答える