Spring Data: ¿se admite "eliminar por"?

99

Estoy usando Spring JPA para acceder a la base de datos. Puedo encontrar ejemplos como findByName y countByName, para los cuales no tengo que escribir ninguna implementación de método. Espero encontrar ejemplos para eliminar un grupo de registros en función de alguna condición.

¿Spring JPA admite la eliminación similar a deleteByName? Se agradece cualquier puntero.

Saludos y gracias.

curioso1
fuente

Respuestas:

184

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

@Modifyinganotación al rescate. Sin embargo, deberá proporcionar su comportamiento SQL personalizado.

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

Actualizar:

En las versiones modernas de la primavera de datos JPA (> = 1.7.x) de derivación para la consulta delete, removey countlas operaciones es accesible.

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}
Andrey Atapin
fuente
2
@AndreyAtapin Downvote porque ya no es una buena respuesta. ¿Quizás eliminarlo? Uno de los defectos de stackoverflows es el manejo de cambios de versión / correcciones de errores asociados con las bibliotecas en cuestión.
Ben George
1
@webgeek, solía resolver este problema con DELETE FROM x WHERE id = ?1 or parent_id = ?1. Por cierto, asegúrese de no tener un tipo de entrada parent__id(¿tiene un guión doble bajo por intención?). Sin embargo, ¿por qué utiliza una opción de consulta nativa?
Andrey Atapin
4
Incluso yo uso 1.7.4, la anotación @Transactional es necesaria arriba del método de consulta para tener una eliminación exitosa
gokhansari
40
Normalmente, en una aplicación, tendrá @ clases / métodos de servicio y estos llamarán a los repositorios. Y los métodos públicos de @ Service deben ser los métodos que están marcados como @ Transactional porque las transacciones se basan en casos de uso. Lo que significa que un caso de uso debe confirmarse o revertirse por completo. No cada método de repositorio individual. Por lo tanto, POR FAVOR, NO use @ Transactional en los métodos de Repositorio. Pero en los métodos de servicio que utilizan el repositorio.
user1567291
1
Hacer @Transactional en el repositorio significa servicio interno si llama al repositorio varias veces, cada una tendrá una transacción diferente, por lo que se revertirá en 1 consulta. Si lo proporciona a nivel de servicio, toda su función se anulará ante cualquier error.
P Satish Patro
78

Se admite la derivación de consultas de eliminación utilizando el nombre de método dado a partir de la versión 1.6.0.RC1 de Spring Data JPA. Las palabras clave removey deleteson compatibles. Como valor de retorno se puede elegir entre el número o una lista de entidades eliminadas.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);
Christoph Strobl
fuente
7

Si echas un vistazo al código fuente de Spring Data JPA, y particularmente a la PartTreeJpaQueryclase, verás que intenta crear una instancia PartTree. Dentro de esa clase, la siguiente expresión regular

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

debe indicar qué está permitido y qué no.

Por supuesto, si intenta agregar un método de este tipo, verá que no funciona y obtendrá el seguimiento de pila completo.

Debo señalar que estaba usando mirando la versión 1.5.0.RELEASEde Spring Data JPA

geo y
fuente
6

2 maneras:-

Primera consulta personalizada

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

2nd one consulta JPA por método

List<User> deleteByLastname(String lastname);

Cuando vaya con la consulta por método (segunda forma), primero hará una llamada get

select * from user where last_name = :firstName

Luego lo cargará en una Lista Luego llamará a eliminar ID uno por uno

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

Primero busque la lista de objetos, luego for loop para eliminar la identificación una por una

Pero, la primera opción (consulta personalizada),

Es solo una consulta. Se eliminará donde exista el valor.

Vaya también a través de este enlace https://www.baeldung.com/spring-data-jpa-deleteby

P Satish Patro
fuente
1
Gracias por la info!
curioso1
2

Si va a utilizar métodos de eliminación predefinidos proporcionados directamente por Spring JPA, el marco ejecutará dos consultas a continuación.

  • Primero recopile datos (como id y otra columna) usando ejecutando la consulta de selección con la cláusula de eliminación de consulta where.

  • luego, después de obtener el resultSet de la primera consulta, las segundas consultas de eliminación se ejecutarán para todos los ID (uno por uno)

    Nota: Esta no es una forma optimizada para su aplicación porque muchas consultas se ejecutarán para una sola consulta de eliminación de MYSQL.

Esta es otra forma optimizada de eliminar código de consulta porque solo se ejecutará una consulta de eliminación utilizando los métodos personalizados a continuación.



@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);
}
Suneet Khurana
fuente
1

Tenga cuidado cuando utilice consultas derivadas para la eliminación por lotes. No es lo que esperabas: DeleteExecution

Andrey Ofim
fuente
Hola. Si está señalando RBAR (fila por fila agonizante), ¿podría agregar eso a su respuesta? (y votaré a favor). Estoy un poco adivinando lo que estás señalando aquí.
granadaCoder
0

Sí, se admite el método deleteBy Para usarlo, debe anotar el método con @Transactional

amoljdv06
fuente