• 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

Aruba Cloud - Virtual Private Server VPS
+1 głos
603 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 (280,450 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ź 478 wizyt
pytanie zadane 19 maja 2017 w Java przez K0XM4N Gaduła (3,640 p.)
0 głosów
1 odpowiedź 410 wizyt
pytanie zadane 4 maja 2020 w Java przez scrxts Nowicjusz (150 p.)
0 głosów
0 odpowiedzi 325 wizyt
pytanie zadane 18 marca 2020 w Java przez Krab789 Nowicjusz (170 p.)

93,324 zapytań

142,323 odpowiedzi

322,390 komentarzy

62,653 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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...