//JAVA 17 //DEPS org.springframework.boot:spring-boot-dependencies:3.1.3@pom //DEPS org.springframework.boot:spring-boot-starter-web //DEPS org.springframework.boot:spring-boot-starter-data-jdbc //DEPS com.h2database:h2 package app; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.event.EventListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.annotation.Id; import org.springframework.data.jdbc.repository.query.Modifying; import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; import org.springframework.web.bind.annotation.*; @SpringBootApplication @RestController public class TodoApp { public static void main(String[] args) { SpringApplication.run(TodoApp.class, args); } private final Logger logger = LoggerFactory.getLogger(TodoApp.class); private final TodoRepository todoRepository; TodoApp(TodoRepository todoRepository) { this.todoRepository = todoRepository; } @GetMapping("/todos") Iterable todos() { return todoRepository.findAll(); } @PostMapping("/todos") Todo newTodo(@RequestBody TodoCreateCommand todo) { logger.debug("Creating new todo: {}", todo); return todoRepository.save(new Todo(null, todo.description(), todo.done())); } @PostMapping("/todos/{id}/done") Todo markTodoDone(@PathVariable("id") Integer id) { todoRepository.markAsDone(id); return todoRepository.findById(id).orElseThrow(); } @PostMapping("/todos/{id}/not-done") Todo markTodoNotDone(@PathVariable("id") Integer id) { todoRepository.markAsNotDone(id); return todoRepository.findById(id).orElseThrow(); } } @Component record StartupAppListener(JdbcTemplate jdbc) { @EventListener public void onApplicationEvent(ContextRefreshedEvent event) { jdbc.execute(""" CREATE TABLE IF NOT EXISTS todos ( id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, description TEXT NOT NULL, done BOOLEAN NOT NULL DEFAULT 0 ); """); } } record TodoCreateCommand(String description, Boolean done) { } @Table("TODOS") record Todo(@Id Integer id, String description, Boolean done) { } @Repository interface TodoRepository extends CrudRepository { @Modifying @Query("update todos set done = true where id=:id") void markAsDone(@Param("id") Integer id); @Modifying @Query("update todos set done = false where id=:id") void markAsNotDone(@Param("id") Integer id); }