프로그래밍/Spring

[Spring] 스프링 JPA 흐름, JPA 관련 질문 내용 정리

Jay Tech 2018. 11. 17. 17:34
반응형

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> {
    <extends T> S save(S var1);
 
    <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 를 찾기 위해 루트 패스를 탐색한다.


반응형