Task Task List Relationship
Now that we have our basic Task and TaskList entities, let's set up the relationship between them. Looking at our domain model, we can see that a TaskList contains many Tasks, and each Task belongs to exactly one TaskList.
Adding Tasks to TaskList
First, let's add the tasks field to our TaskList class. We'll use a List to hold the Task objects:
@OneToMany(mappedBy = "taskList", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
private List<Task> tasks;Let's break down the annotations:
@OneToManyindicates that oneTaskListcan have manyTasksmappedBy = "taskList"tells JPA that theTaskentity owns the relationship through itstaskListfieldcascade = {CascadeType.REMOVE, CascadeType.PERSIST}means:- When we delete a
TaskList, all itsTaskswill be deleted too (REMOVE) - When we save a
TaskList, any newTasksit contains will be saved too (PERSIST)
- When we delete a
Adding TaskList to Task
Now in our Task class, we need to add the reference back to TaskList:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "task_list_id")
private TaskList taskList;Let's break down these annotations:
@ManyToOneindicates that manyTaskscan belong to oneTaskListfetch = FetchType.LAZYmeans theTaskListwon't be loaded from the database until it's actually needed@JoinColumn(name = "task_list_id")specifies the foreign key column name in the tasks table
Updating Constructors and Methods
Now we need to update our constructors, getters, and setters in both classes. Let's start with TaskList:
- Update the all-args constructor to include tasks:
public TaskList(UUID id, String title, String description, List<Task> tasks,
LocalDateTime created, LocalDateTime updated) {
this.id = id;
this.title = title;
this.description = description;
this.tasks = tasks;
this.created = created;
this.updated = updated;
}- Add getter and setter for tasks:
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}And for the Task class:
- Update the all-args constructor to include taskList:
public Task(UUID id, String title, String description, LocalDateTime dueDate,
TaskPriority priority, TaskStatus status, LocalDateTime created,
LocalDateTime updated, TaskList taskList) {
this.id = id;
this.title = title;
this.description = description;
this.dueDate = dueDate;
this.priority = priority;
this.status = status;
this.created = created;
this.updated = updated;
this.taskList = taskList;
}- Add getter and setter for taskList:
public TaskList getTaskList() {
return taskList;
}
public void setTaskList(TaskList taskList) {
this.taskList = taskList;
}Don't forget to update your equals(), hashCode(), and toString() methods in both classes to include the new fields. Your IDE can help generate these for you.
A Note on Bi-directional Relationships
With this bi-directional relationship set up, when we load a TaskList, we can access its Tasks, and when we load a Task, we can access its TaskList
Summary
- We added a one-to-many relationship in
TaskListto manage itsTasks - We added a many-to-one relationship in
Taskto reference itsTaskList - We configured cascading to handle
Tasklifecycle with itsTaskList - We updated constructors and methods to handle the new relationship fields