자바 진영의 ORM(Object-Relational Mapping) 기술 표준인 JPA(Java Persistence API)에 대해 알아보자.
JPA는 자바 진영에서 ORM 기술 표준으로 사용되는 인터페이스의 모음이다. 이 말은, 실제적으로 구현된것이 아니라 구현된 클래스와 매핑을 시켜주기 위해 사용하는 프레임워크 이다. JPA를 구현한 대표적인 오픈소스로는 Hibernate가 있다.
JPA는 애플리케이션과 JDBC 사이에서 동작한다.
즉, JPA를 쓴다해서 JDBC를 사용 안하는것이 아니다!
애플리케이션의 Class와 RDB(Relational DataBase)의 테이블을 매핑(연결)한다는 뜻이며, 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이라고 보면된다.
SQL 중심이 아닌 객체 중심으로 개발하기 때문에 생산성이 좋아지고 유지보수가 수월하다.
자세히 알아보자..
이런 테이블 구조에서 Album 클래스를 저장한다고 가정해보자.
// Album 객체저장
jpa.persist(album);
이렇게 하면 JPA는 위의 코드를 아래의 쿼리로 변환하여 실행한다.
INSERT INTO ITEM (ID, NAME, PRICE) .....
INSERT INTO ALBUM (ARTIST) .....
Album을 Insert하게 되면 Album의 부모인 ITEM 객체도 Insert하게 된다.
조회도 마찬가지 이다.
// JAVA 코드
String albumId = "id100";
Album album = jpa.find(Album.class, albumId);
// 변환된 쿼리
SELECT I.*, A.*
FROM ITEM I
JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
자식인 Album 객체를 조회하게되면 부모인 Item 에서도 조회를 수행하게 된다.
다음으로 이런 연관관계를 가진 객체와 테이블에 대해 살펴보자.
Member 클래스가 Team 클래스를 필드로 가지고있다. 코드로 나타내면 아래와 같다.
class Member {
String id;
Team team;
String username;
}
class Team {
Long id;
String name;
}
member를 조회하게 되면 team도 가져오게된다.
// JAVA 코드
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
위 코드는 아래와 같다.
// 변환된 쿼리
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
살펴본 구조들이 더 복잡해져도 JPA는 문제없이 사용할 수 있다.
성능면에서도 JPA는 이점이 있다!
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId); // SQL
Member member2 = jpa.find(Member.class, memberId); // 캐시
member1 == member2; //같다.
JPA는 동일한 트랙잭션에서 조회한 엔티티는 같은 엔티티를 반환한다 -> 약간의 조회 성능 향상
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit(); // [트랜잭션] 커밋
transaction.begin(); // [트랜잭션] 시작
changeMember(memberA);
deleteMember(memberB);
비즈니스_로직_수행(); //비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.
//커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
지연 로딩에서는 team.getNAME 을 할 때 select를 하지만, 즉시 로딩은 find member 할때 다 가져온다!
추가적으로, 스프링에서 이때까지 사용해왔던 JPA는 JPA를 이용하는 spring-data-jpa 프레임워크이지 JPA는 아니라고 한다.