Как написать запрос, используя только определенные части объекта с помощью Spring JPA - PullRequest
1 голос
/ 22 апреля 2020

Я чувствую, что это должно быть довольно просто, но я не уверен насчет реального кода для него. По сути, мой контроллер покоя принимает 6 аргументов, передает их через Сервис, а затем использует эти аргументы для построения объекта внутри ServiceImplementation. Оттуда я возвращаю вызов в мой репо, используя только что сделанный объект. Этот вызов должен попытаться запросить базу данных, указав c параметры объекта.

В этом запросе я не уверен, как писать, используя стандарты Spring JPA. Я хотел бы просто использовать переменные, для которых я установил свой объект, но я не уверен, придется ли мне выписывать запрос или если Spring JPA может сделать его немного проще?

Код :

Контроллер:

@RestController
public class exampleController {

    @Autowired
    private ExampleService exampleService;

    @GetMapping("/rest/example/search")
    public exampleObj searchExample (@RequestParam(value = "exLetter") String exLetter,
            @RequestParam(value = "exLang") String exLang, @RequestParam(value = "exType")int exType, 
            @RequestParam(value = "exMethod") String exMethod, @RequestParam(value = "exCd") String exCd,
            @RequestParam(value = "exOrg") String exOrg) {

        return exampleService.getExampleLetter(exLetter, exLang, exType, exMethod, exCd, exOrg);
    }
}

ExampleSerivce:

public interface ExampleService {

    public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg);
}

ExampleServiceImplementation:

@Service
public class ExampleServiceImpl implements ExampleService {
    @Autowired
    private ExampleRepository exampleRepo;

    @Override
    public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg) {

        ExampleLetter examp = new ExampleLetter();

        examp.setExCd(exCd);
        examp.getKey().setExampleNumber(exLetter);
        examp.getKey().setLanguageType(exLang);
        examp.getKey().setMethod(exMethod);
        examp.getKey().setMarketOrg(exOrg);
        examp.getKey().setType(exType);

        return exampleRepo.findExampleLetter(examp);
    }   
}

Репо:

@Repository
public interface ExampleRepository extends CrudRepository<ExampleLetter, ExampleLetterKey> {

}

1 Ответ

1 голос
/ 22 апреля 2020

Если я правильно понимаю, вы пытаетесь сделать запрос c dinami, основанный на фильтрации значений, которые могут быть или не быть там. В этом случае вы можете использовать класс Specification для динамического создания запроса:

Сначала в вашем классе репозитория выполните расширение JpaSpecificationExecutor<ExampleLetter>:

@Repository
public interface ExampleRepository extends CrudRepository<ExampleLetter, ExampleLetterKey>, JpaSpecificationExecutor<ExampleLetter> {

}  

Теперь вы нужен метод (я бы посоветовал вам поместить его в специфицированный c класс для организации) для генерации самого запроса:

public class GenerateQueryForExampleLetter {

    ExampleLetter exampleLetter;

    public Specification<ExampleLetter> generateQuery() {
        return new Specification<ExampleLetter>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<ExampleLetter> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Predicate pred = null;

                List<Predicate> predicates = new ArrayList<Predicate>();

                if (this.exampleLetter.getExCd()!= null && !this.exampleLetter.getExCd().isEmpty()) {
                    predicates.add(builder.equal(root.<String>get("exCd"), this.exampleLetter.getExCd()));
                }

    ...................

                if (this.exampleLetter.getTheFieldYouNeed()!= null && !getTheFieldYouNeed.isEmpty()) {
                    predicates.add(builder.equal(root.<TheTypeOfTheField>get("theFieldYouNeed"), this.exampleLetter.getTheFieldYouNeed()));
                }


                if (!predicates.isEmpty()) {
                    pred = builder.and(predicates.toArray(new Predicate[] {}));
                }

                return pred;
            }
        };
    }

    public void setExampleLetter (ExampleLetter el) {
        this.exampleLetter = el;
    }
}

Наконец, в вашем классе обслуживания:

@Override
public ExampleLetter getExampleLetter(String exLetter, String exLang, int exType, String exMethod, String exCd, String exOrg) {

    ExampleLetter examp = new ExampleLetter();

    examp.setExCd(exCd);
    examp.getKey().setExampleNumber(exLetter);
    examp.getKey().setLanguageType(exLang);
    examp.getKey().setMethod(exMethod);
    examp.getKey().setMarketOrg(exOrg);
    examp.getKey().setType(exType);

    GenerateQueryForExampleLetter queryGenerator = new GenerateQueryForExampleLetter ();

    queryGenerator.setExampleLetter(examp);

    return exampleRepo.findAll(queryGenerator.generateQuery());
}

Обратите внимание, что интерфейс JpaSpecificationExecutor добавляет для вас несколько служебных методов, которые помимо фильтрации поддерживают сортировку и разбиение на страницы.

Для получения более подробной информации, проверьте здесь , здесь или этот ответ.

...