Spring Data:支持“删除依据”吗?


99

我正在使用Spring JPA进行数据库访问。我能够找到诸如findByName和countByName之类的示例,对于这些示例,我不必编写任何方法实现。我希望找到一些根据某些条件删除一组记录的示例。

Spring JPA是否支持类似于deleteByName的删除?任何指针表示赞赏。

谢谢,谢谢。

Answers:


184

不建议使用的答案(Spring Data JPA <= 1.6.x)

@Modifying营救的注解。但是,您将需要提供自定义SQL行为。

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

更新:

在现代版本的春天数据JPA(> = 1.7.x)查询推导的deleteremovecount操作是可访问的。

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvote,因为它不再是一个好答案。也许删除它?stackoverflows的缺陷之一是处理与相关库相关的版本更改/错误修正。
本·乔治

1
@webgeek,我曾经用解决此问题DELETE FROM x WHERE id = ?1 or parent_id = ?1。顺便说一句,请确保您没有输入parent__id(您是否故意输入双下划线?)。为什么要使用本机查询选项?
安德烈·阿塔芬

4
即使我使用1.7.4,查询方法上方也需要@Transactional注释才能成功删除
gokhansari

40
通常,在应用程序中,您将具有@服务类/方法,而这些类/方法将调用存储库。@ Service公共方法应该是标记为@ Transactional的方法,因为事务是基于用例的。意味着用例需要完全提交或回滚。不是每个单独的存储库方法。因此,请不要在存储库方法上使用@ Transactional。但是在使用存储库的Service方法上。
user1567291

1
在回购中进行@Transactional意味着如果您多次调用回购,则每个服务都会有差异事务,因此在服务内部,因此在1个查询内回滚。如果您提供服务级别的服务,则所有功能都会在出现任何错误时回滚。
P Satish Patro

78

从Spring Data JPA的1.6.0.RC1版本开始,支持使用给定方法名称派生删除查询。支持关键字removedelete。作为返回值,可以在数字或已删除实体的列表之间进行选择。

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

如果您看一下Spring Data JPA的源代码,特别是 PartTreeJpaQuery该类,您将看到它试图实例化PartTree。在该类中,以下正则表达式

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

应该指出允许的内容和不允许的内容。

当然,如果您尝试添加这样的方法,则实际上会发现该方法不起作用,并且会获得完整的堆栈跟踪。

我应该注意,我使用的1.5.0.RELEASE是Spring Data JPA 版本


6

2种方式:-

第一个自定义查询

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

方法的第二个JPA查询

List<User> deleteByLastname(String lastname);

当您通过方法(第二种方法)进行查询时,它将首先进行get调用

select * from user where last_name = :firstName

然后将其加载到列表中,然后将其一一调用delete id

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

首先获取对象列表,然后进行循环以逐个删除ID

但是,第一个选项(自定义查询)

这只是一个查询,它将删除该值存在的任何位置。

也通过此链接https://www.baeldung.com/spring-data-jpa-deleteby


1
谢谢(你的)信息!
curious1

2

如果您将使用由Spring JPA直接提供的预定义删除方法,则框架将执行以下两个查询。

  • 首先通过执行select查询和delete查询where子句来收集数据(如id和其他列)。

  • 然后在获得第一个查询的resultSet之后,将对所有id(一个接一个)执行第二个删除查询

    注意:这不是针对您的应用程序的优化方法,因为将对单个MYSQL删除查询执行许多查询。

这是删除查询代码的另一种优化方法,因为使用以下自定义方法将仅执行一个删除查询。



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


0

是的,支持deleteBy方法要使用它,您需要使用@Transactional注释方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.