Home [JPA] JPA란?
Post
Cancel

[JPA] JPA란?

SQL 중심적인 개발의 문제점


데이터베이스에서는 관계형 DB, 어플리케이션에서는 객체지향언어인 자바를 사용한다 했을 때, 자바에서 사용하는 객체를 SQL문으로 관계형 DB에 저장해야 한다. 그러기 위해서 자바에서는 객체를 SQL문으로 변환하여 DB에 접근하고, SQL을 자바 객체로 변환해야 하는데, 이 작업은 상당히 지루하고 반복적인 코드가 나오게 된다.

Untitled.png

위의 사진은 만약 요구사항중에 회원 객체에 전화번호 속성이 추가되었다면, 개발자들은 직접 SQL문에 전화번호 속성들을 추가해야 하는 작업이 생기게 된다. 개발자들은 이런식으로 일일이 다 SQL문으로 다 바꿔서 DB에 저장하면 시간도 오래걸리고 단순반복의 코드가 늘어날 것이다. 이처럼 SQL에 의존적인 개발은 좋지 않다!!

Untitled1.png

이 자바 객체와 관계형 데이터베이스사이에 SQL변환하는 과정에서 어려움이 생기는 이유는 바로 객체와 관계형 데이터베이스간의 패러다임이 일치하지 않아서 생기는 문제이다.

패러다임의 불일치 객체 VS 관계형 DB


객체와 관계형 DB는 크게 2가지의 차이점이 존재한다.

  • 상속
  • 연관관계

상속

  • 객체지향에서는 객체사이에 상속관계가 존재하지만, 관계형 데이터베이스 테이블에 상속관계라는 것이 존재하지 않는다.
  • 데이터베이스에는 상속관계와 유사한 Table 슈퍼타입과 서브타입 관계가 있긴하지만 자바의 상속관계랑 개념이 똑같지가 않아 이 객체를 DB에 저장할 때 어려움이 있다.

Untitled2.png

연관관계

  • 객체는 참조를 사용한다. ex) member.getTeam();
  • 테이블은 외래키를 사용한다. ex) JOIN ON M.TEAM_ID = T.TEAM_ID
  • 이 때문에 객체의 참조로 맺는 연관관계를 DB에 저장할때 굉장히 까다롭다.

Untitled3.png

자바 객체와 DB의 매핑 작업이 매우 많아지기 때문에 자바 컬렉션처럼 DB에 저장할 수 있는 개념이 바로 JPA이다.

JPA란?


Java Persistence API로 자바 진영의 ORM 표준 기술이다. 그럼 여기서 ORM은 뭘까?

ORM은 Object Relational Mapping의 약자로 객체랑 관계형 DB를 서로 매핑해주는 프레임워크다.

Untitled4.png

위의 그림과 같이 JPA는 어플리케이션과 JDBC사이에서 동작한다. 즉, 완전히 새로운 기술이 아니라 원래 자바가 JDBC로 DB랑 통신을 했지만 JPA도 JDBC사이에서 동작하는 것이다.

Untitled5.png

만약 회원 객체를 저장하면, JPA는 이 회원 객체(Entity)를 분석 후 INSERT문 SQL문을 직접 생성해서 JDBC API를 이용해서 데이터베이스에 저장한다.

Untitled6.png

JPA는 표준 명세(인터페이스의 모음)이고 어플리케이션은 JPA의 구현체들을 사용하여 ORM 프레임워크를 사용해야 한다. 그 중 JPA 구현체인 Hibernate를 많이 쓴다.

JPA를 사용해야 하는 이유


SQL 중심적인 개발에서 이제는 객체 중심으로 설계를 하면 JPA가 알아서 SQL문을 작성해주기 때문에 생산성, 유지보수 측면에서 높은 효율을 얻을 수 있다.

Untitled7.png

위의 사진처럼 개발자는 jpa.persist한줄의 코드로 album객체를 넣어주면 쿼리문은 JPA가 알아서 처리를 해준다.

JPA의 성능 최적화 기능


  1. 1차 캐시와 동일성(identity) 보장
  2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
  3. 지연 로딩(Lazy Loading)

1차 캐시와 동일성(identity) 보장

  • 같은 트랜잭션 안에서는 같은 엔티티를 반환한다 - 약간의 조회 성능 향상
  • DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장한다.
1
2
3
4
String memberId = "100";
Member m1 = jpa.find(Member.class, memberId); //SQL
Member m2 = jpa.find(Member.class, memberId); //캐시
println(m1 == m2) //true

위와 같은 문장에서 DB로부터 2번의 조회 문장이 있는 것 같지만 실제로는 SQL문이 한번만 나간다.

트랜잭션을 지원하는 쓰기 지연 - INSERT

  • 트랜잭션을 커밋할 때까지 INSERT SQL을 모으고 JDBC BATCH SQL 기능을 사용해서 한번에 SQL을 전송한다.
1
2
3
4
5
6
7
8
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.

transaction.commit(); 
// [트랜잭션] 커밋

위와 같은 코드로 구성하면 commit 시점에 insert문 sql이 나가 쿼리를 한번만 질의할 수 있게 된다. 이로써 네트워크 통신 비용을 줄일 수 있다.

지연 로딩(Lazy Loading)

  • 지연로딩은 객체가 실제 사용될 때 로딩되는거를 말하고 즉시 로딩은 JOIN SQL로 한번에 연관된 객체까지 미리 조회하는 것을 말한다.

Untitled8.png

위의 사진과 같이 지연로딩은 객체가 실제 사용될때 쿼리문이 나가는 것이고, 즉시 로딩은 sql문이 나갈때 객체와 연관된 테이블까지 다 같이 조회하는 것을 말한다.

[자바의 정석] 배열

[자바의 정석] 클래스와 객체