위의 백기선님 영상에서 제시된 문제의 원인을 연관관계 매핑 시 @JoinColumn을 선언하지 않아서라고 생각했다. 하지만 답은 연관관계 편의 메서드를 통해 객체의 연관관계를 양방향으로 설정하지 않은 것이었다.
다대일 매핑 시 항상 @JoinColumn을 선언했었는데, 위의 영상으로 인해 @JoinColumn의 역할에 대해 자세히 공부해 볼 필요성을 느꼈다.
예제로 진행할 전체 코드는 아래와 같다.
Book 클래스
@Entity
public class Book {
@Id @GeneratedValue
private Integer id;
private String isbn;
private String title;
@ManyToOne
private BookStore bookStore;
...
}
BookStore 클래스
@Entity
public class BookStore {
@Id @GeneratedValue
private Integer id;
private String name;
@OneToMany(mappedBy = "bookStore")
private Set<Book> books = new HashSet<>();
public void add(Book book) {
book.setBookStore(this);
this.books.add(book);
}
...
}
Main()
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
BookStore bookStore = new BookStore();
bookStore.setName("시애틀 책방");
em.persist(bookStore);
Book book = new Book();
book.setTitle("JPA 공부 좀 하면서 쓰세요.");
bookStore.add(book);
em.persist(book);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
테스트 1 - @JoinColumn 사용
@Entity
public class Book {
@Id @GeneratedValue
private Integer id;
private String isbn;
private String title;
@ManyToOne
@JoinColumn(name = "BOOKSTORE_ID")
private BookStore bookStore;
...
}
- DB 조회 결과
테스트 2 - @JoinColumn 생략
@Entity
public class Book {
@Id @GeneratedValue
private Integer id;
private String isbn;
private String title;
@ManyToOne
private BookStore bookStore;
...
}
- DB 조회 결과
테스트 3 - @JoinColumn에 임의의 다른 이름 지정
@Entity
public class Book {
@Id @GeneratedValue
private Integer id;
private String isbn;
private String title;
@ManyToOne
@JoinColumn(name = "ABCDEFG")
private BookStore bookStore;
...
}
- DB 조회 결과
테스트 결과
@JoinColumn은 생략될 경우 자동으로 참조 엔티티의 이름_기본키를 컬럼명으로 지정한다.
또한, name 속성은 매핑할 외래키의 이름을 지정하는 속성이다.
그렇다면 외래 키로 매핑할 컬럼을 지정하는 방법은?
referencedColumnName 속성을 통해 참조 테이블의 필드명을 직접 지정할 수 있다.
@ManyToOne
@JoinColumn(name = "ABCDEFG", referencedColumnName = "id")
private BookStore bookStore;
또한 해당 속성도 생략할 경우 자동으로 참조 테이블의 pk 값을 외래 키로 매핑한다.
정리
@JoinColumn: 외래 키를 매핑할 때 사용하는 어노테이션
속성 | 기능 | 기본값 |
name | 매핑할 외래 키 컬럼명 | 필드명_참조하는 테이블의 기본 키 컬럼명 |
referencedColumnName | 참조하는 대상 테이블의 외래 키 컬럼명 | 참조하는 테이블의 기본 키 컬럼명 |
따라서 다대다 매핑 시 컬럼명을 기본 값으로 사용할 경우에는 @JoinColumn
을 생략할 수 있다.
참고로 일대다 매핑 시에는 @JoinColumn
을 필수로 선언해야 한다. 그렇지 않으면 기본적으로 조인 테이블 전략을 사용한다.
'Framework > JPA' 카테고리의 다른 글
[JPA] 페이징 처리 성능 최적화하기 (1) | 2024.02.11 |
---|---|
[QueryDSL] DTO로 조회하기 (0) | 2023.10.15 |
[JPA] @MappedSupperclass vs @Embedded & @Embeddable (0) | 2023.10.01 |
[JPA] 순한 참조 문제 해결하기 (0) | 2023.10.01 |