Zwrócenie listy booleanów

0

Cześć

Mam taką tabelę w Oracle Express, która zawiera dane o audytach, raportach z nich oraz użytkownikach, którzy się podpisali pod tym raportem. Z jednego audytu może być kilka raportów.
Tabela ma m.in. 3 kolumny - auditId, reportId i userId.

Potrzebuję sprawdzić, czy user o danym id podpisał się pod raportami z audytu X.

Mam repozytorium (Spring Data) mam teraz metodę:

boolean existsByAuditIdAndReportIdAndUserId(Long auditId, Long reportId, String userId);

Problem jest taki, że pobieram np. jeden audyt i ma on np. 10 raportów.
Aby ustawić flagę podpisał/nie podpisał dla listy raportów, to wołam tę metodę w pętli :/

for (var report : reports) {
  response.setSigned(existsByAuditIdAndReportIdAndUserId(auditId, report.getId(), userId));
}

Wydaje mi się, że nie powinno się tak walić tyle selectów w pętli.
Ale z tego co wiem, to Spring Data nie pozwoli zwrócić List<Boolean>

Jest jakiś sposób aby zrobić te zapytanie za jednym zamachem?

Mi przychodzi tylko do głowy zwrócić listę id podpisanych raportów, za pomocą jakiegoś takiego zapytania:

@Query(value = "SELECT r.reportId FROM AuditReports r WHERE r.auditId = :auditId AND r.reportId IN :reportIds AND r.userId = :userId")
List<Long> selectAlreadyReadReportIds(@Param("auditId") Long auditId, @Param("reportsId") List<Long> reportsId, @Param("userId") String userId);

i potem dla każdego raportu już w Javie w pętli sprawdzić, czy jego id jest na liście. Wciąż mamy pętlę, ale przynajmniej nie walimy 10 zapytań...

1

Co w przypadku jak dany audyt zawiera np 5 reportów i user podpisał 2 z nich, a 3 z nich nie? Bo obecnie flagę signed ustawiasz wyłącznie na podstawie tego czy podpisał ostatni report.

0

Ogólnie to jeśli chcesz, żeby zapytanie zwracało ci informację, czy wszystkie audyty są podpisane to sprawa jest dosyć prosta:

@Query(value = "SELECT r.reportId FROM AuditReports r WHERE r.auditId = :auditId AND r.reportId IN :reportIds AND r.userId = :userId AND r.signed = 0")
boolean existsUnreadReports(@Param("auditId") Long auditId, @Param("reportsId") List<Long> reportsId, @Param("userId") String userId);

Pytanie kluczowe jest tutaj takie w jaki sposób identyfikujesz czy coś jest podpisane czy nie bo z tego co pamiętam Oracle nie ma kolumny typu boolean.

Możesz też puścić COUNT:

SELECT COUNT(*) FROM AuditReports r WHERE r.auditId = :auditId AND r.reportId IN :reportIds AND r.userId = :userId AND r.signed = 0

I wtedy zero to dobrze (brak raportów), jeden i więcej to źle.

0

@Pinek dzięki za zwrócenie uwagi, ta pętla to mi się pochrzaniła, tam nie ma być signed dla response, tylko dla każdego raportu

@wartek mi chodzi o to, że w response będzie np. 10 raportów i KAŻDY z nich ma mieć flagę signed: true/false. Nie, żeby sprawdzić cały czy cały audyt był podpisany.

Chciałbym to zrobić jednym zapytaniem, jedyne co mi przychodzi do głowy, to wyciągnięcie listy id podpisanych i potem w Javie sprawdzenie ręcznie dla każdego czy jest na tej liście.

1
Szprot100lec napisał(a):

jedyne co mi przychodzi do głowy, to wyciągnięcie listy id podpisanych i potem w Javie sprawdzenie ręcznie dla każdego czy jest na tej liście.

Właśnie to chciałem powiedzieć. Za uboga idea pierwotna, albo inaczej mówiać nijaka, ani nie bardzo ogólna (uniwersalny generyczny tool), ani nie bardzo specjalizowana (jedna metoda, która ma sensowny zamiar biznesowy)

Po drugie, zwracanie serii prymitywów, by je póżniej przetwarzać, jest w poprzek do gospodarki np transakcjami z waszego ukochanego @Transactional, jest nieprzekształcalne na funkcyjne / lambdy itd...

Jak bym zwracał sensowne kolekcje, tj na tych encjach, albo na dobrym ich DTO.

0
Szprot100lec napisał(a):

@wartek mi chodzi o to, że w response będzie np. 10 raportów i KAŻDY z nich ma mieć flagę signed: true/false. Nie, żeby sprawdzić cały czy cały audyt był podpisany.

Ok, i co dalej? W sensie - masz 10 raportów, co chcesz z nimi zrobić? Ustawić flagę signed na true/false?

1 użytkowników online, w tym zalogowanych: 0, gości: 1