INSERT-Anweisung in JPA

1. Übersicht

In diesem kurzen Tutorial erfahren Sie, wie Sie eine INSERT-Anweisung für JPA-Objekte ausführen .

Weitere Informationen zu Hibernate im Allgemeinen finden Sie in unserem umfassenden Handbuch zu JPA mit Spring und in der Einführung in Spring Data mit JPA, um sich eingehend mit diesem Thema zu befassen.

2. Persistierende Objekte in JPA

In JPA wird jede Entität, die von einem vorübergehenden in einen verwalteten Zustand wechselt, automatisch vom EntityManager verarbeitet .

Der EntityManager prüft, ob eine bestimmte Entität bereits vorhanden ist, und entscheidet dann, ob sie eingefügt oder aktualisiert werden soll. Aufgrund dieser automatischen Verwaltung, t er nur durch JPA erlaubt Aussagen sind SELECT, UPDATE und DELETE.

In den folgenden Beispielen werden verschiedene Möglichkeiten zum Verwalten und Umgehen dieser Einschränkung beschrieben.

3. Definieren eines gemeinsamen Modells

Zunächst definieren wir eine einfache Entität, die wir in diesem Lernprogramm verwenden werden:

@Entity public class Person { @Id private Long id; private String firstName; private String lastName; // standard getters and setters, default and all-args constructors }

Definieren wir außerdem eine Repository-Klasse, die wir für unsere Implementierungen verwenden:

@Repository public class PersonInsertRepository { @PersistenceContext private EntityManager entityManager; }

Darüber hinaus wenden wir die Annotation @Transactional an, um Transaktionen bis Spring automatisch abzuwickeln. Auf diese Weise müssen wir uns nicht darum kümmern, Transaktionen mit unserem EntityManager zu erstellen , unsere Änderungen festzuschreiben oder im Falle einer Ausnahme manuell ein Rollback durchzuführen.

4. createNativeQuery

Für manuell erstellte Abfragen können wir die EntityManager # createNativeQuery- Methode verwenden. Es ermöglicht uns, jede Art von SQL-Abfrage zu erstellen, nicht nur solche, die von JPA unterstützt werden. Fügen wir unserer Repository-Klasse eine neue Methode hinzu:

@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(); }

Bei diesem Ansatz müssen wir eine Literalabfrage mit den Namen der Spalten definieren und die entsprechenden Werte festlegen.

Wir können jetzt unser Repository testen:

@Test public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() { Person person = new Person(1L, "firstname", "lastname"); assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> { personInsertRepository.insertWithQuery(PERSON); personInsertRepository.insertWithQuery(PERSON); }); }

In unserem Test versucht jede Operation, einen neuen Eintrag in unsere Datenbank einzufügen. Da wir versucht haben, zwei Entitäten mit derselben ID einzufügen, schlägt die zweite Einfügeoperation fehl, indem eine PersistenceException ausgelöst wird .

Das Prinzip hier ist dasselbe, wenn wir die @Query von Spring Data verwenden.

5. bestehen

In unserem vorherigen Beispiel haben wir Einfüge-Abfragen erstellt, aber wir mussten Literal-Abfragen für jede Entität erstellen. Dieser Ansatz ist nicht sehr effizient und führt zu viel Boilerplate-Code.

Stattdessen können wir die persist- Methode von EntityManager verwenden .

Erweitern wir wie in unserem vorherigen Beispiel unsere Repository-Klasse um eine benutzerdefinierte Methode:

@Transactional public void insertWithEntityManager(Person person) { this.entityManager.persist(person); }

Jetzt können wir unseren Ansatz erneut testen :

@Test public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() { assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> { personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname")); personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname")); }); }

Im Gegensatz zur Verwendung nativer Abfragen müssen keine Spaltennamen und entsprechenden Werte angegeben werden . Stattdessen übernimmt EntityManager das für uns.

Im obigen Test erwarten wir auch, dass EntityExistsException anstelle der Superklasse PersistenceException ausgelöst wird, die spezialisierter ist und von persist ausgelöst wird .

Andererseits müssen wir in diesem Beispiel sicherstellen, dass wir unsere Einfügemethode jedes Mal mit einer neuen Instanz von Person aufrufen . Andernfalls wird es bereits von EntityManager verwaltet, was zu einem Aktualisierungsvorgang führt.

6. Fazit

In diesem Artikel haben wir Möglichkeiten zum Ausführen von Einfügevorgängen für JPA-Objekte veranschaulicht. Wir haben uns Beispiele für die Verwendung einer nativen Abfrage sowie für die Verwendung von EntityManager # persist angesehen , um benutzerdefinierte INSERT-Anweisungen zu erstellen.

Wie immer ist der vollständige Code, der in diesem Artikel verwendet wird, auf GitHub verfügbar.