Spring Data JPA + Hibernate save children entities without finding parent firstly

Viewed 141

In my opinion, if you want to save children entities, you must find their parent firstly. But it's not true. Following is an example.

Person table

public class Person {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  
  @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
  private List<Book> books;
}

Book table

public class Book {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;

  @ManyToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "person_id", nullable = false)
  private Person person;
}

BookRepository

public interface BookRepository extends CrudRepository<Book, Long> {}

persist process

// the person(id=1) is in the database.
Person p = new Person();
p.setId(1);

Book book = new Book();
book.setPerson(p);
book.setName("book");

bookRepository.save(book); // no error throws

I want to know why the last statement is success. The person instance is created manually and is not retrieved from database by Spring Data JPA, I think it means the state of person instance is transient.

2 Answers

Based on your logic Book and person are new then you have to create those objects. Why you think it should come from database. If you want retrieve the user by findbyId then set the newly created book in List and save the user object behind the scenes it will do the updation in the database for that user.

You can use personRepository.getOne(1) which will return a proxy for a person with id 1. Setting this object then as person on the book will do what you are looking for.

Related