Spring Data: "Elimina entro" è supportato?


99

Sto usando Spring JPA per l'accesso al database. Sono in grado di trovare esempi come findByName e countByName, per i quali non devo scrivere alcuna implementazione del metodo. Spero di trovare esempi per eliminare un gruppo di record in base a qualche condizione.

Spring JPA supporta l'eliminazione di tipo deleteByName? Qualsiasi suggerimento è apprezzato.

Saluti e grazie.

Risposte:


184

Risposta obsoleta (Spring Data JPA <= 1.6.x) :

@Modifyingannotazione in soccorso. Tuttavia, dovrai fornire il tuo comportamento SQL personalizzato.

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

Aggiornare:

Nelle versioni moderne di primavera dati JPA (> = 1.7.x) di query di derivazione per delete, removee countle operazioni è accessibile.

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvote perché non è più una buona risposta. Forse cancellarlo? Uno dei difetti di stackoverflows è la gestione delle modifiche alla versione / correzioni di bug associate alle librerie in questione.
Ben George

1
@webgeek, ho risolto questo problema con DELETE FROM x WHERE id = ?1 or parent_id = ?1. A proposito, assicurati di non avere un tipo in parent__id(hai il doppio trattino basso intenzionalmente?). Perché usi un'opzione di query nativa?
Andrey Atapin

4
Anche io uso 1.7.4, l'annotazione @Transactional è necessaria sopra il metodo di query per avere un'eliminazione corretta
gokhansari

40
In genere, in un'applicazione, si avranno classi / metodi @ Service e quelli chiameranno i repository. E i metodi pubblici @ Service dovrebbero essere i metodi contrassegnati con @ Transactional perché le transazioni sono basate sul caso d'uso. Significa che un caso d'uso deve essere completamente commesso o ripristinato. Non ogni singolo metodo di repository. Quindi, PER FAVORE, NON utilizzare @ Transactional sui metodi di repository. Ma sui metodi di servizio che utilizzano il repository.
user1567291

1
Fare @Transactional in repo significa all'interno del servizio se chiami repo più volte ognuno avrà una transazione diff, quindi rollback entro 1 query. Se fornisci a livello di servizio, l'intera funzione verrà ripristinata in caso di errore.
P Satish Patro

78

La derivazione delle query di eliminazione utilizzando il nome del metodo specificato è supportata a partire dalla versione 1.6.0.RC1 di Spring Data JPA. Le parole chiave removee deletesono supportate. Come valore di ritorno si può scegliere tra il numero o un elenco di entità rimosse.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

Se dai un'occhiata al codice sorgente di Spring Data JPA, e in particolare alla PartTreeJpaQueryclasse, vedrai che sta cercando di istanziare PartTree. All'interno di quella classe la seguente espressione regolare

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

dovrebbe indicare cosa è consentito e cosa no.

Ovviamente se provi ad aggiungere un tale metodo vedrai effettivamente che non funziona e ottieni lo stacktrace completo.

Dovrei notare che stavo usando guardando la versione 1.5.0.RELEASEdi Spring Data JPA


6

2 modi: -

La prima query personalizzata

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

Secondo JPA Query per metodo

List<User> deleteByLastname(String lastname);

Quando vai con la query per metodo (secondo metodo), prima eseguirà una chiamata get

select * from user where last_name = :firstName

Quindi lo caricherà in una lista Quindi chiamerà delete id uno per uno

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

Prima recupera l'elenco di oggetti, quindi for loop per eliminare gli id ​​uno per uno

Ma la prima opzione (query personalizzata),

È solo una singola query Eliminerà ovunque il valore esista.

Vai anche attraverso questo link https://www.baeldung.com/spring-data-jpa-deleteby


1
Grazie per le informazioni!
curioso 1

2

Se si utilizzano metodi di eliminazione predefiniti forniti direttamente da Spring JPA, il framework eseguirà le due query di seguito.

  • Per prima cosa raccogli i dati (come id e altre colonne) usando eseguendo la query di selezione con la clausola di cancellazione della query.

  • quindi dopo aver ottenuto il set di risultati della prima query, verranno eseguite le seconde query di eliminazione per tutti gli ID (una per una)

    Nota: questo non è un modo ottimizzato per la tua applicazione perché molte query verranno eseguite per una singola query di eliminazione MYSQL.

Questo è un altro modo ottimizzato per eliminare il codice della query perché verrà eseguita solo una query di eliminazione utilizzando i metodi personalizzati di seguito.



@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

Prestare attenzione quando si utilizza la query derivata per l'eliminazione in batch. Non è quello che ti aspetti: DeleteExecution


Ciao. Se stai indicando RBAR (riga per riga agonizzante), potresti aggiungerlo alla tua risposta? (e io voterò a favore). Sto indovinando quello che stai indicando qui.
granadaCoder

0

Sì, il metodo deleteBy è supportato Per usarlo è necessario annotare il metodo con @Transactional

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.