JPA가 뭘까 고민하기 시작한건 프로젝트를 구현할 때였다. 프로젝트를 진행하다보면 테이블끼리 Join 하여 정보를 출력해줄 일이 생긴다. 하지만, 우리는 Mybatis를 통해 프로젝트를 구현 중이었는데, 조인은 JPA 관련 자료만 잔뜩 떴다...
JPA가 뭐길래 이렇게 잔뜩 뜨는지 궁금해졌다. 프로젝트 때는 JPA를 잘 몰랐기 때문에 Mybatis를 사용하여 조인을 구현했다. 방법은 새로운 DTO를 생성하던지 기존 DTO 클래스에 조인할 DTO를 상속받던지 해야한다.
JPA는 Spring에서 Mybatis를 사용하지 않고 DB를 조작할 수 있는 기술 중 하나이다. JPA는 실질적인 ORM을 사용하는데, Mapper XML과 SQL문을 쓰는 Mybatis는 ORM을 빙자한거고 실질적으로는 ORM이 아니다.
JPA는 Java Persistence API 이다.
이 때 persistence란 영속성이다. 영속성은 데이터를 생성한 프로그램이 종료되어도 사라지지 않는 데이터의 특성인데, 이것은 DB에 저장된 데이터의 특징이니 DB를 다루는 JPA에겐 어찌보면 당연하다고 말할 수 있겠다.
내가 본 자료에선 실무에선 Mybatis는 Mybatis 쓰는데가 있고 JPA는 JPA를 쓴다고 한다. 즉, 혼용해서 사용한다는 건데 왜 혼용하게 될까? JPA는 CRUD에만 치중되어 있고 디테일하게 프로시저나 SQL문을 쓰려면 Mybatis를 사용해야 되기 떄문이다.
Entity는 무엇일까? DB테이블과 연결되어야 하는 데이터 형태라고 생각하면 편할 것 같다. 엔티티는 도메인 클래스에 매핑한 것이다. 엔티티가 메모리 상에 올라가게 되면 DB와 도메인 클래스와 동기화된다.
엔티티 매니저는 필요에 따라 엔티티와 데이터베이스의 데이터를 동기화하는데 이 매니저에 따라 DB가 변하면 엔티티가 변할수 있다. 또한 CRUD 작업을 할 수 있다.
영속성 컨텍스트는 엔티티를 영구적으로 저장하는 환경이다. 해당 데이터를 검색하거나 저장할 때 사용하게 된다. 영속성 컨텍스트에 접근하거나 관리를 위해 엔티티 매니저를 통해야 한다. 비영속은 영속성 컨텍스트와 관련이 없는 상태를 말하고, 영속은 영속성 컨텍스트에 저장된 상태이다.
Hibernate와 연동시키기 위해 spring.jpa 5줄을 작성해준다. 다른 구문들은 익히 봤듯이 jdbc를 사용하기 위한 녀석들이다.
spring.jpa.show-sql=true 는 sql문을 콘솔에 띄워주는 역할이다.
아래는 com.project.domain 패키지 안에 MemberDTO 클래스를 하나 생성해주었다.
어노테이션 @Id 로 적게되면 Primary key를 지정한다. @GeneratedValue(strategy = GenerationType.SEQUENCE) 하면 시퀀스가 적용된다. 시퀀스가 적용된다는 말은 이 엔티티가 늘어날때마다 숫자가 하나씩 늘어난다는 소리다.
@Enumerated(EnumType.STRING)는 열거형으로 선언된 파일을 적용시키겠다는 뜻이다.
@Temporal(TemporalType.DATE) Date형식으로 정하겠다는 뜻이고
@CreationTimestamp 도 비슷한 개념이라고 보면 되겠다.
JPA 특이한 점중 하나는 DB 컬럼명을 다른 두 단어에서는 단어사이에 언더바를 추가해 넣고, 도메인 클래스에는 그 두 단어 사이에 낙타표기법이 적용된다. JPA를 실행하게 되면 SQL상의 Create 테이블을 자동으로 해주고 DB 테이블과 동기화 하게 된다.
위 JPA 레퍼런스를 보면 이와 같은 함수들이 나와있다.
이 것이 Repository 클래스에 상속시키면 바로 쓸 수 있는 기본적인 함수들이다. 실행시키는 것도 간단하다. src/main/java의 com.project.repository 패키지 안에 다음과 같은 MemberRepository 클래스를 넣는다.
src/test/java의 com.project에 JUnit 테스트를 할 아래와 같은 메소드를 넣게 되면 JUnit 실행을 시킬 수 있다.
이렇게 Member DB에 추가된 것을 볼 수 있다.
@OneToOne
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "PARENT_ID"),
inverseJoinColumns = @JoinColumn(name = "CHILD_ID")
)
@ManyToOne(optional = false)
@JoinTable(name = "PARENT_CHILD",
joinColumns = @JoinColumn(name = "CHILD_ID"),
inverseJoinColumns = @JoinColumn(name = "PARENT_ID")
)
이런 Annotation을 도메인 클래스 안에 붙이는 식으로 조인할 수 있다. Mybatis 가 DTO 클래스를 하나 추가시키거나 상속시키는데 반해 더 직관적이라 볼 수 있겠다. ( OneToOne이나 ManyToOne 처럼 영어로 표현하므로)
이게 JPA이자 Hibernate이다. 기본적인 CRUD 형태를 SQL문을 몰라도 작업 할 수 있는 형태를 지니고 있다. 물론 더 복잡한 DB작업을 위해서는 SQL문을 사용하는 JPQL이나 동적으로 변경해주는 Querydsl을 사용해야한다. JPQL이나 Querydsl은 시간이 되거나 프로젝트에서 사용을 할 때 다시금 정리하는 기회를 가지려고 한다!