Absolutely. Since you’ve already been setting up Java + Maven + MySQL + Eclipse on Ubuntu, here is a complete beginner-friendly tutorial to build a Spring Boot Todo Web Application with MySQL.
We’ll use:
- Java 17+
- Maven
- Spring Boot
- Spring Web
- Spring Data JPA
- MySQL
- Thymeleaf
- Eclipse/STS
- HTML/CSS
1. Project architecture
We will build:
Todo Web Application
|
v
Controller
|
v
Service
|
v
Repository
|
v
MySQL
The browser will provide a simple UI:
+----------------------------------+
| TODO APPLICATION |
+----------------------------------+
| Add Todo: [ Learn Spring ] [Add]|
+----------------------------------+
| ID | Todo | Action |
| 1 | Learn Java | Delete |
| 2 | Learn Spring | Delete |
+----------------------------------+
2. Create Spring Starter Project
Open Spring Initializr:
Select:
Project: Maven
Language: Java
Spring Boot: latest stable version
Group: com.example
Artifact: todo
Name: todo
Packaging: Jar
Java: 17 or newer
Add these dependencies:
Spring Web
Spring Data JPA
MySQL Driver
Thymeleaf
Spring Boot DevTools
Then click Generate and download the ZIP.
Extract it:
cd ~/Downloads
unzip todo.zip
cd todo
Open it in Eclipse:
File
→ Import
→ Maven
→ Existing Maven Projects
→ Select todo folder
→ Finish
3. Create MySQL database
Start MySQL:
sudo systemctl start mysql
Open MySQL:
sudo mysql
Create the database:
CREATE DATABASE todo_db;
Create a user:
CREATE USER 'todo_user'@'localhost'
IDENTIFIED BY 'todo_password';
Give permissions:
GRANT ALL PRIVILEGES ON todo_db.*
TO 'todo_user'@'localhost';
Apply:
FLUSH PRIVILEGES;
Check:
SHOW DATABASES;
Exit:
exit;
4. Configure Spring Boot
Open:
src/main/resources/application.properties
Add:
spring.application.name=todo
spring.datasource.url=jdbc:mysql://localhost:3306/todo_db
spring.datasource.username=todo_user
spring.datasource.password=todo_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.thymeleaf.cache=false
server.port=8080
Important
This setting:
spring.jpa.hibernate.ddl-auto=update
allows Hibernate/JPA to automatically create/update tables based on our Java entity.
For example, our Java class:
@Entity
public class Todo {
...
}
will result in a table similar to:
todo
----------------
id
title
completed
5. Create Todo Entity
Create:
src/main/java/com/example/todo/model/Todo.java
Code:
package com.example.todo.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Todo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private boolean completed;
public Todo() {
}
public Todo(String title) {
this.title = title;
this.completed = false;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
}
6. Create Repository
Create:
src/main/java/com/example/todo/repository/TodoRepository.java
package com.example.todo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.todo.model.Todo;
public interface TodoRepository extends JpaRepository<Todo, Long> {
}
That’s it.
Spring Data JPA automatically provides methods such as:
findAll()
findById()
save()
deleteById()
count()
So we don’t need to manually write SQL for basic CRUD operations.
7. Create Service
Create:
src/main/java/com/example/todo/service/TodoService.java
package com.example.todo.service;
import java.util.List;
import org.springframework.stereotype.Service;
import com.example.todo.model.Todo;
import com.example.todo.repository.TodoRepository;
@Service
public class TodoService {
private final TodoRepository todoRepository;
public TodoService(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
public List<Todo> getAllTodos() {
return todoRepository.findAll();
}
public void addTodo(String title) {
Todo todo = new Todo(title);
todoRepository.save(todo);
}
public void deleteTodo(Long id) {
todoRepository.deleteById(id);
}
public void toggleTodo(Long id) {
Todo todo = todoRepository.findById(id)
.orElseThrow();
todo.setCompleted(!todo.isCompleted());
todoRepository.save(todo);
}
}
8. Create Web Controller
Create:
src/main/java/com/example/todo/controller/TodoController.java
package com.example.todo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.example.todo.service.TodoService;
@Controller
public class TodoController {
private final TodoService todoService;
public TodoController(TodoService todoService) {
this.todoService = todoService;
}
@GetMapping("/")
public String home(Model model) {
model.addAttribute(
"todos",
todoService.getAllTodos()
);
return "index";
}
@PostMapping("/add")
public String addTodo(
@RequestParam String title) {
todoService.addTodo(title);
return "redirect:/";
}
@GetMapping("/delete")
public String deleteTodo(
@RequestParam Long id) {
todoService.deleteTodo(id);
return "redirect:/";
}
@GetMapping("/toggle")
public String toggleTodo(
@RequestParam Long id) {
todoService.toggleTodo(id);
return "redirect:/";
}
}
9. Understand the Controller
When the browser visits:
http://localhost:8080/
Spring calls:
@GetMapping("/")
public String home(Model model)
It gets the todos:
todoService.getAllTodos()
and sends them to Thymeleaf:
model.addAttribute("todos", ...);
Finally:
return "index";
means:
templates/index.html
will be displayed.
10. Create HTML page
Create:
src/main/resources/templates/index.html
Put:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Todo Application</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f4f4f4;
margin: 40px;
}
.container {
max-width: 700px;
margin: auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
text-align: center;
}
form {
display: flex;
gap: 10px;
margin-bottom: 25px;
}
input {
flex: 1;
padding: 10px;
}
button {
padding: 10px 15px;
cursor: pointer;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px;
border-bottom: 1px solid #ddd;
}
.completed {
text-decoration: line-through;
}
a {
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Todo Application</h1>
<form action="/add" method="post">
<input
type="text"
name="title"
placeholder="Enter todo"
required>
<button type="submit">
Add
</button>
</form>
<table>
<thead>
<tr>
<th>ID</th>
<th>Todo</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr th:each="todo : ${todos}">
<td th:text="${todo.id}">
1
</td>
<td>
<span
th:text="${todo.title}"
th:classappend="${todo.completed} ? 'completed' : ''">
Learn Spring
</span>
</td>
<td>
<a
th:href="@{/toggle(id=${todo.id})}">
Toggle
</a>
<a
th:href="@{/delete(id=${todo.id})}">
Delete
</a>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
11. Run the application
In Eclipse:
Right click TodoApplication.java
↓
Run As
↓
Spring Boot App
Or from terminal:
./mvnw spring-boot:run
You should see something similar to:
Tomcat started on port 8080
Started TodoApplication
Open:
http://localhost:8080
12. Test the application
Enter:
Learn Java
Click:
Add
Then:
Learn Spring Boot
Click:
Add
Your page should show:
+--------------------------------------+
| Todo Application |
+--------------------------------------+
| [ Learn Spring Boot ] [ Add ] |
+--------------------------------------+
| ID | Todo | Action |
| 1 | Learn Java | Toggle Delete|
| 2 | Learn Spring Boot | Toggle Delete|
+--------------------------------------+
13. Check MySQL
Open MySQL:
mysql -u todo_user -p
Enter:
todo_password
Select database:
USE todo_db;
Show tables:
SHOW TABLES;
You should see something similar to:
todo
Check records:
SELECT * FROM todo;
Example:
+----+------------------+-----------+
| id | title | completed |
+----+------------------+-----------+
| 1 | Learn Java | 0 |
| 2 | Learn Spring Boot| 0 |
+----+------------------+-----------+
14. Understand the complete flow
When you click Add:
HTML
|
| POST /add
v
TodoController
|
v
TodoService
|
v
TodoRepository
|
v
Hibernate/JPA
|
v
MySQL
For example:
todoRepository.save(todo);
causes Hibernate to generate an SQL INSERT similar to:
INSERT INTO todo
(title, completed)
VALUES
('Learn Spring Boot', false);
When you open /:
Browser
|
v
Controller
|
v
Service
|
v
Repository
|
v
MySQL
|
v
Thymeleaf
|
v
HTML
15. Project structure
Your final project should look approximately like:
todo/
│
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/todo/
│ │ │ │
│ │ │ ├── TodoApplication.java
│ │ │ │
│ │ │ ├── controller/
│ │ │ │ └── TodoController.java
│ │ │ │
│ │ │ ├── model/
│ │ │ │ └── Todo.java
│ │ │ │
│ │ │ ├── repository/
│ │ │ │ └── TodoRepository.java
│ │ │ │
│ │ │ └── service/
│ │ │ └── TodoService.java
│ │ │
│ │ └── resources/
│ │ │
│ │ ├── templates/
│ │ │ └── index.html
│ │ │
│ │ └── application.properties
│ │
│ └── test/
│
├── pom.xml
└── mvnw
What you have learned
This small project covers the core Spring Boot concepts:
| Technology | Purpose |
|---|---|
| Spring Boot | Application framework |
| Spring Web | HTTP/web requests |
| Controller | Handles browser requests |
| Service | Business logic |
| Repository | Database operations |
| JPA/Hibernate | Java ↔ SQL mapping |
| MySQL | Persistent database |
| Thymeleaf | HTML templates |
| Maven | Dependency/build management |
| Eclipse | Development IDE |
Next useful step: add Edit Todo, validation, Bootstrap styling, REST APIs (GET/POST/PUT/DELETE), and a proper database schema so this becomes a more realistic Spring Boot CRUD project.