用于接受和连接多个搜索字符串的自定义查询的 Spring Data 方法名称

问题描述 投票:0回答:1

有没有一种方法可以为 Spring Data 中的特殊查询构建自定义存储库方法,该方法接受多个且连接的搜索字符串,这意味着需要在一个数据库字段中找到所有这些字符串?

以这个例子为例,只接受一个字符串:

import java.util.List;

import org.jean.dossier.model.entities.Contact;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ContactRepository extends JpaRepository<Contact, Long> {
    List<Contact> findTop10ByNameContainingOrderByName(String name);
}

在这里,我实质上选择了 contact.name 参数中具有

name
变量内容的所有联系人。我还按名称对结果进行排序,并将输出限制为 10 行。

此搜索仅使用一个参数

name
,即“alfonso”来查找所有名为“alfonso”的联系人。不过,我想要实现的是使用多个字符串进行相同的搜索。

示例:我提供字符串“al”和“du”。查询的可能结果是:

  1. 阿尔方索卡蒂
  2. Malina Perfudu
  3. Galina Padufi

我认为更改上述方法的正确方法如下:

列表 findTop10ByNameContainingOrderByName(String[] name);

有什么办法可以做到吗?

java spring spring-data-jpa spring-data
1个回答
0
投票

显然我正在寻找的东西在 Spring Data 中是不可能的。因此,我的构建有点不同,但仍然达到了我的结果。也许还有另一个人面临着和我一样的问题,所以希望通过这种方式我可以提供一个可能的解决方案。

我向 ContactRepository 添加了一个新的

findAll()
方法,接受规范(用于名称字段的字符串限制)和可分页(用于限制输出行的数量):

import org.jean.dossier.model.entities.Contact;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ContactRepository extends JpaRepository<Contact, Long> {
    Page<Contact> findAll(Specification<Contact> spec, Pageable pageable);
}

为了调用此存储库方法,我创建了一个新服务,在其中准备查询:

import java.util.ArrayList;
import java.util.List;

import org.jean.dossier.data.ContactRepository;
import org.jean.dossier.model.entities.Contact;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import jakarta.persistence.criteria.Predicate;

@Service
public class ContactService {
    
    @Autowired
    private ContactRepository contactRepository;

    private final Logger logger = LoggerFactory.getLogger(ContactService.class);

    public List<Contact> findFirst10ByMultipleStrings(String... searchStrings) {
        this.logger.info("Find contacts using multiple strings.");

        // Sort by attribute "name" ascending.
        Sort sort = Sort.by(Sort.Direction.ASC, "name");

        // Limit to the first 10 lines.
        Pageable pageable = PageRequest.of(0, 10, sort);
        Page<Contact> resultPage = this.contactRepository.findAll(createSpecification(searchStrings), pageable);
        return resultPage.getContent();
    }

    private Specification<Contact> createSpecification(String... searchStrings) {
        this.logger.info("Create specification for query.");

        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            for (String searchString : searchStrings) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + searchString + "%"));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
}

最终,从控制器调用它变得很容易:

@Autowired
private ContactService contactService;

List<Contact> contacts = this.contactService.findFirst10ByMultipleStrings(name.split(" "));
© www.soinside.com 2019 - 2024. All rights reserved.