๋จ๋ฐฉํฅ @OneToMany์ ๋ฌธ์ ์
๊ฐ์
JPA๋ฅผ ํ์ตํ๋ค ๋ณด๋ฉด @OneToMany๋ฅผ ์ฌ์ฉํ ๋ ๋จ๋ฐฉํฅ๋ณด๋ค๋ ์๋ฐฉํฅ ๋งคํ์ ์ฌ์ฉํ๋ผ๋ ๋ง์ ์์ฃผ ๋ฃ๊ฒ ๋๋ค.
์ ๊ทธ๋ฐ์ง ์ดํดํ๊ธฐ ์ํด ๋จ๋ฐฉํฅ @OneToMany๋ฅผ ์ฌ์ฉํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ฌธ์ ์ ์ ๋ํด ์ดํด๋ณด๊ณ , ์๋ฐฉํฅ์ ์ฌ์ฉํ์ ๋ ์ด๋ค ์ ์ด ๊ฐ์ ๋๋์ง ์์๋ณด์
- ๋งคํ ํ ์ด๋ธ์ ์ฌ์ฉํ ๋จ๋ฐฉํฅ @OneToMany ๋์ ๊ณผ์
- @JoinColumn ์ฌ์ฉํ ๋จ๋ฐฉํฅ @OneToMany ๋์ ๊ณผ์
- ์๋ฐฉํฅ @OneToMany๋ฅผ ์ฌ์ฉํ์ ๋์ ๋์ ๊ณผ์
1. ๋งคํ ํ ์ด๋ธ ์ฌ์ฉ
๋งคํ ํ ์ด๋ธ์ ์ด์ฉํ @OneToMany ์ํฐํฐ ์ค๊ณ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String isbn;
}
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
public void removeBook(Book book) {
books.remove(book);
}
}
๊ทธ๋ฆฌ๊ณ ํ ์ด๋ธ์ ๊ด๊ณ๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ ๊ฒ์ด๋ค.
์ด ๊ฒฝ์ฐ ์ฐ๊ฒฐ ํ ์ด๋ธ(author_books)์๋ ๋ ๊ฐ์ ์ธ๋ํค(author_id, books_id)๊ฐ ์๋ค. ๋๋ฌธ์ ์ธ๋ฑ์ฑ ์ book ํ ์ด๋ธ์์ author์ id๋ฅผ ์ง์ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ๋ณด๋ค ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค. ๋ํ book, author_books, author ๊ฐ์ 3๊ฐ์ ์กฐ์ธ์ด ํ์ํ์ฌ ์ฟผ๋ฆฌ ์์ ์๋ ์ํฅ์ ๋ฏธ์น๋ค.
์ด์ INSERT์ DELETE์ ์ด๋ ํ ๊ณผ์ ์ด ์ผ์ด๋๋์ง ์ดํด๋ณด์
1. ์๋ก์ด ์๊ฐ ๋ฐ์ดํฐ ๋ฑ๋ก
์๋ก์ด ์๊ฐ์ ๊ทธ ์๊ฐ์ ์ฑ ์ ๋ฑ๋กํ๋ ์์์ด๋ค.
@Transactional
public void insertAuthorWithBooks() {
Author author = new Author("JK ๋กค๋ง", 42);
Book book1 = new Book("ํด๋ฆฌํฌํฐ์ ๋ง๋ฒ์ฌ์ ๋", "978-89-12345-00-1");
Book book2 = new Book("ํด๋ฆฌํฌํฐ์ ๋น๋ฐ์ ๋ฐฉ", "978-89-12345-00-2");
author.addBook(book1);
author.addBook(book2);
authorRepository.save(author);
}
์ ๋ฉ์๋๋ฅผ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ SQL ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ค.
Hibernate:
insert into author (age, name)
values (?, ?)
returning id
Hibernate:
insert into book (isbn, title)
values (?, ?)
returning id
Hibernate:
insert into book (isbn, title)
values (?, ?)
returning id
-- ์๋๋ ์๋ฐฉํฅ @OneToMany์์๋ ๋ ๋ผ๊ฐ์ง ์๋ ์ถ๊ฐ insert ์ฟผ๋ฆฌ๋ค
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
2. ๊ธฐ์กด ์ ์์ ์๋ก์ด ๋์ ๋ฑ๋ก
์์์ ๋ฑ๋กํ ์๊ฐ์ ์๋ก์ด ๋์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด ๋ณด์.
@Transactional
public void insertNewBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
Book newBook = new Book("ํด๋ฆฌํฌํฐ์ ์์ฆ์นด๋ฐ์ ์ฃ์", "978-89-12345-00-3");
author.addBook(newBook);
authorRepository.save(author);
}
์ ๋ฉ์๋๋ฅผ ์ํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ๊ฐ ๋ ๋ผ๊ฐ๋ค.
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_1.id, b1_1.isbn, b1_1.title
from author_books b1_0
join book b1_1
on b1_1.id=b1_0.books_id
where b1_0.author_id=?
Hibernate:
insert into book (isbn, title)
values (?, ?)
returning id
-- ์๋ DML๋ฌธ๋ค์ ์๋ฐฉํฅ @OneToMany์์๋ ๋ํ๋์ง ์๋๋ค.
Hibernate:
delete from author_books
where author_id=?
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
์ ๋ณด๋ฉด author_books์ delete์ฟผ๋ฆฌ ํ ๊ฐ๊ฐ ๋ ๋ผ๊ฐ๊ณ , ํ ๊ฐ์ ์ ์๋ฅผ ๋ฑ๋กํ์์๋ ๋ถ๊ตฌํ๊ณ 3๊ฐ์ insert์ฟผ๋ฆฌ๊ฐ ๋ ๋ผ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ๊ทธ ์ด์ ๋ ์ ๋์๋ฅผ ์ถ๊ฐํ๊ณ ์ JPA๋ ์ฐ๊ฒฐ ํ ์ด๋ธ์์ ๋ชจ๋ ์ฐ๊ด ๋์๋ฅผ ์ญ์ ํ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ ๋์๋ฅผ ์ถ๊ฐํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ๋ฑ๋กํ๊ธฐ ๋๋ฌธ์ด๋ค.
3. ๋ง์ง๋ง ๋์ ์ญ์
๋ค์์ ์ ์์ ์ฐ๊ด๋ ๋์ ๋ฆฌ์คํธ์์ ๋ง์ง๋ง ๋์๋ฅผ ์ญ์ ํ๋ ์์์ด๋ค. ๋ง์ง๋ง ๋์ ์ญ์ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์์ ์ฐ๊ด๋ List<Book>์ ๊ฐ์ ธ์ค๊ณ ์ด ๋ฆฌ์คํธ์์ ๋ง์ง๋ง ๋์๋ฅผ ์ญ์ ํ๋ค.
@Transactional
public void deleteLastBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book lastBook = books.get(books.size() - 1);
author.removeBook(lastBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_1.id, b1_1.isbn, b1_1.title
from author_books b1_0
join book b1_1
on b1_1.id=b1_0.books_id
where b1_0.author_id=?
Hibernate:
delete from author_books
where author_id=?
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
-- ์๋ฐฉํฅ @OneToMany์์ ์ ์ผํ๊ฒ ํ์ํ DML
Hibernate:
delete from book
where id=?
๋ง์ง๋ง ๋์๋ฅผ ์ญ์ ํ๊ณ ์ JPA๋ ์ฐ๊ฒฐ ํ ์ด๋ธ(author_books)์์ ๋ชจ๋ ์ฐ๊ด ๋์๋ฅผ ์ญ์ ํ๊ณ , ๋ฉ๋ชจ๋ฆฌ์์ ๋ง์ง๋ง ๋์๋ฅผ ์ ๊ฑฐํ ํ ๋๋จธ์ง ๋์๋ฅผ ๋ค์ ์ฝ์ ํ๋ค. ๋ฐ๋ผ์ ์๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ์ ๋น๊ตํ์ ๋ ๋ถํ์ํ DML๋ฌธ์ด ์ถ๊ฐ๋ก ๋ฐ์ํ๊ฒ ๋์ด ์ฑ๋ฅ ์ ํ๋ฅผ ์ด๋ํ ์ ์๊ณ , ํนํ ์ฐ๊ด๋ ๋์๊ฐ ๋ง์์๋ก ์ํ์ฑ์ด ๋์ฑ ์ปค์ง๋ค.
4. ์ฒซ ๋ฒ์งธ ๋์ ์ญ์
๋ค์์ ์ ์์ ์ฐ๊ด๋ ๋์ ๋ฆฌ์คํธ์์ ์ฒซ ๋ฒ์งธ ๋์๋ฅผ ์ญ์ ํ๋ ์์์ด๋ค.
@Transactional
public void deleteFirstBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book firstBook = books.get(0);
author.removeBook(firstBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_1.id, b1_1.isbn, b1_1.title
from author_books b1_0
join book b1_1
on b1_1.id=b1_0.books_id
where b1_0.author_id=?
Hibernate:
delete from author_books
where author_id=?
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
Hibernate:
insert into author_books (author_id, books_id)
values (?, ?)
-- ์๋ฐฉํฅ @OneToMany์์ ์ ์ผํ๊ฒ ํ์ํ DML
Hibernate:
delete from book
where id=?
์ฒซ ๋ฒ์งธ ๋์๋ฅผ ์ญ์ ํ๋ ์์ ๋ ๋ง์ง๋ง ๋์๋ฅผ ์ญ์ ํ๋ ๊ฒ๊ณผ ๋์ผํ ๊ณผ์ ์ ๊ฑฐ์น๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ ์ฒด์ ์ผ๋ก ์ ๋ฆฌํ๋ฉด, ๋งคํ ํ ์ด๋ธ์ ์ฌ์ฉํ ๋จ๋ฐฉํฅ @OneToMany ๊ด๊ณ๋ ์๋์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๋ค.
- ์ถ๊ฐ SQL ๋ฌธ์ ๋์ ๊ฐ์๋ก ์ธํ ์ฑ๋ฅ ์ ํ
- ์ฐ๊ฒฐ ํ ์ด๋ธ์ ์ธ๋ํค ์ปฌ๋ผ๊ณผ ๊ด๋ จ๋ ์ธ๋ฑ์ค ํญ๋ชฉ์ ์ญ์ ๋ฐ ์ฌ์ถ๊ฐ๋ก ์ธํ ์ฑ๋ฅ ์ ํ ๋ฌธ์
๋๋ถ๋ถ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ธ๋ํค์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ฐ๊ฒฐ ํ ์ด๋ธ์์ ๋ถ๋ชจ ์ํฐํฐ์ ์ฐ๊ด๋ ๋ชจ๋ ํ ์ด๋ธ ํ์ ์ญ์ ํ ๋ ํด๋น ์ธ๋ฑ์ค ํญ๋ชฉ๋ ์ญ์ ๋๊ณ , ์ฐ๊ฒฐ ํ ์ด๋ธ์ ๋ค์ ์ถ๊ฐ๋ ๋ ์ธ๋ฑ์ค ํญ๋ชฉ์ด ์ถ๊ฐ๋๋ค.
2. @JoinColumn ์ฌ์ฉ
์ด์ @JoinColumn์ ์ฌ์ฉํ ๋จ๋ฐฉํฅ @OneToMany ๊ด๊ณ์ ๋ํด ์ดํด๋ณด์.
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "author_id")
private Long authorId; // authorId ์ถ๊ฐ
private String title;
private String isbn;
}
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "author_id") // @JoinColumn ์ฌ์ฉ
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
public void removeBook(Book book) {
books.remove(book);
}
}
@JoinColumn์ ์ง์ ํ๋ฉด @OneToMany ์ฐ๊ด๊ด๊ณ์์ ์์ ํ ์ด๋ธ์ ์ธ๋ํค๋ฅผ ์ ์ดํ ์ ์์์ Hibernate์ ์ง์ํ ์ ์๋ค. ์ด๋ฅผ ํตํด ์ฐ๊ฒฐ ํ ์ด๋ธ์ด ์์ด์ง๊ณ , ํ ์ด๋ธ ์๊ฐ 3๊ฐ์์ 2๊ฐ๋ก ์ค์ด๋ ๋ค.
์ด์ ๋์ผํ ๋ฉ์๋๋ค์ ๋์์ ํ์ธํด ๋ณด์. ์คํ ์ฝ๋๋ ์ด์ ๊ณผ ๋์ผํ๋ค.
1. ์๋ก์ด ์๊ฐ ๋ฐ์ดํฐ ๋ฑ๋ก
@Transactional
public void insertAuthorWithBooks() {
Author author = new Author("JK ๋กค๋ง", 42);
Book book1 = new Book("ํด๋ฆฌํฌํฐ์ ๋ง๋ฒ์ฌ์ ๋", "978-89-12345-00-1");
Book book2 = new Book("ํด๋ฆฌํฌํฐ์ ๋น๋ฐ์ ๋ฐฉ", "978-89-12345-00-2");
author.addBook(book1);
author.addBook(book2);
authorRepository.save(author);
}
Hibernate:
insert into author (age, name)
values (?, ?)
returning id
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
-- ์๋ฐฉํฅ @OneToMany์์๋ ํ์ ์๋ ์ถ๊ฐ DML
Hibernate:
update book
set author_id=?
where id=?
Hibernate:
update book
set author_id=?
where id=?
๋งคํ ํ ์ด๋ธ์ ์ฌ์ฉํ์ ๋์ ๋ฌ๋ฆฌ, @JoinColumn์ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ฑ๋ก๋๋ ๊ฐ ๋์์ ๋ํด Hibernate๋ author_id๋ฅผ ์ค์ ํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ UPDATE ์ฟผ๋ฆฌ๋ฅผ ํธ์ถํ๋ค. ๋ฌผ๋ก ์ด ๋ถ๋ถ๋ ์๋ฐฉํฅ @OneToMany ๊ด๊ณ์์๋ ์คํ๋์ง ์๋ ๋ถํ์ํ ์ฟผ๋ฆฌ๋ค์ด๋ค.
2. ๊ธฐ์กด ์ ์์ ์๋ก์ด ๋์ ๋ฑ๋ก
@Transactional
public void insertNewBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
Book newBook = new Book("ํด๋ฆฌํฌํฐ์ ์์ฆ์นด๋ฐ์ ์ฃ์", "978-89-12345-00-3");
author.addBook(newBook);
authorRepository.save(author);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_0.id, b1_0.isbn, b1_0.title
from book b1_0
where b1_0.author_id=?
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
-- ์๋ฐฉํฅ @OneToMany์์๋ ํ์ ์๋ ์ถ๊ฐ DML
Hibernate:
update book
set author_id=?
where id=?
Hibernate๋ ์๋ก ๋ฑ๋ก๋ ๋์์ ๋ํด author_id๋ฅผ ์ค์ ํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ UPDATE๋ฅผ ํธ์ถํ๋ค. ์ผ๋จ ๊ธฐ์กด์ ๋งคํ ํ ์ด๋ธ์ ํ์ฉํ ๋จ๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ์ ๋นํด ์ฟผ๋ฆฌ์ ๊ฐ์๊ฐ ์ค์ด๋ค์ด ๋์์ง๋ ์์ง๋ง, ์ฌ์ ํ @OneToMany ์ฐ๊ด๊ด๊ณ์์๋ ํ์ํ์ง ์์ UPDATE๋ฌธ์ด ์ฒ๋ฆฌ๋๋ค.
3. ๋ง์ง๋ง ๋์ ์ญ์
@Transactional
public void deleteLastBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book lastBook = books.get(books.size() - 1);
author.removeBook(lastBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_0.id, b1_0.isbn, b1_0.title
from book b1_0
where b1_0.author_id=?
Hibernate:
update book
set author_id=null
where author_id=?
and id=?
-- ์๋ฐฉํฅ @OneToMany์์ ํ์ํ ์ ์ผํ DML
Hibernate:
delete from book
where id=?
Hibernate๋ author_id๋ฅผ null๋ก ์ค์ ํด ์ ์๋ก๋ถํฐ ๋์ ์ฐ๊ด๊ด๊ณ๋ฅผ ๋๋๋ค. ๊ทธ๋ฐ ๋ค์ orphanRemoval = true ๋๋ถ์ ์ฐ๊ด์ด ํด์ ๋ ๋์๊ฐ ์ญ์ ๋๋ค. ์ด๊ฒ ๋ํ ๋งคํ ํ ์ด๋ธ์ ํ์ฉํ์ ๋๋ณด๋ค๋ ์ฟผ๋ฆฌ์ ๊ฐ์๊ฐ ์ค์ด๋ค์ง๋ง, ์ฌ์ ํ ์๋ฐฉํฅ @OneToMany๋ฅผ ์ฌ์ฉํ์ ๋๋ณด๋ค๋ ๋นํจ์จ์ ์ด๋ค.
4. ์ฒซ ๋ฒ์งธ ๋์ ์ญ์
@Transactional
public void deleteFirstBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book firstBook = books.get(0);
author.removeBook(firstBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_0.id, b1_0.isbn, b1_0.title
from book b1_0
where b1_0.author_id=?
-- ์๋ฐฉํฅ @OneToMany์์ ํ์ํ ์ ์ผํ DML
Hibernate:
update book
set author_id=null
where author_id=?
and id=?
Hibernate:
delete from book
where id=?
UPDATE๊ฐ ์ฌ์ ํ ์กด์ฌํ๋ค.
์ ๋ฆฌํ๋ฉด, @JoinColumn์ ์ถ๊ฐํ๋ฉด ๋งคํ ํ ์ด๋ธ์ ํ์ฉํ ๋จ๋ฐฉํฅ @OneToMany๋ณด๋ค๋ ์ด์ ์ ์ ๊ณตํ ์ ์์ง๋ง, ์ฌ์ ํ ์๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ๋ณด๋ค๋ ๋ซ์ง ์์ผ๋ฉฐ, ์ถ๊ฐ UPDATE๋ฌธ์ ํตํด ์ฌ์ ํ ์ฑ๋ฅ ์ ํ ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค.
์๋ฐฉํฅ @OneToMany
์ด์ ์๋ฐฉํฅ @OneToMany๋ฅผ ์ฌ์ฉํ์ ๋ ์ผ๋ง๋ ํจ์จ์ ์ธ์ง ์ดํด๋ณด์. ์๋๋ ์๋ฐฉํฅ @OneToMany ๊ด๊ณ๋ฅผ ๋งบ์ ์์ ์ฝ๋์ด๋ค.
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
private String title;
private String isbn;
}
@Entity
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author", orphanRemoval = true)
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
book.setAuthor(this);
}
public void removeBook(Book book) {
books.remove(book);
book.setAuthor(null);
}
}
์๋ฐฉํฅ ๊ด๊ณ์์๋ mappedBy ์์ฑ์ด ์ค์ํ ์ญํ ์ ํ๋๋ฐ, ๋ถ๋ชจ ์ธก์ ์ค์ ๋๋ mappedBy ์์ฑ์ ์๋ฐฉํฅ ์ฐ๊ด๊ด๊ณ์ ํน์ฑ์ ๋ถ์ฌํ๋ค. ๋ค์ ๋งํด ์๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ์์ ๋ถ๋ชจ ์ธก @OneToMany์ mappedBy๊ฐ ์ง์ ๋๊ณ , mappedBy์ ์ํด ์ฐธ์กฐ๋๋ ์์ ์ธก์ @ManyToOne์ด ์ง์ ๋๋ค.
์ด์ ๋์ผํ ๋ฉ์๋๋ฅผ ์ํํ์ ๋ ์ด๋ป๊ฒ ์ฟผ๋ฆฌ๊ฐ ์ํ๋๋์ง ๋น ๋ฅด๊ฒ ์ดํด๋ณด์.
1. ์๋ก์ด ์๊ฐ ๋ฐ์ดํฐ ๋ฑ๋ก
@Transactional
public void insertAuthorWithBooks() {
Author author = new Author("JK ๋กค๋ง", 42);
Book book1 = new Book("ํด๋ฆฌํฌํฐ์ ๋ง๋ฒ์ฌ์ ๋", "978-89-12345-00-1");
Book book2 = new Book("ํด๋ฆฌํฌํฐ์ ๋น๋ฐ์ ๋ฐฉ", "978-89-12345-00-2");
author.addBook(book1);
author.addBook(book2);
authorRepository.save(author);
}
Hibernate:
insert into author (age, name)
values (?, ?)
returning id
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
2. ๊ธฐ์กด ์ ์์ ์๋ก์ด ๋์ ๋ฑ๋ก
@Transactional
public void insertNewBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
Book newBook = new Book("ํด๋ฆฌํฌํฐ์ ์์ฆ์นด๋ฐ์ ์ฃ์", "978-89-12345-00-3");
author.addBook(newBook);
authorRepository.save(author);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
insert into book (author_id, isbn, title)
values (?, ?, ?)
returning id
3. ๋ง์ง๋ง ๋์ ์ญ์
@Transactional
public void deleteLastBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book lastBook = books.get(books.size() - 1);
author.removeBook(lastBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_0.id, b1_0.isbn, b1_0.title
from book b1_0
where b1_0.author_id=?
Hibernate:
delete from book
where id=?
4. ์ฒซ ๋ฒ์งธ ๋์ ์ญ์
@Transactional
public void deleteFirstBook() {
Author author = authorRepository.findByName("JK ๋กค๋ง");
List<Book> books = author.getBooks();
Book firstBook = books.get(0);
author.removeBook(firstBook);
}
Hibernate:
select a1_0.id, a1_0.age, a1_0.name
from author a1_0
where a1_0.name=?
Hibernate:
select b1_0.author_id, b1_0.id, b1_0.isbn, b1_0.title
from book b1_0
where b1_0.author_id=?
Hibernate:
delete from book
where id=?
์ ๋ณด๋ฉด ๋จ๋ฐฉํฅ @OneToMany์์ ๋ณด์๋ ๋ถํ์ํ INSERT๋ UPDATE๋ฌธ์ด ์ํ๋์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์ฒด์ ์ผ๋ก ์๋ฐฉํฅ์ผ ๋๋ ์ฝ๋๋ฅผ ๋ดค์ ๋ ์ง๊ด์ ์ผ๋ก ๋ฑ ์์๋๋ ์ฟผ๋ฆฌ๋ค๋ง ์ํ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ ๋ฆฌ
@JoinColumn์ ์ถ๊ฐํ ๋จ๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ๋ ๋งคํ ํ ์ด๋ธ์ ํ์ฉํ ๋จ๋ฐฉํฅ @OneToMany๋ณด๋ค๋ ์ด์ ์ ์ ๊ณตํ์ง๋ง, ์ฌ์ ํ ์๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ๋ณด๋ค๋ ๋นํจ์จ์ ์ด๋ค. ์ถ๊ฐ UPDATE๋ฌธ์ด ๋ฐ์ํ์ฌ ์ฑ๋ฅ ์ ํ ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค.
์๋ฐฉํฅ @OneToMany ์ฐ๊ด๊ด๊ณ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ ์ฝ๊ธฐ, ์ฐ๊ธฐ, ์ญ์ ์์ ์์ ๋ ํจ์จ์ ์ด๋ค. ๋ฐ๋ผ์ ๋จ๋ฐฉํฅ @OneToMany๋ณด๋ค๋ ์๋ฐฉํฅ ๋งคํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฑ๋ฅ ๋ฐ ํจ์จ์ฑ ์ธก๋ฉด์์ ๊ถ์ฅ๋๋ค.