Java vs SQL при извлечении данных

#java #sql

#java #sql

Вопрос:

У меня есть таблица, в которой я сохранил некоторые параметры, которые действуют как логика для принятия решения о том, какой «приемник» выбрать. Я проиллюстрировал содержимое / данные этой таблицы ниже:

содержимое таблицы

Для выбора правильного получателя я использовал следующий SQL:

 SELECT *
FROM tableOfReceivers
WHERE client = 'DU'
      AND (country = countryOfDestination OR '*' = countryOfDestination)
      AND (
        (packages >= minNumberOfPackages OR minNumberOfPackages IS NULL) AND
        (packages <= maxNumberOfPackages OR maxNumberOfPackages IS NULL)
      )
      AND (
        (weight >= minNetWeight OR minNetWeight IS NULL) AND
        (weight <= maxNetWeight OR maxNetWeight IS NULL)
      )
ORDER BY priority;
  

Переменные для приведенного выше SQL:

 country = BE
packages = 5
weight = 50
  

SQL работает нормально, и я получаю желаемый результат. Но мне нужно перевести это на Java, и при этом я чувствую, что это слишком сложно, и я думаю, что должно быть проще, что для этого нужно сделать.

Вот код Java, который я сейчас использую:

 ArrayList<tableOfReceivers > listOfReceivers = getPersistenceManager().getQueryManager().queryAll(
            tableOfReceivers.class, "this.client = ?1", "this.client", new Object[] { client }, 0);

ArrayList<tableOfReceivers> result = new ArrayList<tableOfReceivers>();

for (tableOfReceivers  rec : listOfReceivers) {
    if ((StringUtils.equals(countryOfDestination, rec.getCountryOfDestination())
            || StringUtils.equals("*", rec.getCountryOfDestination()))) {

        if (((numberOfPackages >= nvl(rec.getMinNumberOfPackages(), 0))
                || rec.getMinNumberOfPackages() == null)
                amp;amp; (numberOfPackages <= nvl(rec.getMaxNumberOfPackages(),0))
                || rec.getMaxNumberOfPackages() == null) {

            if (((totalNetWeight >= nvl(rec.getMinNetWeight(),0)) || rec.getMinNetWeight() == null)
                    amp;amp; (totalNetWeight <= nvl(rec.getMaxNetWeight(),0)) || rec.getMaxNetWeight() == null) {
                result.add(rec);
            }
        }
    }
}

Collections.sort(result, new Comparator<tableOfReceivers >() {

    @Override
    public int compare(tableOfReceivers  o1, tableOfReceivers  o2) {
        return o1.getPriority().compareTo(o2.getPriority());
    }
});

System.out.println("Receiver selection result is:"   "n");
if(!result.isEmpty()){
    System.out.println(result.get(0).getReceiver()   "n");
}       
  

}

 public static Integer nvl(Integer value, Integer alternateValue) {
    if (value == null)
        return alternateValue;
    return value;
}
  

Итак, есть ли более простой и лучший способ получить то, что мне нужно, используя здесь только Java?

Спасибо!

Комментарии:

1. Почему вы хотите использовать только Java? SQL может использовать индексы и другую информацию для более эффективного запроса к базе данных.

2. Почему бы не использовать потоки в Java 8? Это намного проще.

Ответ №1:

Я бы использовал Java 8

 List<tableOfReceivers> result = 
    listOfReceivers.stream()
                   .filter(rec -> countryOfDestination.equals(rec.getCountryOfDestination())
                                  || "*".equals(rec.getCountryOfDestination())
                   .filter(numberOfPackages >= nvl(rec.getMinNumberOfPackages(), numberOfPackages ))
                   .filter(numberOfPackages <= nvl(rec.getMaxNumberOfPackages(), numberOfPackages ))
                   .filter(totalNetWeight >= nvl(rec.getMinNetWeight(), totalNetWeight))
                   .filter(totalNetWeight <= nvl(rec.getMaxNetWeight(), totalNetWeight))
                   .sort(Comparator.comparing(rec -> rec.getPriority()))
                   .collect(Collectors.toList());
  

Или вы могли бы использовать вспомогательный метод, например in

 public static boolean in(int value, Integer min, Integer max) {
    return (min == null || min <= value) amp;amp;
           (max == null || max >= value);
}

public static boolean countryMatch(String a, String b) {
    return "*".equals(a) || "*".equals(b) || a.equals(b);
}

List<tableOfReceivers> result = 
    listOfReceivers.stream()
                   .filter(rec -> countryMatch(countryOfDestination, rec.getCountryOfDestination()))
                   .filter(rec -> in(numberOfPackages, rec.getMinNumberOfPackages(), rec.getMaxNumberOfPackages())))
                   .filter(rec -> in(totalNetWeight, rec.getMinNetWeight(), rec.getMaxNetWeight(), totalNetWeight))
                   .sort(Comparator.comparing(rec -> rec.getPriority()))
                   .collect(Collectors.toList());
  

Комментарии:

1. В этом сила потока ! Но как насчет производительности?

2. Это потрясающе и спасибо за помощь! Мне нужно наверстать упущенное в этих потоках.

3. @AxelH в общем случае perf такой же, как циклы для прогретого кода. Сортировка может быть немного медленнее, но достаточно редко, чтобы иметь значение.

4. @PeterLawrey, я остановлю спам здесь 😉 Я проверю это, это кажется действительно хорошо сделанным. Я надеюсь, что однажды они подумают об обновлении Java в офисе… Спасибо за информацию!

5. @AxelH вы можете использовать одну из интересных функций Stream API parallelStream() , и она будет использовать все процессоры вашего компьютера (возможно, без изменения какого-либо другого кода)