I'm working on a simple todo app in which you can add dependencies between todo items which means you cannot change status to true(completed) if dependency item is not completed. The problem is when I delete an item which another item is dependent to, json still shows dependency between two items. I'll try to explain with an example; say you have item 1 and item 2. Item 1 is dependent to item 2 and you can't mark item 1 "completed" if item 2 is not completed. But if you delete item 2 then dependency between items is also gone. So after deleting item 2 I can change item 1's status to true but when I make a get request for item 1, json still shows dependency to item 2.
Here is my TodoItem class;
package com.erdemkara.todoapp.data.entity;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.*;
import java.time.LocalDate;
import java.util.Set;
@Entity
@Table(name = "todo_items")
public class TodoItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String name;
private String description;
@Column(nullable = false)
private LocalDate deadline;
@Column(nullable = false)
private boolean status;
@Column(name = "todo_list_id", nullable = false)
private int todoListId;
@OneToMany(mappedBy = "todoItem", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonManagedReference
private Set<Dependency> dependencies;
public TodoItem()
{}
public TodoItem(int id, String name, String description, LocalDate deadline,
boolean status, int todoListId, Set<Dependency> dependencies)
{
this.id = id;
this.name = name;
this.description = description;
this.deadline = deadline;
this.status = status;
this.todoListId = todoListId;
this.dependencies = dependencies;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDate getDeadline() {
return deadline;
}
public void setDeadline(LocalDate deadline) {
this.deadline = deadline;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
@JsonGetter("todo_list_id")
public int getTodoListId() {
return todoListId;
}
public void setTodoListId(int todoListId) {
this.todoListId = todoListId;
}
public Set<Dependency> getDependencies() {
return dependencies;
}
public void setDependencies(Set<Dependency> dependencies) {
this.dependencies = dependencies;
}
}
Dependency class;
package com.erdemkara.todoapp.data.entity;
import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
@Entity
@Table(name = "dependencies")
public class Dependency {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
private int id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "todo_item_id", nullable = false)
@JsonBackReference
private TodoItem todoItem;
@Column(name = "dependency_item_id", nullable = false)
private int dependencyItemId;
public Dependency()
{}
public Dependency(int id, TodoItem todoItem, int dependencyItemId)
{
this.id = id;
this.todoItem = todoItem;
this.dependencyItemId = dependencyItemId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public TodoItem getTodoItem() {
return todoItem;
}
public void setTodoItem(TodoItem todoItem) {
this.todoItem = todoItem;
}
public int getDependencyItemId() {
return dependencyItemId;
}
public void setDependencyItemId(int dependencyItemId) {
this.dependencyItemId = dependencyItemId;
}
}
Response for item 1 get request(item 1 is dependent to item 2 and 3);
{
"id": 1,
"name": "Item 1",
"description": "Study Collections",
"deadline": "2023-01-09",
"status": false,
"dependencies": [
{
"dependencyItemId": 3
},
{
"dependencyItemId": 2
}
],
"todo_list_id": 1
}
I get the same response before and after deleting item 2. But I want to get a response like this;
{
"id": 1,
"name": "Item 1",
"description": "Study Collections",
"deadline": "2023-01-09",
"status": false,
"dependencies": [
{
"dependencyItemId": 3
}
],
"todo_list_id": 1
}
How can I fix this?
EDIT: @Zychoo I use 2 different delete methods on Service layer. One is for deleting all dependencies for an item. The other one is to delete a specific dependency;
public void deleteDependencyByDependencyItemId(int todoItemId, int dependencyItemId) {
dependencyRepository.deleteByDependencyItemId(todoItemId, dependencyItemId);
}
public void deleteAllDependenciesByTodoItemId(int todoItemId) {
dependencyRepository.deleteAll(dependencyRepository.findAllByTodoItemId(todoItemId));
}
And this is the Repository Layer;
public interface IDependencyRepository extends CrudRepository<Dependency, Integer> {
@Modifying
@Transactional
@Query(value = "delete from dependencies d where d.todo_item_id=? and d.dependency_item_id =?", nativeQuery = true)
void deleteByDependencyItemId(int todoItemId, int dependencyItemId);
}
CodePudding user response:
You could changed
public Set<Dependency> getDependencies() {
return dependencies;
}
to
public Set<Dependency> getDependencies() {
return dependencies.stream().filter(dependency -> "your condition for completion").collect(Collectors.toSet());
}
The ObjectMapper from spring-boot uses the getters to create a JSON. If your Dependency does not show up in the return value of your getter, it will not show up in the JSON response.
CodePudding user response:
I reorganized delete method in TodoItem service layer from this:
public void deleteItemById(int id) {
todoItemRepository.deleteById(id);
}
to this:
public void deleteItemById(int id) {
todoItemRepository.deleteById(id);
dependencyService.deleteAllDependenciesByTodoItemId(id);
}
It deletes every dependency along with the item. Now it works as I expected. Thank you for the answers.