问题
I am struggling with understanding how to use Spring Data/JPA to interact with a database. I'm using the simple H2 database currently for testing purposes.
I have a main item, Task
, that in addition to fields, also has two collections of "child" data: TaskNote
and StateChangeHistory
.
In my task service class, I have a @PostConstruct
method to set up some dummy data and save it to the database so that I can retrieve and display it later. It appears that the Task
is being saved, but none of the children are. When I load the data into a view (or inspect the data in the debugger), the child collections are always empty.
What do I need to do to ensure that the Task and it's child items are all saved?
Here is some of the code:
Task.java:
@Entity
@NamedEntityGraph(name = "graph.task", attributeNodes = { @NamedAttributeNode("notes") })
public class Task extends AbstractEntity {
@OneToMany(mappedBy = "task")
private List<StateChangeHistory> stateHistory = new ArrayList<>();
@OneToMany(mappedBy = "task")
private List<TaskNote> notes = new ArrayList<>();
...
}
TaskNote.java:
@Entity
public class TaskNote extends AbstractEntity {
@ManyToOne
private Task task;
...
}
TaskRepository.java:
public interface TaskRepository extends JpaRepository<Task, Long> {
@Override
@EntityGraph(attributePaths = { "notes" })
public List<Task> findAll();
}
TaskService.java:
@Service
public class TaskService {
private TaskRepository taskRepository;
public TaskService(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
...
@PostConstruct
public void populateTestData() {
if (taskRepository.count() == 0) {
Task task = null;
TaskNote note = null;
// Task 1
task = new Task("Task-1");
task.setPriority(TaskPriority.HIGH);
task.setType(TaskType.RECURRING);
// Note 1
note = new TaskNote();
note.setNote("note-1");
task.getNotes().add(note);
// Note 2
note = new TaskNote();
note.setNote("note-2");
task.getNotes().add(note);
taskRepository.save(task);
// Task 2
taskRepository.save(new Task("Task-2"));
}
}
}
As you can see, I create a task object and add two notes to it and then try to save it. I assume the save of the task works, as I can get them to display in my view. However, the notes list is always empty.
What do I need to do to save the child data along with the parent?
回答1:
As stated in other answers you have to use @OneToMany(cascade=CascadeType.ALL)
over Task notes
.
To make code work you have to set a two-way entity relationship:
Task task = new Task("Task-1");
TaskNote note = new TaskNote();
note.setNote("note-1");
note.setTask(task); // missing in your code
task.getNotes().add(note);
taskRepository.save(task);
回答2:
There are three ways how to save the status of an entity using JPA.
Load the entity from the database and make changes to its state. JPA keeps track of these changes and will flush them (i.e. perform DML-statements) before the end of the transaction, typically exactly at the end of the transaction.
Create entities and
save
them to a repositoryPerform #2 with a different entity which references your entity with the reference annotated with
cascade=CascadeType.ALL
. ActuallyMERGE
andPERSIST
are sufficient but I think if you cascade you should cascade all.
回答3:
Solution
You can solve it by just adding cascade= CascadeType.ALL
in @OneToMany annotation as a property .
来源:https://stackoverflow.com/questions/65081753/spring-data-jpa-how-do-i-save-an-item-with-multiple-child-collections