Frühlingsdaten: "Löschen von" wird unterstützt?


99

Ich verwende Spring JPA für den Datenbankzugriff. Ich kann Beispiele wie findByName und countByName finden, für die ich keine Methodenimplementierung schreiben muss. Ich hoffe, Beispiele für das Löschen einer Gruppe von Datensätzen zu finden, die auf einer bestimmten Bedingung basieren.

Unterstützt Spring JPA deleteByName-like delete? Jeder Zeiger wird geschätzt.

Grüße und danke.

Antworten:


184

Veraltete Antwort (Spring Data JPA <= 1.6.x) :

@ModifyingAnmerkung zur Rettung. Sie müssen jedoch Ihr benutzerdefiniertes SQL-Verhalten angeben.

public interface UserRepository extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.firstName = ?1")
    void deleteUsersByFirstName(String firstName);
}

Aktualisieren:

In modernen Versionen von Spring Data JPA (> = 1.7.x) Abfrage Ableitung für delete, removeund countOperationen zugänglich ist .

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvote, weil es keine gute Antwort mehr ist. Vielleicht löschen? Einer der Fehler bei Stackoverflows ist die Behandlung von Versionsänderungen / Bugfixes, die mit den betreffenden Bibliotheken verbunden sind.
Ben George

1
@webgeek, ich habe dieses Problem mit gelöst DELETE FROM x WHERE id = ?1 or parent_id = ?1. Übrigens, stellen Sie sicher, dass Sie keine Eingabe haben parent__id(haben Sie absichtlich einen doppelten niedrigen Strich?). Warum verwenden Sie jedoch eine native Abfrageoption?
Andrey Atapin

4
Sogar ich benutze 1.7.4, @Transactional Annotation wird über der Abfragemethode benötigt, um erfolgreich zu
löschen

40
In der Regel verfügen Sie in einer Anwendung über @ Service-Klassen / -Methoden, die die Repositorys aufrufen. Und öffentliche @ Service-Methoden sollten die Methoden sein, die mit @ Transactional gekennzeichnet sind, da Transaktionen auf Anwendungsfällen basieren. Dies bedeutet, dass ein Anwendungsfall vollständig festgeschrieben oder zurückgesetzt werden muss. Nicht jede einzelne Repository-Methode. Verwenden Sie daher BITTE NICHT @ Transactional für Repository-Methoden. Aber auf den Dienstmethoden, die das Repository verwenden.
user1567291

1
Wenn Sie @Transactional bei Repo ausführen, bedeutet dies, dass Sie innerhalb des Dienstes, wenn Sie Repo mehrmals aufrufen, jeweils eine unterschiedliche Transaktion haben. Führen Sie also ein Rollback innerhalb einer Abfrage durch. Wenn Sie auf Service-Ebene bereitstellen, wird Ihre gesamte Funktion bei jedem Fehler zurückgesetzt.
P Satish Patro

78

Die Ableitung von Löschabfragen unter Verwendung des angegebenen Methodennamens wird ab Version 1.6.0.RC1 von Spring Data JPA unterstützt. Die Schlüsselwörter removeund deletewerden unterstützt. Als Rückgabewert kann zwischen der Anzahl oder einer Liste entfernter Entitäten gewählt werden.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

Wenn Sie sich den Quellcode von Spring Data JPA und insbesondere die PartTreeJpaQueryKlasse ansehen, werden Sie feststellen, dass versucht wird, diese zu instanziieren PartTree. Innerhalb dieser Klasse der folgende reguläre Ausdruck

private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

sollte angeben, was erlaubt ist und was nicht.

Wenn Sie versuchen, eine solche Methode hinzuzufügen, werden Sie natürlich feststellen, dass dies nicht funktioniert, und Sie erhalten die vollständige Stapelverfolgung.

Ich sollte beachten, dass ich die Version 1.5.0.RELEASEvon Spring Data JPA verwendet habe


6

2 Wege:-

1. eine benutzerdefinierte Abfrage

@Modifying
@Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(@Param("firstName") String firstName);

2. JPA-Abfrage nach Methode

List<User> deleteByLastname(String lastname);

Wenn Sie mit der Abfrage nach Methode (2. Weg) fortfahren, wird zuerst ein get-Aufruf ausgeführt

select * from user where last_name = :firstName

Dann wird es in eine Liste geladen. Dann wird nacheinander die Lösch-ID aufgerufen

delete from user where id = 18
delete from user where id = 19

Zuerst die Liste des Objekts abrufen, dann die for-Schleife, um die ID nacheinander zu löschen

Aber die 1. Option (benutzerdefinierte Abfrage),

Es ist nur eine einzige Abfrage. Sie wird gelöscht, wo immer der Wert vorhanden ist.

Gehen Sie auch über diesen Link https://www.baeldung.com/spring-data-jpa-deleteby


1
Danke für die Information!
neugierig1

2

Wenn Sie vordefinierte Löschmethoden verwenden, die direkt von Spring JPA bereitgestellt werden, werden im Folgenden zwei Abfragen vom Framework ausgeführt.

  • Sammeln Sie zuerst Daten (wie ID und andere Spalte), indem Sie eine Auswahlabfrage mit einer Löschabfrage-Where-Klausel ausführen.

  • Nachdem Sie die Ergebnismenge der ersten Abfrage erhalten haben, werden die zweiten Löschabfragen für alle IDs ausgeführt (eine nach der anderen).

    Hinweis: Dies ist keine für Ihre Anwendung optimierte Methode, da viele Abfragen für einzelne MYSQL-Löschabfragen ausgeführt werden.

Dies ist eine weitere optimierte Methode zum Löschen von Abfragecode, da nur eine Löschabfrage mithilfe der folgenden benutzerdefinierten Methoden ausgeführt wird.



@NamedNativeQueries({

@NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
            query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
    ,

    @NamedNativeQuery(name = "Abc.getByMaxId",
            query = "SELECT max(id) from abc")
})

@Entity
public class Abc implements Serializable {

}

@Repository
public interface AbcRepository extends CrudRepository {

    int getByMaxId();

    @Transactional
    @Modifying
    void deleteByCreatedTimeBetween(String startDate, String endDate);
}

1

Seien Sie vorsichtig, wenn Sie abgeleitete Abfragen zum Löschen von Stapeln verwenden. Es ist nicht das, was Sie erwarten: DeleteExecution


Hallo. Wenn Sie auf RBAR (Zeile durch quälende Zeile) hinweisen, können Sie dies Ihrer Antwort hinzufügen? (und ich werde abstimmen). Ich rate ein bisschen, worauf Sie hier hinweisen.
GranadaCoder

0

Ja, die deleteBy-Methode wird unterstützt. Um sie zu verwenden, müssen Sie die Methode mit @Transactional kommentieren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.