web-dev-qa-db-ja.com

スプリングデータJPAがsave()の前にSELECTを実行しないようにするにはどうすればよいですか?

既存のデータベースに対して新しいアプリを作成しています。私はSpring Data JPAを使用していますが、単に

MyRepository.save() 

私の新しいエンティティで、を使用して

MyRepository extends CrudRepository<MyThing, String>

ログを見ると、休止状態では挿入前にSelectが実行されており、インデックスを使用している場合でも時間がかかることがわかりました。

ここでこれを検索しましたが、通常、 見つかった回答 はHibernateに特に関連しています。私はJPAを初めて使用しますが、少なくともSpring Dataのコンテキスト内で使用する場合は、JPAとHibernateが非常に密接に絡み合っているようです。リンクされた回答は、Hibernate persist()を使用することを提案していますか、おそらく何らかの形でentityManagerからのセッションを使用していますか?セッションやentityManager、またはHibernate APIを直接使用する必要はありません。これまでのところ、save()といくつかの@Queryをリポジトリで簡単に挿入しました。

11
user26270

Spring Dataリポジトリを使用して使用しているSpring SimpleJpaRepositoryのコードは次のとおりです。

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

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

次のことを行います。

デフォルトでは、Spring Data JPAは指定されたエンティティの識別子プロパティを検査します。 identifierプロパティがnullの場合、エンティティは新規と見なされ、そうでない場合は新規ではないと見なされます。

Spring Dataドキュメントへのリンク

したがって、エンティティの1つにnull以外のIDフィールドがある場合、SpringはHibernateに更新を実行させます(したがって、前にSELECTを実行します)。

同じドキュメントに記載されている2つの方法で、この動作をオーバーライドできます。簡単な方法は、エンティティに(Serializableではなく)Persistableを実装させることです。これにより、メソッド「isNew」を実装できます。

13
Bertrand88

独自のid値を指定すると、Spring DataはDBの重複キーをチェックする必要があると見なします(したがって、select + insertを使用)。

次のようなIDジェネレーターを使用することをお勧めします。

@Entity
public class MyThing {
    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    private UUID id;
}

本当に自分のIDを挿入する必要があり、select + insertを防ぎたい場合は、Persistableを実装します。

@Entity
public class MyThing implements Persistable<UUID> {

    @Id
    private UUID id;

    @Override
    public UUID getId() {
        return id;
    }

    //prevent Spring Data doing a select-before-insert - this particular entity is never updated
    @Override
    public boolean isNew() {
        return true;
    }
}
2
Paul Hilliar