JPA (Java Persistence API)란?
자바 진영의 ORM 기술 표준
ORM?
- Object-Relational-Mapping(객체 관계 매핑)
- 객체는 객체대로 설계한다.
- 관계형 DB는 관계형 DB대로 설계
- ORM 프레임워크가 중간에서 매핑( 하나의 값을 다른 값으로 대응시키는 것)
즉, 객체와 관계형 DB를 각각 설계한 후, ORM으로 매핑시킨다.
JPA는 애플리케이션과 JDBC(자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API )사이에서 동작한다.
1. SQL을 직접 다룰 때 발생하는 문제점
1.1 반복 작업
SQL을 직접 다룰 때의 문제점을 보기 위한 기능 예시
public class Member
{
private String memberId;
private String name;
}
회원 객체
public class MemberManager
{
public Member find(String memberId){
// 1
String sql = "SELECT MEMBER_ID, NAME FROME MEMBER M WHERE MEMBER_ID = ?";
// 2
Statement stmt;
ResultSet res = stmt.excuteQuery(sql);
// 3
String memberId = res.getString("MEMBER_ID");
String name = res. getString("NAME");
Member member = new Member();
member.setMemberId(memberId);
member.setName(name);
return member;
}
}
회원 관리를 위한 Manager.
find(String memberId)로 회원을 조회한다.
- sql문 작성
- sql문 실행
- 조회 결과를 Member객체로 매핑
회원 추가, 수정, 삭제 또한 SQL을 작성하고, JDBC API를 사용하는 비슷한 일을 반복할 것이다.
만약, 회원 객체를 데이터베이스가 아닌 자바 컬렉션에 보관한다면 다음 한 줄로 저장할 수 있다.
list.add(member);
하지만 데이터베이스는 객체 구조와는 다른 데이터 중심의 구조이다.
때문에 데이터베이스에 직접 저장하거나 조회할 수는 없다.
즉, 개발자가 객체지향 애플리케이션과 데이터베이스 중간에서 SQL과 JDBC API를 코드로 작성해야 한다.
결국 하나의 애플리케이션에는 수많은 DB 테이블이 있을 것이다.
그러면 이런 비슷한 일을 더 많이 반복해야 한다.
1.2 SQL에 의존적
앞에서 만든 회원 객체를 관리하는 MemberManager를 완성하였다.
그런데 갑자기 회원의 연락처도 함께 저장해달라는 요구가 들어왔다.
public class Member
{
private String memberId;
private String name;
private String tel; // 추가
}
이렇게 되면 조회, 추가, 수정, 삭제의 코드 전체가 변동될 수 있다.
왜냐하면 매핑을 할 데이터가 늘어났으니까.
Member처럼 비즈니스 요구사항을 모델링한 객체를 엔티티라고 한다.
지금처럼 SQL에 모든것을 의존하는 상황에서는 개발자들이 Manager을 열어서 어떤 SQL이 실행되고 어떤 객체들이 함께 조회되는지 일일이 확인해야 한다.
즉,
- 진정한 의미의 계층 분할이 어렵다.
- 엔티티를 신뢰할 수 없다.
- SQL에 의존적인 개발을 피하기 어렵다.
1.3 JPA와 문제 해결
간단히 JPA가 문제를 해결하는 법을 알아보자.
JPA를 사용하면 객체를 DB에 저장하고 관리할 때, 개발자가 직접 SQL을 작성하는 것이 아니다.
JPA가 제공하는 API를 사용하면 개발자 대신 적절한 SQL문을 생성해서 DB에 전달한다.
jpa.persist(member); // 저장
persist() 메소드는 객체를 데이터베이스에 저장한다.
이 메서드를 호출하면 JPA가 객체와 매핑정보를 보고 적절한 INSERT SQL을 생성해서 DB에 전달한다.
String memberId = "helloId";
Member member = jpa.find(Member.class, memberId); // 조회
find() 메소드는 객체 하나를 데이터베이스에서 조회한다.
이 메서드를 호출하면 JPA가 객체와 매핑정보를 보고 적절한 SELECT SQL을 생성해서 DB에 전달한다.
그 결과로 Member 객체를 생성해서 반환한다.
수정기능과 연관된 객체를 조회하는 기능은 나중에 설명하겠다.
2. 패러다임의 불일치
애플리케이션은 전부터 점점 발전해나가면서 그 내부의 복잡성도 점점 커지고 있다.
지속 가능한 애플리케이션을 개발하기 위해선, 유지보수가 중요하다.
객체지향 프로그래밍은 추상화, 캡슐화, 상속, 다형성 등의 특성이 있다.
그 덕분에 현대의 복잡한 애플리케이션은 대부분 객체지향 언어로 개발된다.
엔티티들로 객체를 모델링하면 객체지향 언어가 가진 장점을 활용할 수 있다.
하지만 이 모델링한 엔티티를 저장할 때 문제가 생길 수 있다.
문제
class Dog
{
String name;
public void move(){}
}
Dog라는 클래스의 객체를 저장해야 하는 상황이 있다.
이때는 해당 객체 의 필드만을 저장하면 나중에 DB에 접근해서 처리를 해야할 때 문제없이 이용할 수 있다.
하지만
만약 이 객체가 부모 객체를 상속받았다면?
만약 이 객체가 다른 객체를 참조하고 있다면?
이런 경우는 객체의 상태를 저장하기 쉽지 않다.
예를 들어 회원 객체를 저장할 때 팀 객체를 참조하고 있다면?
회원 객체를 저장할 때 팀 객체도 함께 저장해야 한다.
단순히 회원 객체만 저장하면 참조하는 팀 객체를 잃어버릴 수 있다.
객체와 관계형 데이터베이스는 지향하는 목적이 서로 다르다.
이것을 객체와 관계형 데이터베이스의 패러다임 일치 문제라고 한다.
이러한 불일치를 개발자가 중간에서 직접 해결해야 한다.
이를 해결하는 시간에 너무 많은 시간과 코드를 소비하게 된다.
3. JPA로 ORM알아보기
ORM은 객체와 관계형 DB를 매핑한다고 했었다.
그리고 ORM 프레임워크는 패러다임 불일치 문제를 개발자 대신 해결해준다.
예를 들어 ORM 프레임워크를 사용하면 객체를 DB에 저장할 때 :
개발자는 INSERT SQL을 직접 작성하지 않는다.
객체를 마치 자바 컬렉션에 저장하듯이 ORM 프레임워크에 저장하면 된다.
그러면 ORM 프레임워크가 적절한 INSERT SQL을 생성해서 DB에 저장해준다.
개발자는 그냥 매핑 방법만 ORM 프레임워크에게 알려주기만 하면 된다.
4. JPA 정리
1. 생산성
JPA를 사용하면 다음 코드처럼 자바 컬렉션에 객체를 저장하듯이 JPA에게 저장할 객체를 전달한다.
jpa.persist(member); // 저장
Member member = jpa.find(memberId) // 조회
따라서 지루하고 반복적인 CRUD용 SQL을 개발자가 직접 작성하지 않아도 된다.
2. 유지보수
SQL을 직접 다루게 되면 엔티티에 필드를 하나만 추가해도 SQL결과를 매핑하기 위한 JDBC API코드를 모두 변경해야 했다.
하지만 JPA를 사용함으로써 대신 SQL을 작성하기 때문에 필드를 추가하거나 삭제해도 수정해야 할 코드가 줄어든다.
3. 패러다임의 불일치 해결
객체와 관계형 데이터베이스는 지향하는 목적이 서로 다르다.
이것을 객체와 관계형 데이터베이스의 패러다임 일치 문제라고 한다.
JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해준다.
'JPA' 카테고리의 다른 글
JPA TIL - 06 다양한 연관관계 매핑 (0) | 2024.04.16 |
---|---|
JPA TIL - 05 연관관계 매핑 기초 (0) | 2024.04.09 |
JPA TIL - 04 엔티티 매핑 (0) | 2024.04.02 |
JPA TIL - 03 영속성 관리 (0) | 2024.03.26 |
JPA TIL - 02 프로젝트 설정 및 엔티티 매니저 관리 (0) | 2024.03.25 |