{"id":27,"date":"2026-10-08T16:17:16","date_gmt":"2026-10-08T16:17:16","guid":{"rendered":"https:\/\/boot-code.com\/?p=27"},"modified":"2026-10-08T16:17:19","modified_gmt":"2026-10-08T16:17:19","slug":"spring-boot-todo-web-application-with-mysql-extension","status":"publish","type":"post","link":"https:\/\/boot-code.com\/?p=27","title":{"rendered":"Spring Boot Todo Web Application with MySQL Extension"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Great. Let\u2019s upgrade the Todo application into a <strong>proper Spring Boot CRUD project<\/strong> with:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add Todo<\/li>\n\n\n\n<li>View Todo<\/li>\n\n\n\n<li>Edit Todo<\/li>\n\n\n\n<li>Delete Todo<\/li>\n\n\n\n<li>Mark Complete\/Incomplete<\/li>\n\n\n\n<li>Validation<\/li>\n\n\n\n<li>Bootstrap UI<\/li>\n\n\n\n<li>REST API<\/li>\n\n\n\n<li>MySQL persistence<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">We can build it incrementally so you understand <strong>Controller \u2192 Service \u2192 Repository \u2192 MySQL<\/strong> rather than just copying code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below is a <strong>complete Spring Boot Todo CRUD application<\/strong> you can import into Eclipse and run with MySQL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It includes <strong>Web UI + Bootstrap + CRUD + validation + REST API + MySQL<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Project structure<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>todo\/\n\u251c\u2500\u2500 pom.xml\n\u2514\u2500\u2500 src\/\n    \u2514\u2500\u2500 main\/\n        \u251c\u2500\u2500 java\/com\/example\/todo\/\n        \u2502   \u251c\u2500\u2500 TodoApplication.java\n        \u2502   \u251c\u2500\u2500 controller\/\n        \u2502   \u2502   \u251c\u2500\u2500 TodoController.java\n        \u2502   \u2502   \u2514\u2500\u2500 TodoRestController.java\n        \u2502   \u251c\u2500\u2500 model\/\n        \u2502   \u2502   \u2514\u2500\u2500 Todo.java\n        \u2502   \u251c\u2500\u2500 repository\/\n        \u2502   \u2502   \u2514\u2500\u2500 TodoRepository.java\n        \u2502   \u2514\u2500\u2500 service\/\n        \u2502       \u2514\u2500\u2500 TodoService.java\n        \u2502\n        \u2514\u2500\u2500 resources\/\n            \u251c\u2500\u2500 templates\/\n            \u2502   \u251c\u2500\u2500 index.html\n            \u2502   \u2514\u2500\u2500 edit.html\n            \u2514\u2500\u2500 application.properties<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. MySQL setup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl start mysql<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mysql<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create the database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE DATABASE todo_db;\n\nCREATE USER 'todo_user'@'localhost'\nIDENTIFIED BY 'todo_password';\n\nGRANT ALL PRIVILEGES ON todo_db.*\nTO 'todo_user'@'localhost';\n\nFLUSH PRIVILEGES;\n\nEXIT;<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2. <code>pom.xml<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Replace your <code>pom.xml<\/code> with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"\n         xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"\n         http:&#47;&#47;maven.apache.org\/POM\/4.0.0\n         https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n\n    &lt;parent&gt;\n        &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;\n        &lt;version&gt;3.5.6&lt;\/version&gt;\n        &lt;relativePath\/&gt;\n    &lt;\/parent&gt;\n\n    &lt;groupId&gt;com.example&lt;\/groupId&gt;\n    &lt;artifactId&gt;todo&lt;\/artifactId&gt;\n    &lt;version&gt;0.0.1-SNAPSHOT&lt;\/version&gt;\n\n    &lt;name&gt;todo&lt;\/name&gt;\n    &lt;description&gt;Spring Boot Todo Application&lt;\/description&gt;\n\n    &lt;properties&gt;\n        &lt;java.version&gt;17&lt;\/java.version&gt;\n    &lt;\/properties&gt;\n\n    &lt;dependencies&gt;\n\n        &lt;!-- Spring Web --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- Thymeleaf --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- Spring Data JPA --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- Validation --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-validation&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- MySQL --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.mysql&lt;\/groupId&gt;\n            &lt;artifactId&gt;mysql-connector-j&lt;\/artifactId&gt;\n            &lt;scope&gt;runtime&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- DevTools --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-devtools&lt;\/artifactId&gt;\n            &lt;optional&gt;true&lt;\/optional&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- Testing --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\n            &lt;scope&gt;test&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n\n    &lt;\/dependencies&gt;\n\n    &lt;build&gt;\n        &lt;plugins&gt;\n\n            &lt;plugin&gt;\n                &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n                &lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt;\n            &lt;\/plugin&gt;\n\n        &lt;\/plugins&gt;\n    &lt;\/build&gt;\n\n&lt;\/project&gt;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">If your Spring Initializr generated a newer Spring Boot 3.x version, you can keep that version instead of <code>3.5.6<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3. Main application<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>src\/main\/java\/com\/example\/todo\/TodoApplication.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class TodoApplication {\n\n    public static void main(String&#91;] args) {\n\n        SpringApplication.run(TodoApplication.class, args);\n\n    }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. Todo Entity<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>model\/Todo.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo.model;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport jakarta.validation.constraints.NotBlank;\nimport jakarta.validation.constraints.Size;\n\n@Entity\npublic class Todo {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    @NotBlank(message = \"Title is required\")\n    @Size(min = 3, max = 100,\n          message = \"Title must be between 3 and 100 characters\")\n    private String title;\n\n    private boolean completed;\n\n    public Todo() {\n    }\n\n    public Todo(String title) {\n        this.title = title;\n        this.completed = false;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public boolean isCompleted() {\n        return completed;\n    }\n\n    public void setCompleted(boolean completed) {\n        this.completed = completed;\n    }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. Repository<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>repository\/TodoRepository.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo.repository;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\n\nimport com.example.todo.model.Todo;\n\npublic interface TodoRepository extends JpaRepository&lt;Todo, Long&gt; {\n\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s all the repository needs for basic CRUD.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Spring gives us:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>findAll()\nfindById()\nsave()\ndeleteById()\nexistsById()\ncount()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">automatically.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. Service<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>service\/TodoService.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo.service;\n\nimport java.util.List;\n\nimport org.springframework.stereotype.Service;\n\nimport com.example.todo.model.Todo;\nimport com.example.todo.repository.TodoRepository;\n\n@Service\npublic class TodoService {\n\n    private final TodoRepository todoRepository;\n\n    public TodoService(TodoRepository todoRepository) {\n        this.todoRepository = todoRepository;\n    }\n\n    \/\/ READ ALL\n    public List&lt;Todo&gt; getAllTodos() {\n\n        return todoRepository.findAll();\n\n    }\n\n    \/\/ READ ONE\n    public Todo getTodoById(Long id) {\n\n        return todoRepository.findById(id)\n                .orElseThrow(() -&gt;\n                    new RuntimeException(\"Todo not found: \" + id)\n                );\n\n    }\n\n    \/\/ CREATE\n    public Todo saveTodo(Todo todo) {\n\n        return todoRepository.save(todo);\n\n    }\n\n    \/\/ UPDATE\n    public Todo updateTodo(Long id, Todo todoDetails) {\n\n        Todo todo = getTodoById(id);\n\n        todo.setTitle(todoDetails.getTitle());\n        todo.setCompleted(todoDetails.isCompleted());\n\n        return todoRepository.save(todo);\n\n    }\n\n    \/\/ DELETE\n    public void deleteTodo(Long id) {\n\n        if (!todoRepository.existsById(id)) {\n\n            throw new RuntimeException(\n                \"Todo not found: \" + id\n            );\n\n        }\n\n        todoRepository.deleteById(id);\n\n    }\n\n    \/\/ TOGGLE\n    public void toggleTodo(Long id) {\n\n        Todo todo = getTodoById(id);\n\n        todo.setCompleted(!todo.isCompleted());\n\n        todoRepository.save(todo);\n\n    }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7. Web Controller<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This controller handles the HTML web pages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>controller\/TodoController.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\n\nimport com.example.todo.model.Todo;\nimport com.example.todo.service.TodoService;\n\nimport jakarta.validation.Valid;\n\n@Controller\npublic class TodoController {\n\n    private final TodoService todoService;\n\n    public TodoController(TodoService todoService) {\n        this.todoService = todoService;\n    }\n\n    \/\/ HOME PAGE\n    @GetMapping(\"\/\")\n    public String home(Model model) {\n\n        model.addAttribute(\n            \"todos\",\n            todoService.getAllTodos()\n        );\n\n        model.addAttribute(\n            \"todo\",\n            new Todo()\n        );\n\n        return \"index\";\n    }\n\n    \/\/ CREATE\n    @PostMapping(\"\/todos\")\n    public String addTodo(\n            @Valid @ModelAttribute(\"todo\") Todo todo,\n            BindingResult result,\n            Model model) {\n\n        if (result.hasErrors()) {\n\n            model.addAttribute(\n                \"todos\",\n                todoService.getAllTodos()\n            );\n\n            return \"index\";\n        }\n\n        todoService.saveTodo(todo);\n\n        return \"redirect:\/\";\n    }\n\n    \/\/ EDIT PAGE\n    @GetMapping(\"\/todos\/edit\/{id}\")\n    public String editTodo(\n            @PathVariable Long id,\n            Model model) {\n\n        Todo todo = todoService.getTodoById(id);\n\n        model.addAttribute(\"todo\", todo);\n\n        return \"edit\";\n    }\n\n    \/\/ UPDATE\n    @PostMapping(\"\/todos\/update\/{id}\")\n    public String updateTodo(\n            @PathVariable Long id,\n            @Valid @ModelAttribute(\"todo\") Todo todo,\n            BindingResult result) {\n\n        if (result.hasErrors()) {\n\n            return \"edit\";\n        }\n\n        todoService.updateTodo(id, todo);\n\n        return \"redirect:\/\";\n    }\n\n    \/\/ DELETE\n    @GetMapping(\"\/todos\/delete\/{id}\")\n    public String deleteTodo(\n            @PathVariable Long id) {\n\n        todoService.deleteTodo(id);\n\n        return \"redirect:\/\";\n    }\n\n    \/\/ TOGGLE\n    @GetMapping(\"\/todos\/toggle\/{id}\")\n    public String toggleTodo(\n            @PathVariable Long id) {\n\n        todoService.toggleTodo(id);\n\n        return \"redirect:\/\";\n    }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8. REST Controller<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Now we also expose a REST API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>controller\/TodoRestController.java<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.todo.controller;\n\nimport java.util.List;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.example.todo.model.Todo;\nimport com.example.todo.service.TodoService;\n\n@RestController\n@RequestMapping(\"\/api\/todos\")\npublic class TodoRestController {\n\n    private final TodoService todoService;\n\n    public TodoRestController(TodoService todoService) {\n        this.todoService = todoService;\n    }\n\n    \/\/ GET ALL\n    @GetMapping\n    public List&lt;Todo&gt; getAllTodos() {\n\n        return todoService.getAllTodos();\n\n    }\n\n    \/\/ GET ONE\n    @GetMapping(\"\/{id}\")\n    public ResponseEntity&lt;Todo&gt; getTodo(\n            @PathVariable Long id) {\n\n        try {\n\n            return ResponseEntity.ok(\n                todoService.getTodoById(id)\n            );\n\n        } catch (RuntimeException e) {\n\n            return ResponseEntity.notFound().build();\n\n        }\n    }\n\n    \/\/ CREATE\n    @PostMapping\n    public ResponseEntity&lt;Todo&gt; createTodo(\n            @RequestBody Todo todo) {\n\n        Todo savedTodo =\n                todoService.saveTodo(todo);\n\n        return ResponseEntity\n                .status(HttpStatus.CREATED)\n                .body(savedTodo);\n    }\n\n    \/\/ UPDATE\n    @PutMapping(\"\/{id}\")\n    public ResponseEntity&lt;Todo&gt; updateTodo(\n            @PathVariable Long id,\n            @RequestBody Todo todo) {\n\n        try {\n\n            Todo updatedTodo =\n                    todoService.updateTodo(id, todo);\n\n            return ResponseEntity.ok(updatedTodo);\n\n        } catch (RuntimeException e) {\n\n            return ResponseEntity.notFound().build();\n\n        }\n    }\n\n    \/\/ DELETE\n    @DeleteMapping(\"\/{id}\")\n    public ResponseEntity&lt;Void&gt; deleteTodo(\n            @PathVariable Long id) {\n\n        try {\n\n            todoService.deleteTodo(id);\n\n            return ResponseEntity.noContent().build();\n\n        } catch (RuntimeException e) {\n\n            return ResponseEntity.notFound().build();\n\n        }\n    }\n\n    \/\/ TOGGLE\n    @PatchMapping(\"\/{id}\/toggle\")\n    public ResponseEntity&lt;Todo&gt; toggleTodo(\n            @PathVariable Long id) {\n\n        try {\n\n            todoService.toggleTodo(id);\n\n            return ResponseEntity.ok(\n                todoService.getTodoById(id)\n            );\n\n        } catch (RuntimeException e) {\n\n            return ResponseEntity.notFound().build();\n\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9. <code>application.properties<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>src\/main\/resources\/application.properties<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.application.name=todo\n\n# MySQL\nspring.datasource.url=jdbc:mysql:\/\/localhost:3306\/todo_db\nspring.datasource.username=todo_user\nspring.datasource.password=todo_password\n\n# JPA \/ Hibernate\nspring.jpa.hibernate.ddl-auto=update\nspring.jpa.show-sql=true\nspring.jpa.properties.hibernate.format_sql=true\n\n# Thymeleaf\nspring.thymeleaf.cache=false\n\n# Server\nserver.port=8080<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10. Main HTML page<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>src\/main\/resources\/templates\/index.html<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"\n      xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;\n\n&lt;head&gt;\n\n    &lt;meta charset=\"UTF-8\"&gt;\n\n    &lt;meta name=\"viewport\"\n          content=\"width=device-width, initial-scale=1\"&gt;\n\n    &lt;title&gt;Todo Application&lt;\/title&gt;\n\n    &lt;link\n        href=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/css\/bootstrap.min.css\"\n        rel=\"stylesheet\"&gt;\n\n&lt;\/head&gt;\n\n&lt;body class=\"bg-light\"&gt;\n\n&lt;div class=\"container mt-5\"&gt;\n\n    &lt;div class=\"row justify-content-center\"&gt;\n\n        &lt;div class=\"col-md-8\"&gt;\n\n            &lt;div class=\"card shadow\"&gt;\n\n                &lt;div class=\"card-header bg-primary text-white\"&gt;\n\n                    &lt;h2 class=\"text-center mb-0\"&gt;\n                        Todo Application\n                    &lt;\/h2&gt;\n\n                &lt;\/div&gt;\n\n                &lt;div class=\"card-body\"&gt;\n\n                    &lt;!-- ADD TODO --&gt;\n\n                    &lt;form\n                        th:action=\"@{\/todos}\"\n                        th:object=\"${todo}\"\n                        method=\"post\"\n                        class=\"mb-4\"&gt;\n\n                        &lt;div class=\"input-group\"&gt;\n\n                            &lt;input\n                                type=\"text\"\n                                th:field=\"*{title}\"\n                                class=\"form-control\"\n                                placeholder=\"Enter todo\"&gt;\n\n                            &lt;button\n                                type=\"submit\"\n                                class=\"btn btn-primary\"&gt;\n\n                                Add Todo\n\n                            &lt;\/button&gt;\n\n                        &lt;\/div&gt;\n\n                        &lt;div\n                            th:if=\"${#fields.hasErrors('title')}\"\n                            th:errors=\"*{title}\"\n                            class=\"text-danger mt-2\"&gt;\n                        &lt;\/div&gt;\n\n                    &lt;\/form&gt;\n\n\n                    &lt;!-- TODO TABLE --&gt;\n\n                    &lt;table class=\"table table-hover\"&gt;\n\n                        &lt;thead class=\"table-dark\"&gt;\n\n                        &lt;tr&gt;\n\n                            &lt;th&gt;ID&lt;\/th&gt;\n\n                            &lt;th&gt;Todo&lt;\/th&gt;\n\n                            &lt;th&gt;Status&lt;\/th&gt;\n\n                            &lt;th&gt;Actions&lt;\/th&gt;\n\n                        &lt;\/tr&gt;\n\n                        &lt;\/thead&gt;\n\n                        &lt;tbody&gt;\n\n                        &lt;tr th:each=\"todo : ${todos}\"&gt;\n\n                            &lt;td th:text=\"${todo.id}\"&gt;\n                                1\n                            &lt;\/td&gt;\n\n                            &lt;td&gt;\n\n                                &lt;span\n                                    th:text=\"${todo.title}\"\n                                    th:classappend=\"${todo.completed}\n                                    ? 'text-decoration-line-through text-muted'\n                                    : ''\"&gt;\n\n                                    Learn Spring Boot\n\n                                &lt;\/span&gt;\n\n                            &lt;\/td&gt;\n\n                            &lt;td&gt;\n\n                                &lt;span\n                                    th:if=\"${todo.completed}\"\n                                    class=\"badge bg-success\"&gt;\n\n                                    Completed\n\n                                &lt;\/span&gt;\n\n                                &lt;span\n                                    th:unless=\"${todo.completed}\"\n                                    class=\"badge bg-warning text-dark\"&gt;\n\n                                    Pending\n\n                                &lt;\/span&gt;\n\n                            &lt;\/td&gt;\n\n                            &lt;td&gt;\n\n                                &lt;a\n                                    th:href=\"@{\/todos\/toggle\/{id}(id=${todo.id})}\"\n                                    class=\"btn btn-sm btn-success\"&gt;\n\n                                    Toggle\n\n                                &lt;\/a&gt;\n\n                                &lt;a\n                                    th:href=\"@{\/todos\/edit\/{id}(id=${todo.id})}\"\n                                    class=\"btn btn-sm btn-primary\"&gt;\n\n                                    Edit\n\n                                &lt;\/a&gt;\n\n                                &lt;a\n                                    th:href=\"@{\/todos\/delete\/{id}(id=${todo.id})}\"\n                                    class=\"btn btn-sm btn-danger\"\n                                    onclick=\"return confirm('Delete this todo?');\"&gt;\n\n                                    Delete\n\n                                &lt;\/a&gt;\n\n                            &lt;\/td&gt;\n\n                        &lt;\/tr&gt;\n\n                        &lt;tr th:if=\"${#lists.isEmpty(todos)}\"&gt;\n\n                            &lt;td\n                                colspan=\"4\"\n                                class=\"text-center text-muted\"&gt;\n\n                                No todos found.\n\n                            &lt;\/td&gt;\n\n                        &lt;\/tr&gt;\n\n                        &lt;\/tbody&gt;\n\n                    &lt;\/table&gt;\n\n                &lt;\/div&gt;\n\n            &lt;\/div&gt;\n\n        &lt;\/div&gt;\n\n    &lt;\/div&gt;\n\n&lt;\/div&gt;\n\n&lt;\/body&gt;\n\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11. Edit page<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Create:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>src\/main\/resources\/templates\/edit.html<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"\n      xmlns:th=\"http:\/\/www.thymeleaf.org\"&gt;\n\n&lt;head&gt;\n\n    &lt;meta charset=\"UTF-8\"&gt;\n\n    &lt;meta name=\"viewport\"\n          content=\"width=device-width, initial-scale=1\"&gt;\n\n    &lt;title&gt;Edit Todo&lt;\/title&gt;\n\n    &lt;link\n        href=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/css\/bootstrap.min.css\"\n        rel=\"stylesheet\"&gt;\n\n&lt;\/head&gt;\n\n&lt;body class=\"bg-light\"&gt;\n\n&lt;div class=\"container mt-5\"&gt;\n\n    &lt;div class=\"row justify-content-center\"&gt;\n\n        &lt;div class=\"col-md-6\"&gt;\n\n            &lt;div class=\"card shadow\"&gt;\n\n                &lt;div class=\"card-header bg-primary text-white\"&gt;\n\n                    &lt;h3 class=\"text-center mb-0\"&gt;\n                        Edit Todo\n                    &lt;\/h3&gt;\n\n                &lt;\/div&gt;\n\n                &lt;div class=\"card-body\"&gt;\n\n                    &lt;form\n                        th:action=\"@{\/todos\/update\/{id}(id=${todo.id})}\"\n                        th:object=\"${todo}\"\n                        method=\"post\"&gt;\n\n                        &lt;div class=\"mb-3\"&gt;\n\n                            &lt;label class=\"form-label\"&gt;\n                                Todo\n                            &lt;\/label&gt;\n\n                            &lt;input\n                                type=\"text\"\n                                th:field=\"*{title}\"\n                                class=\"form-control\"&gt;\n\n                            &lt;div\n                                th:if=\"${#fields.hasErrors('title')}\"\n                                th:errors=\"*{title}\"\n                                class=\"text-danger\"&gt;\n                            &lt;\/div&gt;\n\n                        &lt;\/div&gt;\n\n                        &lt;div class=\"form-check mb-3\"&gt;\n\n                            &lt;input\n                                type=\"checkbox\"\n                                th:field=\"*{completed}\"\n                                class=\"form-check-input\"&gt;\n\n                            &lt;label class=\"form-check-label\"&gt;\n                                Completed\n                            &lt;\/label&gt;\n\n                        &lt;\/div&gt;\n\n                        &lt;button\n                            type=\"submit\"\n                            class=\"btn btn-primary\"&gt;\n\n                            Update\n\n                        &lt;\/button&gt;\n\n                        &lt;a\n                            href=\"\/\"\n                            class=\"btn btn-secondary\"&gt;\n\n                            Cancel\n\n                        &lt;\/a&gt;\n\n                    &lt;\/form&gt;\n\n                &lt;\/div&gt;\n\n            &lt;\/div&gt;\n\n        &lt;\/div&gt;\n\n    &lt;\/div&gt;\n\n&lt;\/div&gt;\n\n&lt;\/body&gt;\n\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12. Run the application<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">From the project directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd todo<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/mvnw spring-boot:run<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or in Eclipse:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Right click TodoApplication.java\n        \u2193\nRun As\n        \u2193\nSpring Boot App<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then open:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"http:\/\/localhost:8080\/?utm_source=chatgpt.com\">Todo Application<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">13. Test CRUD<\/h1>\n\n\n\n<h3 class=\"wp-block-heading\">Create<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Enter:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Learn Java<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Click <strong>Add Todo<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Read<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The todo appears in the table.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Update<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Click:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Edit<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Change:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Learn Java<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Learn Java and Spring Boot<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Click <strong>Update<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Complete<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Click:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Toggle<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The status changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Pending<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Completed<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Delete<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Click:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Delete<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The record is removed from MySQL.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">14. Test REST API<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">You can test the REST API using Postman, curl, or your browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get all todos<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl http:\/\/localhost:8080\/api\/todos<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\n    {\n        \"id\": 1,\n        \"title\": \"Learn Java\",\n        \"completed\": false\n    },\n    {\n        \"id\": 2,\n        \"title\": \"Learn Spring Boot\",\n        \"completed\": true\n    }\n]<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Get one todo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl http:\/\/localhost:8080\/api\/todos\/1<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Create todo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -X POST \\\n-H \"Content-Type: application\/json\" \\\n-d '{\"title\":\"Learn REST API\",\"completed\":false}' \\\nhttp:&#47;&#47;localhost:8080\/api\/todos<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Update todo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -X PUT \\\n-H \"Content-Type: application\/json\" \\\n-d '{\"title\":\"Learn Spring Boot REST\",\"completed\":true}' \\\nhttp:&#47;&#47;localhost:8080\/api\/todos\/1<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Toggle todo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -X PATCH \\\nhttp:&#47;&#47;localhost:8080\/api\/todos\/1\/toggle<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Delete todo<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -X DELETE \\\nhttp:&#47;&#47;localhost:8080\/api\/todos\/1<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">15. Check MySQL<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql -u todo_user -p<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>USE todo_db;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check tables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SHOW TABLES;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check todos:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM todo;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should get something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>+----+-------------------------+-----------+\n| id | title                   | completed |\n+----+-------------------------+-----------+\n|  1 | Learn Java              |         0 |\n|  2 | Learn Spring Boot       |         1 |\n|  3 | Learn REST API          |         0 |\n+----+-------------------------+-----------+<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">16. How the application works<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The important Spring architecture is:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> <code>                   Browser\n                       |\n                       v\n              TodoController\n                       |\n                       v\n                TodoService\n                       |\n                       v\n              TodoRepository\n                       |\n                       v\n                 JPA\/Hibernate\n                       |\n                       v\n                    MySQL<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For REST:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Postman \/ curl \/ Frontend\n          |\n          v\n  TodoRestController\n          |\n          v\n     TodoService\n          |\n          v\n   TodoRepository\n          |\n          v\n       MySQL<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Create<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>POST \/todos\n       \u2193\nController\n       \u2193\nService\n       \u2193\nRepository\n       \u2193\nINSERT\n       \u2193\nMySQL<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Read<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/\n   \u2193\nController\n   \u2193\nService\n   \u2193\nRepository\n   \u2193\nSELECT\n   \u2193\nThymeleaf\n   \u2193\nHTML<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Update<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>PUT \/api\/todos\/1\n       \u2193\nController\n       \u2193\nService\n       \u2193\nRepository\n       \u2193\nUPDATE\n       \u2193\nMySQL<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Delete<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>DELETE \/api\/todos\/1\n       \u2193\nController\n       \u2193\nService\n       \u2193\nRepository\n       \u2193\nDELETE\n       \u2193\nMySQL<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">17. Final API table<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Method<\/th><th>URL<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>GET<\/td><td><code>\/api\/todos<\/code><\/td><td>Get all<\/td><\/tr><tr><td>GET<\/td><td><code>\/api\/todos\/1<\/code><\/td><td>Get one<\/td><\/tr><tr><td>POST<\/td><td><code>\/api\/todos<\/code><\/td><td>Create<\/td><\/tr><tr><td>PUT<\/td><td><code>\/api\/todos\/1<\/code><\/td><td>Update<\/td><\/tr><tr><td>PATCH<\/td><td><code>\/api\/todos\/1\/toggle<\/code><\/td><td>Toggle<\/td><\/tr><tr><td>DELETE<\/td><td><code>\/api\/todos\/1<\/code><\/td><td>Delete<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And the web application:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Method<\/th><th>URL<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>GET<\/td><td><code>\/<\/code><\/td><td>Todo home<\/td><\/tr><tr><td>POST<\/td><td><code>\/todos<\/code><\/td><td>Add<\/td><\/tr><tr><td>GET<\/td><td><code>\/todos\/edit\/1<\/code><\/td><td>Edit page<\/td><\/tr><tr><td>POST<\/td><td><code>\/todos\/update\/1<\/code><\/td><td>Update<\/td><\/tr><tr><td>GET<\/td><td><code>\/todos\/toggle\/1<\/code><\/td><td>Toggle<\/td><\/tr><tr><td>GET<\/td><td><code>\/todos\/delete\/1<\/code><\/td><td>Delete<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This gives you a complete <strong>Spring Boot + Maven + MySQL + JPA\/Hibernate + Thymeleaf + Bootstrap + REST CRUD<\/strong> project suitable for practicing in Eclipse on Ubuntu.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete Spring Boot&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,9,8,24,30,10],"tags":[33,31,23,32],"class_list":["post-27","post","type-post","status-publish","format-standard","hentry","category-java","category-linux","category-maven","category-mysql","category-spring","category-web","tag-application","tag-spring","tag-ubuntu","tag-web"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"DEVESH\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/boot-code.com\/?p=27\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"boot-code.com - programming tutorials\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Spring Boot Todo Web Application with MySQL Extension - boot-code.com\" \/>\n\t\t<meta property=\"og:description\" content=\"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/boot-code.com\/?p=27\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-08T16:17:16+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-08T16:17:19+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Spring Boot Todo Web Application with MySQL Extension - boot-code.com\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#blogposting\",\"name\":\"Spring Boot Todo Web Application with MySQL Extension - boot-code.com\",\"headline\":\"Spring Boot Todo Web Application with MySQL Extension\",\"author\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?author=1#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/#organization\"},\"datePublished\":\"2026-10-08T16:17:16+00:00\",\"dateModified\":\"2026-10-08T16:17:19+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#webpage\"},\"articleSection\":\"JAVA, Linux, Maven, MySQL, Spring, Web, application, spring, UBUNTU, web\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/boot-code.com\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?cat=3#listItem\",\"name\":\"JAVA\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?cat=3#listItem\",\"position\":2,\"name\":\"JAVA\",\"item\":\"https:\\\/\\\/boot-code.com\\\/?cat=3\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#listItem\",\"name\":\"Spring Boot Todo Web Application with MySQL Extension\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#listItem\",\"position\":3,\"name\":\"Spring Boot Todo Web Application with MySQL Extension\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?cat=3#listItem\",\"name\":\"JAVA\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/#organization\",\"name\":\"boot-code.com boot-code.com\",\"description\":\"programming tutorials programming tutorials\",\"url\":\"https:\\\/\\\/boot-code.com\\\/\",\"telephone\":\"+919259571202\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?author=1#author\",\"url\":\"https:\\\/\\\/boot-code.com\\\/?author=1\",\"name\":\"DEVESH\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"DEVESH\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#webpage\",\"url\":\"https:\\\/\\\/boot-code.com\\\/?p=27\",\"name\":\"Spring Boot Todo Web Application with MySQL Extension - boot-code.com\",\"description\":\"Great. Let\\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\\\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \\u2192 Service \\u2192 Repository \\u2192 MySQL rather than just copying code. Below is a complete\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?p=27#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?author=1#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/?author=1#author\"},\"datePublished\":\"2026-10-08T16:17:16+00:00\",\"dateModified\":\"2026-10-08T16:17:19+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/boot-code.com\\\/#website\",\"url\":\"https:\\\/\\\/boot-code.com\\\/\",\"name\":\"boot-code.com\",\"description\":\"programming tutorials\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/boot-code.com\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Spring Boot Todo Web Application with MySQL Extension - boot-code.com","description":"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete","canonical_url":"https:\/\/boot-code.com\/?p=27","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/boot-code.com\/?p=27#blogposting","name":"Spring Boot Todo Web Application with MySQL Extension - boot-code.com","headline":"Spring Boot Todo Web Application with MySQL Extension","author":{"@id":"https:\/\/boot-code.com\/?author=1#author"},"publisher":{"@id":"https:\/\/boot-code.com\/#organization"},"datePublished":"2026-10-08T16:17:16+00:00","dateModified":"2026-10-08T16:17:19+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/boot-code.com\/?p=27#webpage"},"isPartOf":{"@id":"https:\/\/boot-code.com\/?p=27#webpage"},"articleSection":"JAVA, Linux, Maven, MySQL, Spring, Web, application, spring, UBUNTU, web"},{"@type":"BreadcrumbList","@id":"https:\/\/boot-code.com\/?p=27#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/boot-code.com\/#listItem","position":1,"name":"Home","item":"https:\/\/boot-code.com\/","nextItem":{"@type":"ListItem","@id":"https:\/\/boot-code.com\/?cat=3#listItem","name":"JAVA"}},{"@type":"ListItem","@id":"https:\/\/boot-code.com\/?cat=3#listItem","position":2,"name":"JAVA","item":"https:\/\/boot-code.com\/?cat=3","nextItem":{"@type":"ListItem","@id":"https:\/\/boot-code.com\/?p=27#listItem","name":"Spring Boot Todo Web Application with MySQL Extension"},"previousItem":{"@type":"ListItem","@id":"https:\/\/boot-code.com\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/boot-code.com\/?p=27#listItem","position":3,"name":"Spring Boot Todo Web Application with MySQL Extension","previousItem":{"@type":"ListItem","@id":"https:\/\/boot-code.com\/?cat=3#listItem","name":"JAVA"}}]},{"@type":"Organization","@id":"https:\/\/boot-code.com\/#organization","name":"boot-code.com boot-code.com","description":"programming tutorials programming tutorials","url":"https:\/\/boot-code.com\/","telephone":"+919259571202"},{"@type":"Person","@id":"https:\/\/boot-code.com\/?author=1#author","url":"https:\/\/boot-code.com\/?author=1","name":"DEVESH","image":{"@type":"ImageObject","@id":"https:\/\/boot-code.com\/?p=27#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?s=96&d=mm&r=g","width":96,"height":96,"caption":"DEVESH"}},{"@type":"WebPage","@id":"https:\/\/boot-code.com\/?p=27#webpage","url":"https:\/\/boot-code.com\/?p=27","name":"Spring Boot Todo Web Application with MySQL Extension - boot-code.com","description":"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/boot-code.com\/#website"},"breadcrumb":{"@id":"https:\/\/boot-code.com\/?p=27#breadcrumblist"},"author":{"@id":"https:\/\/boot-code.com\/?author=1#author"},"creator":{"@id":"https:\/\/boot-code.com\/?author=1#author"},"datePublished":"2026-10-08T16:17:16+00:00","dateModified":"2026-10-08T16:17:19+00:00"},{"@type":"WebSite","@id":"https:\/\/boot-code.com\/#website","url":"https:\/\/boot-code.com\/","name":"boot-code.com","description":"programming tutorials","inLanguage":"en-US","publisher":{"@id":"https:\/\/boot-code.com\/#organization"}}]},"og:locale":"en_US","og:site_name":"boot-code.com - programming tutorials","og:type":"article","og:title":"Spring Boot Todo Web Application with MySQL Extension - boot-code.com","og:description":"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete","og:url":"https:\/\/boot-code.com\/?p=27","article:published_time":"2026-10-08T16:17:16+00:00","article:modified_time":"2026-10-08T16:17:19+00:00","twitter:card":"summary_large_image","twitter:title":"Spring Boot Todo Web Application with MySQL Extension - boot-code.com","twitter:description":"Great. Let\u2019s upgrade the Todo application into a proper Spring Boot CRUD project with: Add Todo View Todo Edit Todo Delete Todo Mark Complete\/Incomplete Validation Bootstrap UI REST API MySQL persistence We can build it incrementally so you understand Controller \u2192 Service \u2192 Repository \u2192 MySQL rather than just copying code. Below is a complete"},"aioseo_meta_data":{"post_id":"27","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_image_url":null,"twitter_title":null,"twitter_description":null,"schema_type":"default","schema_type_options":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"BlogPosting","isEnabled":true},"graphs":[]},"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"created":"2026-10-08 16:17:19","updated":"2026-10-08 16:46:50"},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/boot-code.com\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/boot-code.com\/?cat=3\" title=\"JAVA\">JAVA<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tSpring Boot Todo Web Application with MySQL Extension\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/boot-code.com\/"},{"label":"JAVA","link":"https:\/\/boot-code.com\/?cat=3"},{"label":"Spring Boot Todo Web Application with MySQL Extension","link":"https:\/\/boot-code.com\/?p=27"}],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/posts\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boot-code.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=27"}],"version-history":[{"count":1,"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":28,"href":"https:\/\/boot-code.com\/index.php?rest_route=\/wp\/v2\/posts\/27\/revisions\/28"}],"wp:attachment":[{"href":"https:\/\/boot-code.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boot-code.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boot-code.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}