JPA Query с несколькими столбцами, если пустые данные столбца игнорируют столбцы в запросе и данных [дубликат]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

24
задан Mr.Chowdary 5 March 2015 в 10:34
поделиться

2 ответа

Вы можете использовать Спецификации, которые Spring-data дает вам из коробки. и иметь возможность использовать критерии API для создания запросов программным способом. Для поддержки спецификаций вы можете расширить свой интерфейс репозитория с помощью интерфейса JpaSpecificationExecutor

public interface CustomerRepository extends SimpleJpaRepository<T, ID>, JpaSpecificationExecutor {

}

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

Например, метод findAll возвращает все сущности, соответствующие спецификации:

List<T> findAll(Specification<T> spec);

Интерфейс спецификации выглядит следующим образом:

public interface Specification<T> {
     Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
            CriteriaBuilder builder);
}

Хорошо, так какой типичный вариант использования? Спецификации могут быть легко использованы для создания расширяемого набора предикатов на вершине объекта, который затем может быть объединен и использован с JpaRepository без необходимости объявлять запрос (метод) для каждой необходимой комбинации. Вот пример: Пример 2.15. Спецификации для клиента

public class CustomerSpecs {
    public static Specification<Customer> isLongTermCustomer() {
        return new Specification<Customer>() {
            public Predicate toPredicate(
                Root<Customer> root, CriteriaQuery<?> query,
                CriteriaBuilder builder) {
                LocalDate date = new LocalDate().minusYears(2);
                return builder.lessThan(root.get('dateField'), date);
            }
        };
    }

    public static Specification<Customer> hasSalesOfMoreThan(MontaryAmount value) {
        return new Specification<Customer>() {
            public Predicate toPredicate(
                Root<T> root, CriteriaQuery<?> query,
                CriteriaBuilder builder) {
                // build query here
            }
        };
    }
}

Вы указали некоторые критерии уровня абстракции бизнес-требований и создали исполняемые спецификации. Таким образом, клиент может использовать Спецификацию следующим образом:

List customers = customerRepository.findAll(isLongTermCustomer());

Вы также можете комбинировать пример спецификации 2.17. Комбинированные спецификации

    MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR);
    List<Customer> customers = customerRepository.findAll(
        where(isLongTermCustomer()).or(hasSalesOfMoreThan(amount)));

Как вы можете видеть, спецификации предлагают некоторые методы клея-кода для объединения и комбинирования спецификаций. Таким образом, расширение уровня доступа к данным - это просто вопрос о создании новых спецификаций спецификаций и их объединении с уже существующими.

И вы можете создавать сложные спецификации, вот пример

public class WorkInProgressSpecification {
    public static Specification<WorkInProgress> findByCriteria(final SearchCriteria searchCriteria) {

        return new Specification<WorkInProgress>() {

            @Override
            public Predicate toPredicate(
                Root<WorkInProgress> root,
                CriteriaQuery<?> query, CriteriaBuilder cb) {

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

                if (searchCriteria.getView() != null && !searchCriteria.getView().isEmpty()) {
                    predicates.add(cb.equal(root.get("viewType"), searchCriteria.getView()));
                }
                if (searchCriteria.getFeature() != null && !searchCriteria.getFeature().isEmpty()) {
                    predicates.add(cb.equal(root.get("title"), searchCriteria.getFeature()));
                }
                if (searchCriteria.getEpic() != null && !searchCriteria.getEpic().isEmpty()) {
                    predicates.add(cb.equal(root.get("epic"), searchCriteria.getEpic()));
                }
                if (searchCriteria.getPerformingGroup() != null && !searchCriteria.getPerformingGroup().isEmpty()) {
                    predicates.add(cb.equal(root.get("performingGroup"), searchCriteria.getPerformingGroup()));
                }
                if (searchCriteria.getPlannedStartDate() != null) {
                    System.out.println("searchCriteria.getPlannedStartDate():" + searchCriteria.getPlannedStartDate());
                    predicates.add(cb.greaterThanOrEqualTo(root.<Date>get("plndStartDate"), searchCriteria.getPlannedStartDate()));
                }
                if (searchCriteria.getPlannedCompletionDate() != null) {
                    predicates.add(cb.lessThanOrEqualTo(root.<Date>get("plndComplDate"), searchCriteria.getPlannedCompletionDate()));
                }
                if (searchCriteria.getTeam() != null && !searchCriteria.getTeam().isEmpty()) {
                    predicates.add(cb.equal(root.get("agileTeam"), searchCriteria.getTeam()));
                }

                return cb.and(predicates.toArray(new Predicate[] {}));
            }
        };
    }
}

