JPA의 매핑 관계를 설정할 때 조금 복잡한 상황을 보자.
1 2 3 4 5 | @ManyToMany @JoinTable(name = "recipe_category", joinColumns = @JoinColumn(name = "recipe_id"), inverseJoinColumns = @JoinColumn(name = "category_id")) private Set<Category> categories = new HashSet<>(); | cs |
다 대 다 관계에서 @ManyToMany를 썼다. John Tompson께서 이런 상황은 많이 발생하지 않는다고는 한다. 지금 보면 Recipe와 Category 두 테이블이 다 대 다 관계로 묶여있다. 그래서 처음에 @JoinTable에서 이름을 "recipe_category"로 정해주었다. 이름은 명시적으로 조인된 테이블을 나타내기 위해 저렇게 지정했다. 그리고 JoinColumn에서 recipe_id가 들어오고 반대편에서 category_id가 들어오게 설정하였다. 그러면 조인테이블에는 두 테이블의 pk가 들어가게 된다.
반대 편 테이블을 보면
1 2 | @ManyToMany(mappedBy = "categories") private Set<Recipe> recipes; | cs |
mappedBy속성으로 아까 처음 테이블의 필드명을 정의 해주었다.
* 전체 적인 JPA 매핑 과정
하나의 모델 (여기서는 Recipe)을 정의한다.
그리고 Service단과 데이터조회를 위한 repositories 패키지 안에 Repository를 정의해준다.
RecipeService 인터페이스를 RecipeServiceImpl에서 구현해주고 RecipeServiceImpl은 RecipleRepository를 Dependecny Injection을 해준다.
1 2 3 4 5 6 7 8 | @Service public class RecipeServiceImpl implements RecipeService { private final RecipeRepository recipeRepository; public RecipeServiceImpl(RecipeRepository recipeRepository) { this.recipeRepository = recipeRepository; } | cs |
이런식으로 의존성 주입을 해준다. 의존성 주입에서 constructor based (생성자 기반 의존성주입) injection을 하였다. (클래스가 초기화 될 때 바로 의존성을 주입할 수 있게 되고 @Autowired까지 생략 가능하다.)
1 2 3 4 | public interface RecipeRepository extends CrudRepository<Recipe, Long> { } | cs |
Recipe Repository는 CrudRepository를 상속받는다.
CrudRepository를 열어보면 기본적인 DB CRUD기능을 할 수 있는 인터페이스를 만들어 놓았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @NoRepositoryBean public interface CrudRepository<T, ID> extends Repository<T, ID> { <S extends T> S save(S var1); <S extends T> Iterable<S> saveAll(Iterable<S> var1); Optional<T> findById(ID var1); boolean existsById(ID var1); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> var1); long count(); void deleteById(ID var1); void delete(T var1); void deleteAll(Iterable<? extends T> var1); void deleteAll(); } | cs |
** JPA 관련 질문 내용 정리
* Entity Relationship의 4가지 타입은 무엇인가?
@OneToOne, @OneToMany, @ManyToOne, @ManyToMany
* Join table이 필요한 JPA relationship은?
@ManyToMany가 조인테이블이 필요하다.
* 단방향 관계 (unidirectional) 와 양방향 관계 (bidirectional)의 차이는 무엇인가?
단방향은 한쪽이 다른 한쪽을 모른다는 점이고 양방향은 서로의 관계를 인식하고 있다는 점이다. 양방향 관계를 쓰는것이 더 좋다.
* JPA에서 쓸 수 있는 2가지 fetch type은?
Lazy, Eager
* JPA Cascade Type은 무엇을 하는가?
부모 object에서 자식 object로 cascade하는 것을 제어한다.
* JPA 2.1에서 default Cascade Type은 무엇인가?
없다. JPA는 default Cascade Type이 없다.
* JPA 2.1에서 가능한 6가지 Cascade Type은?
PERSIST, MERGE, REFRESH, REMOVE, DETACH, ALL
* JPA는 object 상속을 지원하는가?
지원한다. JPA클래스는 슈퍼클래스로부터 상속 가능하다.
* Hiberante의 상속의 default persistence strategy는 무엇인가?
Single Table이다. 하나의 테이블이 슈퍼테이블로 만들어지고 서브클래스들을 상속관계에 둔다.
* Single Table strategy의 단점은 무엇인가?
사용하지 않는 db 칼럼이 생길 수 있다.
* Join Table strategy의 단점은 무엇인가?
서브클래스 엔티티 조회를 위해 슈퍼클래스와의 조인작업이 필요하다.
JPA가 자동으로 timestamp를 갱신하는가?
그렇다. @PrePersist @PreUpdate를 사용하고 Hibernate specific으로 @CreationTimestamp, @UpdateTimestamp를 사용한다.
* SQL은 무엇의 줄인말인가?
Structured Query Language
* DDL은 무엇의 줄인말인가?
Data Definition Language
* DML은 무엇의 줄인말인가?
Data Manipulation Language
* DDL과 DML의 차이점은 무엇인가?
DDL은 데이터베이스 구조를 정의한다 (테이블, 인덱스 등) DML은 data operation을 제어한다. (insert, update 등)
* Spring boot가 database 초기화를 위해 사용하는 두 가지는 무엇인가?
Spring boot는 schema.sql, data.sql 를 찾기 위해 루트 패스를 탐색한다.
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] Bcrypt를 이용하여 비밀번호를 암호화하여 저장하는 방법 - 실제 프로젝트 적용기 (0) | 2019.07.20 |
---|---|
[Spring] Spring Interceptor (인터셉터)와 WebTestClient Session (세션) 테스트 적용기 (4) | 2019.07.18 |
[Spring] 스프링 Properties 관리하기 (0) | 2018.11.13 |
[Spring] SpringFramework Configuration, 각종 스프링 관련 면접 질문 (0) | 2018.11.12 |
[SpringOneTour] 스프링을 만든 Pivotal사가 한국을 방문했다! (0) | 2018.11.08 |