JPAのINSERTステートメント

1. 概要

このクイックチュートリアルでは、* JPAオブジェクトでINSERTステートメントを実行する方法を学習します*。
一般的なHibernateの詳細については、包括的なlink:/the-persistence-layer-with-spring-and-jpa[Springを使用したJPAのガイド]およびhttps://www.baeldungをご覧ください。 .com / the-persistence-layer-with-spring-data-jpa [JPAによるSpring Dataの紹介]このトピックの詳細

2. JPAでのオブジェクトの永続化

JPAでは、一時状態から管理状態に移行するすべてのエンティティは、https://www.baeldung.com/hibernate-entitymanager [_EntityManager_]によって自動的に処理されます。
_EntityManager_は、指定されたエンティティが既に存在するかどうかを確認し、挿入または更新する必要があるかどうかを決定します。 この自動管理のため、JPAで許可されるステートメントはSELECT、UPDATE、および* DELETE。*のみです。
以下の例では、この制限を管理および回避するさまざまな方法を見ていきます。

3. 共通モデルの定義

それでは、このチュートリアル全体で使用する単純なエンティティを定義することから始めましょう。
@Entity
public class Person {

    @Id
    private Long id;
    private String firstName;
    private String lastName;

    // standard getters and setters, default and all-args constructors
}
また、実装に使用するリポジトリクラスを定義しましょう。
@Repository
public class PersonInsertRepository {

    @PersistenceContext
    private EntityManager entityManager;

}
さらに、link:/transaction-configuration-with-jpa-and-spring[[email protected]_]注釈を適用して、Springによってトランザクションを自動的に処理します。 これにより、_EntityManagerを使用してトランザクションを作成したり、変更をコミットしたり、例外が発生した場合に手動でロールバックを実行したりする必要がなくなります。

4.  _ createNativeQuery _

手動で作成されたクエリの場合、_EntityManager#createNativeQuery_メソッドを使用できます。 JPAでサポートされているものだけでなく、あらゆるタイプのSQLクエリを作成できます。 リポジトリクラスに新しいメソッドを追加しましょう。
@Transactional
public void insertWithQuery(Person person) {
    entityManager.createNativeQuery("INSERT INTO person (id, first_name, last_name) VALUES (?,?,?)")
      .setParameter(1, person.getId())
      .setParameter(2, person.getFirstName())
      .setParameter(3, person.getLastName())
      .executeUpdate();
}
このアプローチでは、列の名前を含むリテラルクエリを定義し、対応する値を設定する必要があります。
これで、リポジトリをテストできます。
@Test
public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() {
    Person person = new Person(1L, "firstname", "lastname");

    assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> {
        personInsertRepository.insertWithQuery(PERSON);
        personInsertRepository.insertWithQuery(PERSON);
    });
}
テストでは、すべての操作がデータベースに新しいエントリを挿入しようとします。 同じ_id_を持つ2つのエンティティを挿入しようとしたため、2番目の挿入操作はa__PersistenceException_をスローして失敗します。
ここでの原則は、Spring Dataのd_https://www.baeldung.com/spring-data-jpa-query [@Query]を使用している場合と同じです。

5. persist

前の例では、挿入クエリを作成しましたが、エンティティごとにリテラルクエリを作成する必要がありました。 このアプローチはあまり効率的ではなく、多くの定型コードが作成されます。
代わりに、_EntityManager_から_persist_メソッドを使用できます。
前の例のように、カスタムメソッドでリポジトリクラスを拡張しましょう。
@Transactional
public void insertWithEntityManager(Person person) {
    this.entityManager.persist(person);
}
これで、アプローチを再度テストできます__:__
@Test
public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() {
    assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> {
        personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname"));
        personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname"));
    });
}
ネイティブクエリの使用とは対照的に、*列名と対応する値を指定する必要はありません*。 代わりに、_ EntityManager _がそれを処理します。
上記のテストでは、_persist_によって特殊化されてスローされるスーパークラス_PersistenceException_の代わりに、_EntityExistsException_がスローされることも想定しています。
一方、この例では、**新しいインスタンス_Person._ **を使用して毎回挿入メソッドを呼び出すようにしなければなりません。 。

6. 結論

この記事では、JPAオブジェクトで挿入操作を実行する方法を説明しました。 ネイティブクエリの使用例と、_EntityManager#persist_を使用してカスタムINSERTステートメントを作成する例を見てみました。
いつものように、この記事で使用される完全なコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-jpa[GitHubで]から入手できます。