Здесь JPA Respositories docs

21
ответ дан EpicPandaForce 18 August 2018 в 14:03
поделиться
  • 1
    В настоящее время мы использовали версию 3.2.5. – EpicPandaForce 5 March 2015 в 11:29
  • 2
    Здесь также было руководство по этому вопросу (дополнительная информация о тестировании, например): petrikainulainen.net/programming/spring-framework/… и изначально здесь: spring.io/blog / 2011/04/26 / & hellip; – EpicPandaForce 5 March 2015 в 14:27
  • 3
    Я уверен, что вы можете получить метамодель, сгенерированный таким образом, что вам не нужно указывать свойства со строками. – EpicPandaForce 5 March 2015 в 20:29
  • 4
    Вы абсолютно правы, QueryDSL стоит рассмотреть для запросов типа безопасности – iamiddy 5 March 2015 в 22:29
  • 5
    Даже не в QueryDsl, я думаю, вы можете создать метамодель для корней в API критериев. согласно сообщению в блоге здесь spring.io/blog/2011/04/26/… они, похоже, создают метамодель, которая позволяет root.get(WorkInProgress_.agileTeam) вместо root.get("agileTeam"). В конце концов, строка является проблематичной. – EpicPandaForce 6 March 2015 в 00:28
  • 6
    Отлично .. Он отлично работает. Я не знал о BooleanBuilder .. После хорошего примера с ним теперь узнал, что может сделать Querydsl .. Спасибо за ваше драгоценное время .. – Mr.Chowdary 6 March 2015 в 02:57
  • 7
    – Mr.Chowdary 6 March 2015 в 03:02
  • 8
    Добро пожаловать, рад помочь: D Spring Data с QueryDSL поражает. – EpicPandaForce 6 March 2015 в 08:23
  • 9
    информация о генерации метамодели: stackoverflow.com/questions/3037593/… – EpicPandaForce 7 March 2015 в 03:16
  • 10
    хороший проект, упростить использование jpa – zhaozhi 1 September 2016 в 09:59

Из Spring Data JPA 1.10 есть еще один вариант для этого: Query By Example . Ваш репозиторий должен реализовывать помимо JpaRepository также интерфейс QueryByExampleExecutor , где вы получаете такие методы, как:

<S extends T> Iterable<S> findAll(Example<S> example)

Затем вы создаете пример для поиска например:

Employee e = new Employee();
e.setEmployeeNumber(getEmployeeNumberSomewherFrom());
e.setName(getNameSomewhereFrom());
e.setMarried(getMarriedSomewhereFrom());
e.setProfession(getProfessionSomewhereFrom());
e.setDateOfBirth(getDateOfBirthSomewhereFrom());

, а затем:

employeeRepository.findAll(Example.of(e));

Если некоторые параметры равны нулю, они не будут приняты в предложение WHERE, поэтому вы получите динамические запросы.

Чтобы уточнить соответствие атрибутов String, просмотрите ExampleMatcher

. А ExampleMatcher, который делает регистр без учета регистра like, например:

ExampleMatcher matcher = ExampleMatcher.matching().
          withMatcher("profession", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.CONTAINING).ignoreCase());

Примеры QBE: https://github.com/spring-projects/spring-data-examples/tree/master/jpa/query-by-example

14
ответ дан Robert Niestroj 18 August 2018 в 14:03
поделиться
  • 1
    Query By Example выглядит очень хорошо и подходит для многих случаев, но, к сожалению, у него есть один недостаток, о котором стоит упомянуть. Невозможно определить условие типа LESS THAN, GREATER THAN, BETWEEN и т. Д., Используя Query By Example. Таким образом, вы не можете определить, что какая-то дата или некоторое число должно быть в определенных границах. Он упоминается в официальной документации в разделе Ограничения: Only supports starts/contains/ends/regex matching for strings and exact matching for other property types. – luke 31 March 2017 в 20:29
  • 2
    QueryByExample также не делает соединение, если есть одно для многих судов отношений. Как например, у меня есть сущность POST, и у меня есть другое задание POSTComments, где у одного сообщения может быть много комментариев. В этом случае и скажем, что я ищу POST имея статус, активно некоторые поля, которые я ищу в объекте POST. Сначала он получает все сообщения с критериями, а затем делает запрос выбора на дочерний объект. Как получить PostComments, где postid это. Если он выбирает, позволяет сказать 100 сообщений, тогда он делает еще 100 выборок, чтобы получить дочерние объекты, которые кажутся неэффективными – swati 15 August 2017 в 20:06
Другие вопросы по тегам:

Похожие вопросы: