Models & Repositories

The interviewer just said…

“OK, let’s see some code. Start with your models.”

In many interviews you stop at diagrams; in this course you implement. The code lives in the hub/scripts/movie-ticket-sourced/ repo under com.interview — build it as you read.


What you should do next

  1. Create the package layout
  2. Add Lombok @Builder / @Data models (match entities from previous chapter)
  3. Add in-memory repos with just enough methods to seed and query data
  4. Add ShowSeat.reserveTime and the 5-minute soft-expiry idea (full sweeper optional)

Package layout

com.interview
├── model/       Movie, Theater, Screen, Show, ShowSeat, Ticket
├── enums/       SeatStatus
├── repo/        *Repo (in-memory HashMap stores)
├── service/     MovieService, ShowService, BookingService, TicketService
├── exception/   ReserveException, PaymentException, ...
└── Main.java    seed + demo

This mirrors standard Spring-style layering without bringing in Spring — interview-friendly.


Models (Java)

Align with the whiteboard. Example ShowSeat:

@Builder
@Data
public class ShowSeat {
    String showId;
    String SeatId;
    SeatStatus status;
    LocalDateTime reserveTime;
}

Other models match hub/scripts/movie-ticket-sourced/src/main/java/com/interview/model/ — copy field names exactly so repos and services compile together.

SeatStatus enum:

public enum SeatStatus {
    AVAILABLE, BOOKED, RESERVE
}

In-memory repositories

Interviewers accept HashMap stores. Each repo owns one entity type.

public class ShowSeatRepo {
    Map<String, ShowSeat> store = new HashMap<>();

    public void add(ShowSeat seat) {
        store.put(seat.getShowId() + seat.getSeatId(), seat);
    }

    public List<ShowSeat> findByShowId(String showId) {
        return store.values().stream()
                .filter(s -> s.getShowId().equals(showId))
                .toList();
    }

    public List<ShowSeat> getAvailableSeatsByShowId(String showId) { /* filter AVAILABLE */ }
    public void bookSeats(String showId, List<String> seatIds) { /* RESERVE→BOOKED */ }
    public void releaseSeats(List<String> seatIds, String showId) { /* → AVAILABLE */ }
}

Mirror the pattern for MovieRepo, TheaterRepo, ScreenRepo, ShowRepo, TicketRepo.

Say in interview: “I’m using in-memory repos for clarity; in production these become JPA repositories or SQL with SELECT FOR UPDATE on reserve.”


Seeding ShowSeat rows

When a Show is created, materialize one ShowSeat per seat label:

for (String seatId : show.getSeats()) {
    showSeatRepo.add(ShowSeat.builder()
            .showId(show.getId())
            .SeatId(seatId)
            .status(SeatStatus.AVAILABLE)
            .build());
}

Main.java in the repo does this manually for demo show sh1 with seats A1–A3.


reserveTime + 5-minute soft expiry (idea)

When reserveSeat runs:

s.setStatus(SeatStatus.RESERVE);
s.setReserveTime(LocalDateTime.now());

Soft expiry rule: If now - reserveTime > 5 minutes, treat seat as releasable (background job or lazy check on read).

boolean isExpired(ShowSeat s) {
    return s.getStatus() == SeatStatus.RESERVE
        && s.getReserveTime().plusMinutes(5).isBefore(LocalDateTime.now());
}

For v1 demo you may skip the sweeper — but mention it in the interview so holds don’t leak forever if payment hangs.

Wire services in Main via constructor injection — no Spring required.