• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Spring Specification - czy można dodać własne zapytanie

VPS Starter Arubacloud
+1 głos
376 wizyt
pytanie zadane 7 listopada 2022 w Java przez Lulex Użytkownik (820 p.)

Cześć,

stworzyłem w bazie danych metodę której użyłem do swotrzenia custom query w repozytorium:

@Query(value = "SELECT * FROM SHAPES WHERE COUNT_AREA(TYPE, RADIUS, WIDTH, HEIGHT) >= ?1", nativeQuery = true)
   List<ShapeEntity> getWithAreaGreaterThan(double area);

Walczę również ze specyfikacjami, aby dane można było wygodnie i szybko filtrować. 

Jednak mam problem z polem. "COUNT_AREA" to funkcja w bazie danych. Czy mogę w jakiś sposób użyć tego do specyfikacji? Nie mogę nic wygooglować na ten temat i obawiam się, że nie będzie to możliwe, ponieważ Specyfikacja operuje na polach klasy, które robię bez problemu:

public static Specification<ShapeEntity> radiusGreaterThan(Double radiusFrom) {
        return (root, query, builder) ->
                radiusFrom == null ?
                        builder.conjunction() :
                        builder.greaterThan(root.get("shapes").get("radius"), radiusFrom);
    }

Więc pytanie czy będzie to w ogóle możliwe czy raczej powinienem zrobić to dynamiczne wyszukiwanie w zupełnie inny sposób?

1 odpowiedź

+2 głosów
odpowiedź 8 listopada 2022 przez Wiciorny Ekspert (269,120 p.)

Zacznijmy od jednej istotnej rzeczy.
Interfejs Specyfication służy do określania predykatów w warunkach filtrowania.
Zapytanie z funkcja obliczającą- nie jest częścią warunków "spełnienia filtrowania, wyboru elementów" a jedynie jeje rezultat jako np  operacja sumująca już "wybrane parametry" w tym wypadku funkcja  powinna działać w ramach twojego predykatu i tam byc zdefiniowana.
Natomiast rezultat  wynikowy zapytania  będzie efektem końcowym jedynie. Coś na zasadzie : terminated operation.

Wszystko zależy jak zapisywane są dane dla tego pola w bazie? Czy jest to czysta funkcja, czy jej wynik, jednocześnie powinieneś mieć obiekt który poprzez ORM reprezentuje to w bazie danych.

Być może dobrym rozwiązaniem będzie utworzenie 1 z predykatów jako funkcje - tzw. wyrażenie lambda. które będzie ewaluowane podczas uruchomienia specyfikacji 
dla przykładu 
 

Predicate<Integer>  countAreaFn = (param1,param2,param3), -> ( result); 

jako RESULT -> możesz albo dowolnie podać referencje do funkcji jakiejś która na rzecz tego ma być wykonana, albo po prostu jesli np. byłoby to mnożenie, zsumować określone parametry. 

komentarz 19 listopada 2022 przez Lulex Użytkownik (820 p.)

Zawsze doceniam Twoją pomoc i wskazówki, ponieważ zazwyczaj udawało mi się rozwiązywać problem :D .

 

W tym przypadku jest nieco inaczej, ponieważ mam problem ze zrozumieniem i ułożeniem tego aby to jakkolwiek wyglądało, nie mogę też znaleźć jakiegoś odpowiedniego przykładu, wszędzie gdzie byłem są tylko te "proste" przypadki.

Predicate wygląda jak coś co chciałbym zastosować, tylko no właśnie jak to zrobić.

Nie ogarniam co się dzieje w twoim kodzie i jak to wykorzystać. Próbowałem iść w tym kierunku, czyli zależnie od kolumny, policzyć pole figury:

public static Specification<ShapeEntity> areaTo(double areaTo) {
        return (root, query, criteriaBuilder) -> {
            double area;
            switch (root.get("type").toString()) {
                case "CIRCLE":
                    area = Math.pow(Double.parseDouble(root.get("radius").toString()), 2) * Math.PI;
                    break;
                case "RECTANGLE":
                    area = Double.parseDouble(root.get("width").toString()) * Double.parseDouble(root.get("height").toString());
                    break;
                case "SQUARE":
                    area = Math.pow(Double.parseDouble(root.get("width").toString()), 2);
                    break;
                default:
                    throw new IllegalArgumentException();
            }
            return criteriaBuilder.lessThanOrEqualTo(????, areaTo);
        };
    }

jednak kompletnie nie wiem jak to wykorzystać i wrzucić w return.

Podobne pytania

0 głosów
1 odpowiedź 432 wizyt
pytanie zadane 19 maja 2017 w Java przez K0XM4N Gaduła (3,640 p.)
0 głosów
1 odpowiedź 343 wizyt
pytanie zadane 4 maja 2020 w Java przez scrxts Nowicjusz (150 p.)
0 głosów
0 odpowiedzi 255 wizyt
pytanie zadane 18 marca 2020 w Java przez Krab789 Nowicjusz (170 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...