4 min to read
자바 ORM 표준 JPA 프로그래밍
1. JPA 소개
- JPA는 관계형 db와 객체형 모델링 간의 간극을 해결해주는 중간다리 역할의 ORM(Object Relational Mapping) 프레임워크. → 패러다임의 불일치를 보완해줌
- 이점
- CRUD SQL을 작성할 필요가 없음.
- 조회된 결과에 대한 객체 매핑도 자동으로 처리해줌으로써 데이터 저장 계층의 코드가 줄음.
- 네이티브 SQL이나 데이터베이스 쿼리 힌트를 사용함으로써 성능 문제도 해결할 수 있음.
- SQL이 아닌 객체 중심으로 개발함으로써 유지보수 및 생산성이 좋아졌고 테스트 작성도 간편해짐.
- 별다른 코드 수정 없이 데이터베이스 교체가 가능.
1.1 SQL을 직접 다룰 때의 단점
- 작성해야 할 코드의 양이 많음.
String selectSql = "SELECT MEMBER_ID, NAME FROM MEMBER M WHERE MEMBER_ID = ?" ResultSet rs = stmt.executeQuery(readSql); String memberId = rs.getString("MEMBER_ID"); String name = rs.getString("NAME"); Member member = new Member(); member.setMemberId(memberId); member.setName(name); ... String insertSql = "INSERT INTO MEMBER(MEMBER_ID, NAME) VALUES(?, ?);" pstmt.setString(1, member.getMemberId()); pstmt.setString(2, member.getName()); pstmt.executeUpdate(insertSql);
- 테이블의 필드가 추가될 때 마다 작성한 모든 CRUD 처리 코드도 수정돼야 함.
- 진정한 의미의 계층 분할이 어려움.
- 유지보수 과정에서 DAO를 열어보고 SQL을 일일이 직접 확인해봐야 함.
- 이런식으로 SQL에 의존하게 되면서 엔티티를 신뢰할 수 없음.
- 때문에 객체 관점이 아닌 SQL에 의존적으로 개발될 수 밖에 없음.
1.1.3 JPA를 통한 문제 해결
-
저장 기능
jpa.persist(member);
-
조회 기능
String memberId = "helloId"; Member member = jpa.find(Member.class, memberId);
-
수정 기능
Member member = jpa.find(Member.class, memberId); member.setName("jaedooLee");
-
연관된 객체 조회
Member member = jpa.find(Member.class, memberId); Team team = member.getTeam();
1.2 패러다임의 불일치
- 관계형 데이터베이스는 데이터 중심, 객체지향적 개념이 존재하지 않음.
- 관계형 데이터베이스와 객체가 서로 갖는 목적이 다르기 때문에 객체 구조를 테이블 구조에 저장하는데 한계가 있음.
- 객체지향 ↔ 관계형 데이터베이스 사이의 패러다임 불일치 문제를 해결하는데 많은 시간과 코드가 사용됨.
- 이를 JPA로 해결
1.2.1 상속
- 객체의 상속 → db 모델링의 슈퍼/서브 타입 관계
1.2.2 연관관계
- 객체는 참조를 통해 다른 객체와 연관관계를 맺고 참조 객체에 접근하여 연관 관계인 객체를 조회 → 테이블은 외래 키를 사용하여 다른 테이블과 연관관계를 맺고 조인을 사용하여 연관된 테이블을 조회함.
- 객체도 테이블 처럼 외래 키 필드를 직접 저장하면 안되고 참조 객체를 필드로 추가해야 함.
- 본 객체를 통해 참조 객체를 조회할 수 없게 됨. → 객체지향의 특징을 잃어버림.
class Member {
String id;
Team team; // 외래 키 그대로가 아닌 Team 객체 참조를 통해 연관관계를 맺음.
String userName;
Team getTeam() {
return team;
}
}
class Team {
Long id; // TEAM_ID PK
String name;
}
- JPA 활용 없이 연관관계를 적용하려면 → Member 객체는 team 필드로 연관관계를 맺고, MEMBER 테이블은 TEAM_ID 외래 키로 연관관계를 맺는 차이를 개발자가 중간에서 일일이 변환처리를 해줘야 함.
- JPA 활용한다면
member.setTeam(team); // 회원과 팀 연관관계 설정 jpa.persist(member); // 회원과 연관관계 함께 저장.
→ 개발자는 member와 team 관계만 설정해주고 위 코드 처럼 member 객체를 저장하게 되면 JPA가 알아서 team의 참조를 외래 키로 변환하여 적절한 INSERT SQL을 데이터베이스에 전달함.
1.2.3 객체 그래프 탐색
- 언제 끊어질지 모를 객체 그래프에서 조회 시도 시, JPA를 사용하면 지연 로딩 기술을 통해 실제 사용되는 정보가 조회되는 경우에만 해당 객체를 조인하여 데이터베이스에서 조회가 됨.
1.2.4 비교
- 데이터베이스는 각 row의 id 값으로 비교.
- but, 객체는 동일성(==)비교와 동등성(equals()) 두 가지 비교 방식이 있음.
- 동일성 : 주소 값 비교
- 동등성 : 실제 내부 값 비교
- JPA 활용 없이 같은 객체를 두 번 조회하여 반환된 두 객체를 비교하게 되면 동일성 비교에서 false가 반환됨.
- 값은 같더라도 별도의 새로운 객체에 저장된 객체들이기 때문에 주소값이 다를 수 밖에 없음.
- JPA를 활용하면 이러한 경우의 동일성 비교를 보장해줌.(같은 트랜잭션 인 경우)
1.3 JPA란 무엇인가?
- 객체와 테이블 간의 매핑을 통해 패러다임 불일치 문제를 해결해주는 ORM 프레임워크.
- JPA를 사용해야 하는 이유
- 생산성
- 지루하고 반복적인 코드 개발 타파
- 유지보수
- 패러다임의 불일치 해결
- 성능
- 같은 객체를 두번 조회 시, sql은 한번만 데이터베이스에 전달되고 두번째는 조회했던 객체를 재사용함. → 불필요한 데이터베이스 접근이 줄어듦.
- 데이터 접근 추상화와 벤더 독립성
- 생산성
Comments