2017-07-12 6 views
1

私は永続化レイヤーとしてJPA(Hibernate)を使用するSpringブートアプリケーションを開発中です。既存のデータを一括して挿入する:すべての挿入の前にJPAがselectを実行するのを防ぐ

現在、移行機能を実装しています。基本的には、システムのすべての既存のエンティティをXMLファイルにダンプします。このエクスポートにはエンティティのIDも含まれます。

私が抱えている問題は、反対側にあり、既存のデータを再インポートしています。このステップでは、XMLは再びJavaオブジェクトに変換され、データベースに永続化されます。

エンティティを保存しようとすると、EntityManagerクラスのmergeメソッドが使用されています。すべて正常に保存されます。

ただし、Hibernateのクエリログを有効にすると、すべての挿入クエリの前に、選択クエリが実行され、そのIDを持つエンティティが既に存在するかどうかが確認されます。これは、エンティティがすでに提供しているIDを持っているためです。

私はこの動作を理解しており、実際には意味があります。しかし、IDは存在しないので、選択が私の場合に意味をなさないと確信しています。何千ものレコードを節約しているので、大規模なテーブルで何千もの選択クエリが発生し、インポートプロセスが大幅に遅くなっています。

私の質問:「挿入する前にエンティティが存在するかどうかのチェック」をオフにする方法はありますか?


追加情報:

org.hibernate.PersistentObjectException:

私が代わりにマージのentityManager.persist()を使用し、私はこの例外を取得 に渡さ切り離さエンティティが

を持続

提供された/提供されたIDを使用できるようにするには、私はこのIDジェネレータを使用します:

@Id 
@GeneratedValue(generator = "use-id-or-generate") 
@GenericGenerator(name = "use-id-or-generate", strategy = "be.stackoverflowexample.core.domain.UseIdOrGenerate") 
@JsonIgnore 
private String id; 

発電機自体:

public class UseIdOrGenerate extends UUIDGenerator { 

    private String entityName; 

    @Override 
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException { 
     entityName = params.getProperty(ENTITY_NAME); 
     super.configure(type, params, serviceRegistry); 
    } 

    @Override 
    public Serializable generate(SessionImplementor session, Object object) 
    { 
     Serializable id = session 
      .getEntityPersister(entityName, object) 
      .getIdentifier(object, session); 

     if (id == null) { 
     return super.generate(session, object); 
     } else { 
     return id; 
     } 
    } 
} 

答えて

1

あなたがデータベース上の任意の既存のエントリを更新することはありませんし、すべてのエンティティを常に新鮮に挿入されなければならないことが確実な場合は、私は行くだろうの代わりにpersist操作を実行します。その場合

更新当たり

(idフィールドがセット・アップされるような自動生成)IDフィールドから発生注釈を削除した構成を残すであろう唯一の方法:

@Id 
@JsonIgnore 
private String id; 

基本的にidを常に手動で割り当てるように設定しています。次に、永続性プロバイダは、idが存在する場合でも、エンティティを一時的と見なします。つまり、persistが機能し、余分な選択が生成されません。

+0

ありがとう、私はそれを言及するのを忘れました。私はpersistを使用しようとしましたが、例外がスローされます。オリジナルの投稿に詳細を更新しました。 – geoffreydv

+0

あなたが変更することができる場合は、私のアップアップを確認してください –

+0

それは良いアイデアですが、私は正しく理解すると、IDは空であるため、アプリケーションの他の部分に新しい項目を挿入することができなくなります。私は手動でsetId(generateId())をどこでも実行する必要がありますが、これは現在オプションではありません。 – geoffreydv

0

IDを入力するかどうかわかりません。アプリケーション側で記入する場合は、answer hereを確認してください。私は以下のそれをコピーした:ここで

あなたは春のデータリポジトリを使用して使用している春SimpleJpaRepositoryのコードです:

@Transactional 
public <S extends T> S save(S entity) { 

    if (entityInformation.isNew(entity)) { 
     em.persist(entity); 
     return entity; 
    } else { 
     return em.merge(entity); 
    } 
} 

それは以下のん:デフォルトでは

春データJPAは、検査します指定されたエンティティの識別子プロパティ。 identifierプロパティがnullの場合、エンティティは新規とみなされ、そうでない場合は新しいものとみなされます。

Link to Spring Data documentation

だから、あなたのエンティティのいずれかがNULLでないIDフィールドを持っている場合は、春は、Hibernateは(前とそうSELECT)の更新を行うようになります。

この動作は、同じドキュメントに記載されている2つの方法で無効にすることができます。簡単な方法は、Entityが永続化可能(Serializableではなく)を実装するようにすることです。これにより、メソッドisNewを実装できます。

関連する問題