Spring Boot Course · Reference
The vocabulary of Spring Boot. Terms here are used consistently across every lesson. Bookmark this; it grows over time.
spring-boot-starter-*. E.g. spring-boot-starter-web pulls in everything needed to build a web/REST app, at compatible versions. added L1sdk install java 21-tem and switch versions per project with sdk use — no manual PATH/JAVA_HOME editing. added L1sdk install springboot) whose spring init command generates a project from the terminal — the CLI front-end to Spring Initializr. added L1pom.xml file. (Gradle is the common alternative.) added L1mvnw)mvnw / mvnw.cmd) that downloads and runs the exact Maven version the project needs, so contributors don't have to install Maven themselves. Run goals with it, e.g. ./mvnw spring-boot:run. added L1@SpringBootApplication@RestController@GetMapping (and friends)@GetMapping("/books") handles GET /books; siblings are @PostMapping, @PutMapping, @DeleteMapping. added L1/api/books. Endpoints are organised around resources. added L2com.example.library.book holds the book's controller, service, repository, model). The alternative is package-by-layer (separate controller/service/… packages). Either way, keep everything under the main class's package so component scanning finds it. added L211111111-1111-1111-1111-111111111111). We use it as the Book id: it can be generated by the app, isn't sequentially guessable, and stays unique across systems. The common alternative is an auto-incremented numeric Long. Jackson serialises a UUID as a JSON string. added L2spring-boot-starter-web. It reads an object's accessors to serialise it to JSON, and builds objects from incoming JSON. You rarely call it directly — Spring does. added L2Content-Type: application/json. added L2@ResponseBody@RestController, which is why every method there returns data. added L2@RequestMapping@GetMapping, etc.) are specialised forms of it. added L2@Service)@Service marks the class as a Spring-managed bean. The controller delegates the real work to it. added L3@Component is the base; @Service, @Repository, and @Controller/@RestController are specialised forms that also document the class's architectural role. added L3final, missing dependencies fail fast, the dependencies are explicit, and the class can be instantiated in a plain test without Spring. With a single constructor, no @Autowired is needed. added L3@AutowiredPOST (create), GET (read), PUT (update/replace), DELETE (delete). added L4@RequestBody@PathVariable@GetMapping("/{id}"), @PathVariable UUID id captures the {id} segment and converts it to the declared type. added L4ResponseEntity200 OK (e.g. 201 Created, 204 No Content, 404 Not Found). added L42xx success (200 OK, 201 Created, 204 No Content), 4xx client error (400 Bad Request, 404 Not Found, 415 Unsupported Media Type), 5xx server error. Choosing the right one is part of designing a good API. added L4Location header201 Created response sets it to the newly created resource's address; ResponseEntity.created(uri) sets both the status and this header. added L4GET, PUT, and DELETE are idempotent; POST is not (each call creates another resource). A key reason create is POST and replace is PUT. added L4@Entity, @Id, …) describing how Java objects map to database rows. It defines the contract; it doesn't run any SQL itself. added L5JpaRepository and Spring Data generates the implementation at runtime. added L5@Entity@IdUUID. added L5JpaRepositoryJpaRepository<Book, UUID> supplies save, findById, findAll, deleteById, count, and more, with no implementation written by you. added L5findByAuthor becomes WHERE author = ?. Keywords like Containing, IgnoreCase, GreaterThanEqual, and OrderBy…Desc compose into the SQL — no method body required. added L5uuid column type that maps cleanly to the entity's UUID id. added L5compose.yaml). Here it declares the Postgres container the app needs. With spring-boot-docker-compose on the classpath, Spring Boot starts that container on boot, reads its credentials, and auto-configures the datasource — no JDBC URL to write by hand. added L5ddl-autospring.jpa.hibernate.ddl-auto) controlling how the schema is managed at startup: create-drop/update (dev convenience), or validate/none (production). We use validate — Hibernate only checks the entities match the schema; Liquibase owns the schema itself. Never let Hibernate rewrite a production schema. added L5db/changelog/db.changelog-master.yaml), applying any not-yet-run changesets. The common alternative is Flyway. added L5id + author. Liquibase records applied changesets in a tracking table and never re-runs them — so an applied changeset is immutable: to change the schema you append a new one. added L5equals/hashCode) from annotations at compile time. Safe on entities: @Getter, @Setter, @NoArgsConstructor, id-only @EqualsAndHashCode. Avoid on entities: @Data, all-fields @EqualsAndHashCode, and unguarded @ToString. added L5@RequestParam?, e.g. ?author=Bloch) to a method parameter. Use it for filtering, sorting, or paging a collection — as opposed to @PathVariable, which identifies a single resource in the path. added L5UUID.randomUUID() is v4 (fully random, poor index locality). added L5book.author_id is a foreign key into author.id. A foreign key lives in exactly one of the two tables — the "many" side. added L6@ManyToOneBooks reference one Author. Paired with @JoinColumn, it owns the foreign-key column. Defaults to eager fetching; prefer fetch = FetchType.LAZY and load the association deliberately. added L6@OneToManyAuthor has many Books, held as a collection. On a bidirectional relationship it's the inverse side and uses mappedBy; it owns no column. Defaults to lazy fetching. added L6@ManyToOne side) and is what Hibernate reads to decide what to persist; the inverse side (@OneToMany(mappedBy = …)) is for navigation only. To save the link you must set the owning side — hence a helper that updates both sides at once. added L6mappedBy@OneToMany(mappedBy = "author") → the author field on Book). It tells JPA "don't create another column; this link is already mapped over there." added L6@JoinColumn@JoinColumn(name = "author_id") maps the author reference to the author_id column. added L6orphanRemovalCascadeType.ALL means saving or deleting an author also saves or deletes its books. orphanRemoval deletes a child once it's removed from the parent's collection. Powerful but sharp: this course leaves cascade off, so deleting an author can't silently wipe their books and the database's foreign key guards against accidental deletes. Reach for cascade only when you've deliberately decided a child should share its parent's lifecycle. added L6record — that shapes data crossing the API boundary, separate from your entities. A request DTO (e.g. CreateBookRequest, no id) defines what you accept; a response DTO (e.g. BookResponse) defines what you send. A related entity is exposed as a small projection — a compact, embeddable view such as AuthorSummary (id + name, no nested collections) — which both hides internals and breaks the entity cycle that would otherwise crash JSON serialization. DTOs decouple the wire format from the schema. added L6spring.jpa.open-in-view=true) that keeps the persistence session open for the whole request, so lazy associations can load during JSON rendering. Convenient — it's why mapping an entity to a DTO in the controller "just works" — but it can hide N+1 queries; many teams disable it. added L6JOIN FETCH query or an entity graph. added L6spring-boot-starter-validation. added L7@NotNull, @NotBlank (non-null and non-whitespace), @Size(min,max), @Positive, @Min/@Max, @Email, @Pattern. Placed on the request DTO — the boundary shape — not the entity. added L7@Valid@RequestBody parameter it tells Spring to check the object's constraints before the handler runs; a violation throws MethodArgumentNotValidException. Without it, constraints are ignored. added L7MethodArgumentNotValidException@Valid body fails its constraints. Its BindingResult holds the per-field errors; a handler reads them to build a response. Maps naturally to 400 Bad Request. added L7@ControllerAdvice / @RestControllerAdvice@ExceptionHandler methods apply across every controller — one central place to turn exceptions into HTTP responses. The @RestController variant writes return values to the response body (as JSON), like @RestController does. added L7@ExceptionHandler@RestControllerAdvice it catches that exception from any controller and returns the error response to send. Spring picks the most specific handler, so a method for a precise type out-ranks a catch-all @ExceptionHandler(Exception.class). added L7ResponseEntityExceptionHandlerProblemDetail-shaped handling for every standard Spring MVC exception (malformed JSON, type mismatch, unsupported method/media type, validation, …). You override individual methods (e.g. handleMethodArgumentNotValid) to customize, add @ExceptionHandlers for your own exceptions, and rely on specificity so a catch-all only fires for the truly unexpected. added L7type, title, status, detail, instance, plus custom members. Spring's ProblemDetail class produces it; returning one sets the application/problem+json content type and the status. A single consistent error shape across the whole API. added L7LIMIT and OFFSET down to the database. Bounds the work done by the database, server, and client regardless of table size. Pages are zero-based (page 0 is the first). added L8Pageablepage, size, and sort query parameters — no @RequestParam needed — and handed to a repository method. added L8Page / SlicePage<T> holds the slice of rows plus metadata (totalElements, totalPages, current number, size) — it runs an extra COUNT query to know the totals. Slice<T> skips the count and only knows whether a next page exists (cheaper; good for "load more"). Page.map(...) transforms each element to a DTO while preserving the metadata. added L8@PageableDefaultsize and sort applied when a request omits them, e.g. @PageableDefault(size = 20, sort = "title"). Without it, an unparameterized request falls back to Spring's global default (20 rows, unsorted). added L8PagedModel / @EnableSpringDataWebSupportPage (PageImpl) is discouraged — it's an internal type with no guarantee its JSON stays stable across versions (Spring logs a warning). PagedModel is the stable representation: rows under content, paging facts under one page object. Turn it on globally with @EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) and controllers can keep returning Page. The page size is also capped by spring.data.web.pageable.max-page-size (default 2000) so a client can't request unbounded rows. added L8@ManyToOne defaults to eager but should be set LAZY; @OneToMany is lazy by default. Lazy is the right default — but every lazy touch is a potential query, which is how the N+1 problem arises. added L9@EntityGraph@EntityGraph(attributePaths = "author"). The go-to fix for N+1 — the association is LEFT JOINed in rather than lazily loaded per row. Safe with pagination for to-one associations (a join adds columns, not rows); for to-many collections the query is more involved (modern Hibernate paginates the parents in a subquery first). added L9JOIN FETCH)select b from Book b join fetch b.author. The hand-written equivalent of @EntityGraph — reach for it inside a custom @Query. added L9LazyInitializationExceptionCould not initialize proxy … no session). Common once spring.jpa.open-in-view=false: it turns a hidden lazy load into a loud failure, signalling exactly where you must fetch the association deliberately (a fetch join or @EntityGraph). added L9@BatchSize / batch fetchinghibernate.default_batch_fetch_size = N (or @BatchSize(size = N)) collapses N per-row lazy loads into a few WHERE id IN (?, ?, …) queries — turning 1 + N into roughly 1 + (N / N). Needs an open session when the collection is accessed. added L9when(repo.findById(id)).thenReturn(...)); a mock also records interactions so you can assert they happened (verify(repo).save(...)). In Mockito a single @Mock object does both jobs. added L10@Test methods, lifecycle hooks (@BeforeEach), @DisplayName, and an extension model (@ExtendWith) that plugs in tools like Mockito. Ships with Spring Boot's test starter. added L10@Mock creates a test double; when(...).thenReturn(...) stubs its answers; verify(...) asserts it was (or, with never(), wasn't) called; an ArgumentCaptor grabs the exact argument passed to a mock so you can assert on it. Enabled in JUnit 5 via @ExtendWith(MockitoExtension.class), which runs in strict-stubbing mode. added L10assertThat(x).isEqualTo(y), isSameAs, assertThatThrownBy(() -> …).isInstanceOf(...).hasMessageContaining(...). Reads left-to-right and gives rich failure messages. The assertion style used throughout this course. added L10