【问题标题】:Spring Data: "delete by" is supported?Spring Data:支持“删除”?
【发布时间】:2014-07-06 13:03:55
【问题描述】:

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

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

问候和感谢。

【问题讨论】:

    标签: spring spring-data spring-data-jpa


    【解决方案1】:

    不推荐使用的答案(Spring Data JPA :

    @Modifying 注释来救援。不过,您需要提供您的自定义 SQL 行为。

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

    更新:

    在 Spring Data 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);
    
    }
    

    【讨论】:

    • @AndreyAtapin Downvote 因为它不再是一个好的答案。也许删除它? stackoverflows 的缺陷之一是处理与相关库相关的版本更改/错误修复。
    • @webgeek,我曾经用DELETE FROM x WHERE id = ?1 or parent_id = ?1 解决这个问题。顺便说一句,请确保您在parent__id 中没有类型(您是否有意使用双低破折号?)。你为什么要使用原生查询选项?
    • 即使我用的是1.7.4,查询方法上面也需要@Transactional注解才能成功删除
    • 通常,在应用程序中,您将拥有@Service 类/方法,并且它们将调用存储库。而@Service 公共方法应该是标记为@Transactional 的方法,因为事务是基于用例的。这意味着用例需要完全提交或回滚。不是每个单独的存储库方法。所以请不要在存储库方法上使用@Transactional。但是在使用存储库的服务方法上。
    • 在 repo 上创建 @Transactional 意味着如果您多次调用 repo 每次都会有差异事务,因此在 1 个查询内回滚。如果您在服务级别提供,您的整个功能将在任何错误时回滚。
    【解决方案2】:

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

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

    应该指出什么是允许的,什么是不允许的。

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

    我应该注意到我正在查看 Spring Data JPA 的 1.5.0.RELEASE 版本

    【讨论】:

      【解决方案3】:

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

      Long removeByLastname(String lastname);
      
      List<User> deleteByLastname(String lastname);
      

      【讨论】:

        【解决方案4】:

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

        • 首先使用带删除查询where子句的执行选择查询收集数据(如id和其他列)。

        • 然后在获得第一个查询的结果集后,将对所有 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);
        }
        
        

        【讨论】:

          【解决方案5】:

          使用派生查询进行批量删除时要小心。 这不是你所期望的:DeleteExecution

          【讨论】:

          • 嗨。如果您指出 RBAR(逐行痛苦),您能否将其添加到您的答案中? (我会投票)。我有点猜到你在这里指出了什么。
          • 您能否更明确地阐明您的意思?
          【解决方案6】:

          两种方式:-

          第一个自定义查询

          @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
          

          先获取对象列表,然后for循环逐个删除id

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

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

          由于第二个选项是进行多个数据库查询,请尝试使用第一个选项。

          也可以通过这个链接https://www.baeldung.com/spring-data-jpa-deleteby

          【讨论】:

          • 感谢您的信息!
          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            下面是我的 2 美分。您还可以使用本机查询,例如:

            @Modifying
            @Query(value="delete from rreo r where r.cod_ibge = ?1 and r.exercicio= ?2", nativeQuery = true)
            void deleteByParameters(Integer codIbge, Integer exercicio);
            

            【讨论】:

              【解决方案9】:
              @Query(value = "delete from addresses u where u.ADDRESS_ID LIKE %:addressId%", nativeQuery = true)
              void deleteAddressByAddressId(@Param("addressId") String addressId);
              

              【讨论】:

              • 欢迎来到 Stack Overflow。在回答已接受答案的旧问题(寻找绿色✓)以及其他答案之前,请确保您的答案添加了新内容或对它们有帮助。同样,只是发布没有任何解释的代码并没有太大帮助,因为它没有解释为什么或如何回答问题。请include an explanation for your code 提高您的帖子质量。另请参考How do I write a good answer?
              【解决方案10】:

              它只是工作

              import org.springframework.transaction.annotation.Transactional;
              
                  @Transactional
                  Long removeAddressByCity(String city);
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-03-10
                • 1970-01-01
                • 1970-01-01
                • 2016-03-25
                • 1970-01-01
                • 2023-03-24
                • 2018-06-20
                • 2018-11-23
                相关资源
                最近更新 更多