【问题标题】:Spring JPA repository find all which does not existSpring JPA 存储库找到所有不存在的
【发布时间】:2020-03-18 05:54:08
【问题描述】:

我有一个仓库

public interface PersonRepository extends JpaRepository<Person, Long> {}

实体看起来像这样:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    @Id
    private Long id;
    @NotBlank
    private String name;
}

我想要一个方法来检查数据库表中是否存在所有“人员”,这是我目前所拥有的:

void checkIfAllPersonsExist(List<Long> personIds) {
    var persons = personRepository.findAllById(personIds);
    if (personIds.size() != persons.size()) {
        personIds.removeAll(persons.stream().map(Persons::getId).collect(toList()));
        throw new NotFoundException("Persons with id's [id:%s] does not exist", personIds);
    }
}

我想知道 Spring JPA Repository 是否可以提供更优雅的东西?像返回不存在的 id 的特定命名查询一样?

【问题讨论】:

  • 为什么 JpaRepository&lt;Person, String&gt; {} 的 ID 是 String 而不是 Long
  • @lczapski 这只是一个错字,我已经编辑了问题。

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


【解决方案1】:

如果你只想知道有些 id 不存在,你可以数一数

@Query("select COUNT(p.id) from Person p where p.id in :ids")
Long countIds(List<Long> ids);

或等效的based on

long countByIdIn(Collection<Long> ids);

或者返回存在的id列表

@Query("select p.id from Person p where p.id in :ids")
List<Long> getExistenIds(List<Long> ids);

然后过滤掉你需要的东西。

personIds.removeAll(personRepository.getExistenIds(personIds));
if (!personIds.isEmpty()) {
    throw new NotFoundException("Persons with id's [id:%s] does not exist", personIds);
}

【讨论】:

    【解决方案2】:

    首先,您的存储库应该扩展 JpaRepository&lt;Person, Long&gt; 而不是 JpaRepository&lt;Person, String &gt;,因为您的实体的 id 类型是 Long

    InNotIn 关键字可以帮助您实现目标。请在本文档中查看它们:Query Creation - Spring Data JPA - Reference Documentation

    我稍微修改了你的代码,它对我有用。

    存储库类:

    public interface PersonRepository extends JpaRepository<Person, Long> {
        List<Person> findByIdIn(Collection<Long> ids);
    }
    

    还有示例 sn-p:

    @Component
    public class Bootstrap implements CommandLineRunner {
        @Autowired
        private PersonRepository repository;
    
        @Override
        public void run(String... args) throws Exception {
            savePersons();
    
            testFindMethod();
        }
    
        private void savePersons() {
            Person person1 = Person.builder().id(1L).name("Name 1").build();
            Person person2 = Person.builder().id(2L).name("Name 2").build();
            Person person3 = Person.builder().id(3L).name("Name 3").build();
            Person person4 = Person.builder().id(4L).name("Name 4").build();
    
            repository.save(person1);
            repository.save(person2);
            repository.save(person3);
            repository.save(person4);
        }
    
        private void testFindMethod() {
            List<Long> toFind = new ArrayList<>();
            toFind.add(1L);
            toFind.add(2L);
            toFind.add(3L);
            checkIfAllPersonsExist(toFind);
    
            toFind.add(7L);
            checkIfAllPersonsExist(toFind);
        }
    
        void checkIfAllPersonsExist(List<Long> personIds) {
            List<Person> persons = repository.findByIdIn(personIds);
            if (personIds.size() != persons.size()) {
                System.out.println("Sizes are different");
            } else {
                System.out.println("Sizes are same!");
            }
        }
    }
    

    这是控制台输出:

    Sizes are same!
    Sizes are different
    

    希望对你有帮助。

    【讨论】:

    • 这很好,但这不是我想要的。您只需检查所有 id 是否存在,我想知道哪个不存在。此外,我只想返回 Id 的不完整实体。但是感谢您的意见,干得好。
    • 我可以清楚地看到你的问题:I want to have a method which checks if all "persons" exist in database table by id
    【解决方案3】:

    使用这个 JPA 存储库方法,您可以获取 id 不存在的元素:

    List<Person> findByIdNotIn(List<Long> personIds);
    

    如果你想像你的例子一样删除它们,你可以使用这个:

    List<Person> deleteByIdNotIn(List<Long> personIds);
    

    希望对你有帮助!

    【讨论】:

    • 这个答案是错误的findByIdNotIn 与预期结果不符。为什么还要投票呢?
    猜你喜欢
    • 2020-09-09
    • 2018-10-15
    • 2015-06-19
    • 2019-01-04
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    相关资源
    最近更新 更多