Pobieranie miejsc na seans

0

Każdy seans ma przypisaną salę a sala miejsca. Potrzebuje wyświetlić miejsca na danych seans z informacją czy jest wolne. Teraz robię to tak, że dostaje id seansu, pobieram seans, biorę z niego id sali, potem wszystkie id miejsc biletów na ten seans i wszystkie miejsca z tej sali i jeśli lista id miejsc biletów zawiera id danego miejsca, to znaczy, że miejsce jest zajęte. W kodzie wygląda, to tak:

public List<SeatWithStatusDto> handle(GetSeatsByScreeningId query) {
        log.info("Query:{}", query);
        var hallId = jdbcTemplate.queryForObject(
                "select s.hall_id from screenings s where s.id = ?",
                Long.class,
                query.screeningId()
        );
        var ticketsSeatsId = getTicketsSeatIdsByScreeningHandler.handle(
                new GetTicketsSeatIdsByScreeningId(query.screeningId())
        );
        return getSeatsByHallIdHandler
                .handle(new GetSeatsByHallId(hallId))
                .stream()
                .map(seatDto -> new SeatWithStatusDto(
                                seatDto.rowNumber(),
                                seatDto.number(),
                                !ticketsSeatsId.contains(seatDto.seatId())
                        )
                ).toList();
    }

Jak zrobić to lepiej? Może wprowadzić 2 różne modele dla miejsc - HallSeat (przechowywanie informacji jakie w ogóle mamy miejsca w danej sali) i ScreeningSeat (z informacją czy miejsce jest wolne czy nie)

0

Lepiej się nie da niestety. Możesz pobawić się w lekkie poprawki, ale.calosc szału nie ma.

1

Technicznie to coś co robi się jednym zapytaniem - jeśli trzeba:

SELECT s.seat_id
FROM seats s
JOIN screening sc ON s.hall_id = sc.hall_id
LEFT JOIN tickets t ON s.seat_id = t.seat_id AND sc.screening_id = t.screening_id
WHERE sc.screening_id = {your_screening_id}
  AND t.ticket_id IS NULL; -- tu jest kluczowy trick

(kod jest wygenerowany z chatGPT z małą poprawką, nie wiem nawet czy dobry, ale wrzuciłem komentarz co jest istotnym miejscem)

Z tym, że:

  1. to wcale nie jest tak, że jedno zapytanie będzie wydajniejsze od tych streamów i kilku zapytań - to zależy od wielu rzeczy,
  2. to wcale nie jest tak, że takie zapytanie jest bardziej czytelne od operacji na streamach - to zależy. Twój kod jest dla mnie dość niezrozumiały, bo posługujesz się mało znaczącymi nazwami typu handle, jakby to po prostu rozbić na podoperacje - byłoby IMO lepiej
0
jarekr000000 napisał(a):

Technicznie to coś co robi się jednym zapytaniem - jeśli trzeba:

SELECT s.seat_id
FROM seats s
JOIN screening sc ON s.hall_id = sc.hall_id
LEFT OUTER JOIN tickets t ON s.seat_id = t.seat_id AND sc.screening_id = t.screening_id
WHERE sc.screening_id = {your_screening_id}
  AND t.ticket_id IS NULL; -- tu jest kluczowy trick

(kod jest wygenerowany z chatGPT z małą poprawką, nie wiem nawet czy dobry, ale wrzuciłem komentarz co jest istotnym miejscem)

Z tym, że:

  1. to wcale nie jest tak, że jedno zapytanie będzie wydajniejsze od tych streamów i kilku zapytań - to zależy od wielu rzeczy,
  2. to wcale nie jest tak, że takie zapytanie jest bardziej czytelne od operacji na streamach - to zależy. Twój kod jest dla mnie dość niezrozumiały, bo posługujesz się mało znaczącymi nazwami typu handle, jakby to po prostu rozbić na podoperacje - byłoby IMO lepiej

Wiem, że teoretycznie można by to zrobić jakimś karkołomnym Sqlem, ale:
1.Po pierwsze, mam podział na moduły typu "screenings", "halls" itd i takie zapytanie, łamie enkapsulacje, bo grzebie po tabelkach innych modułów zamiast korzystać z API tych modułów
2.Jest bardzo nieczytelne i ciężkie w utrzymaniu

0

@Nofenak: jest łatwe w utrzymaniu, jeśli nie umiesz SQL aby dopisać prosta rzecz, to się nie dziw

0
Zadacpyt napisał(a):

@Nofenak: jest łatwe w utrzymaniu, jeśli nie umiesz SQL aby dopisać prosta rzecz, to się nie dziw

A teraz się czasem nie odchodzi od tego typu złożonych joinów na rzecz jakiś view modeli z CQRS?

0

@Nofenak: to wszystko jest pod spodem błędem, nie martw się oby działało.

0
Nofenak napisał(a):

Wiem, że teoretycznie można by to zrobić jakimś karkołomnym Sqlem, ale:
1.Po pierwsze, mam podział na moduły typu "screenings", "halls" itd i takie zapytanie, łamie enkapsulacje, bo grzebie po tabelkach innych modułów zamiast korzystać z API tych modułów

Pytanie czy to sensowny podział. Ale to już zależy od wielkości modułów i co tam jeszcze jest.
Z tym, że twój oryginalny kod też specjalnie nie trzyma jakieś enkapsulacji - po prostu robisz w Javie logicznie to samo co w tym SQL.

2.Jest bardzo nieczytelne i ciężkie w utrzymaniu

Oczywiście - SQL to trochę g**no, więc jak mam już pisać SQL to wolę chociaż typowane -> np. JOOQ.

0

Rozwiązałem to w ten sposób, że w module "halls" mam Seat z polami id, rowNumber, number, hallId a w module "screenings" Seat z polami id, rowNumber, number, isFree, screeningId, które jest aktulizowane za pomocą eventów. Myślę, że to jest całkiem spoko rozwiązanie chyba, że ktoś widzi jakieś problemy.

0
Nofenak napisał(a):
Zadacpyt napisał(a):

@Nofenak: jest łatwe w utrzymaniu, jeśli nie umiesz SQL aby dopisać prosta rzecz, to się nie dziw

A teraz się czasem nie odchodzi od tego typu złożonych joinów na rzecz jakiś view modeli z CQRS?

Główną zaletą CQRSa jest to, że po stronie odczytowej nie używamy ORM-a tylko SQL-a czy czegoś na wzór widoków zmaterializowanych reprezentujących nasze read modele, które są dużo szybsze i wydajniejsze bo działają bezpośrednio na silniku bazy danych i można je dość łatwo optymalizować.

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