J.J. Beam
J.J. Beam

Reputation: 3059

Does JPA framework save One-To-Many relationship automatically?

Suppose I've One-To-Many Relationship: One-To-Many

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

@Entity
@Table(name = "books")
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String author;
    @Column(unique = true)
    private String isbn;

    @OneToMany(mappedBy = "book", fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private Set<Page> pages;

    public Book() {
    }

    public Book(String title, String author, String isbn) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
    }

    // getters and setters, equals(), toString() .... (omitted for brevity)
}

And

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "pages")
public class Page implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private int number;
    private String content;
    private String chapter;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "book_id", nullable = false)
    private Book book;

    public Page() {
    }

    public Page(int number, String content, String chapter, Book book) {
        this.number = number;
        this.content = content;
        this.chapter = chapter;
        this.book = book;
    }

    // getters and setters, equals(), toString() .... (omitted for brevity)
}

And store it with:

// create a new book
Book book = new Book("Java 101", "John Doe", "123456");
    
// save the book
bookRepository.save(book);
    
// create and save new pages
pageRepository.save(new Page(1, "Introduction contents", "Introduction", book));
pageRepository.save(new Page(65, "Java 8 contents", "Java 8", book));
pageRepository.save(new Page(95, "Concurrency contents", "Concurrency", book));

The question is: do I really need to save every page manually? Can I just work with java collections and then just save the main entity like:

book.pages.add(new Page(1, "Introduction contents", "Introduction", book));

book.pages.add(new Page(65, "Java 8 contents", "Java 8", book));

book.pages.add(new Page(95, "Concurrency contents", "Concurrency", book));

bookRepository.save(book);

The example was taken from https://attacomsian.com/blog/spring-data-jpa-one-to-many-mapping

And I wanna know the right and the best way to store relationships, that's why I'm asking here and not just experiment by myself, because it seems the article misleading tons of people

Upvotes: 0

Views: 529

Answers (1)

Ken Chan
Ken Chan

Reputation: 90517

Here is what cascade on the Book#pages comes into play. As you configured it as CascadeType.ALL, it means that when you use EntityManager to persist() on a Book, it will automatically call persist() on all its Page.

With cascade disabled, you have to call the following to save a new Book and all of its pages:

entityManager.persist(book);
entityManager.persist(page1);
entityManager.persist(page2);
....
entityManager.persist(pageN);

But with cascade enabled, you just have to call the following as all the persist() on Page will be cascaded to be called automatically.

entityManager.persist(book);

As the spring-data-jpa repositories internally just use the same EntityManager to save objects for the same transaction, you just need to call the following to save the book and its pages if cascade is enabled:

Book book = new Book("Java 101", "John Doe", "123456");
book.pages.add(new Page(1, "Introduction contents", "Introduction", book));
book.pages.add(new Page(65, "Java 8 contents", "Java 8", book));
book.pages.add(new Page(95, "Concurrency contents", "Concurrency", book));
bookRepository.save(book);

Otherwise if cascade is disabled, you have to call the following to save a Book and its pages:

Book book = new Book("Java 101", "John Doe", "123456");
bookRepository.save(book);

pageRepository.save(new Page(1, "Introduction contents", "Introduction", book));
pageRepository.save(new Page(65, "Java 8 contents", "Java 8", book));
pageRepository.save(new Page(95, "Concurrency contents", "Concurrency", book));

Upvotes: 1

Related Questions