• 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

Object Storage Arubacloud
+1 głos
392 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 (270,150 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ź 434 wizyt
pytanie zadane 19 maja 2017 w Java przez K0XM4N Gaduła (3,640 p.)
0 głosów
1 odpowiedź 350 wizyt
pytanie zadane 4 maja 2020 w Java przez scrxts Nowicjusz (150 p.)
0 głosów
0 odpowiedzi 260 wizyt
pytanie zadane 18 marca 2020 w Java przez Krab789 Nowicjusz (170 p.)

92,573 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...