JPA/JPA Principles
[JPA 프로그래밍 - 기본편] 01. JPA란? (SQL 중심적인 개발의 문제점)
송재근
2021. 6. 28. 18:44
반응형
※JPA 김영한님 강의 정리
애플리케이션을 만들 때 쓰이는 객체 지향 언어들(Java, Scala 등)과 주로 쓰이는 데이터베이스인 RDBMS..
지금 시대는 객체를 관계형 DB에 관리 형식이다
SQL 중심적인 개발의 문제점
무한 반복, 지루한 코드
CRUD
INSERT INTO …
UPDATE …
SELECT …
DELETE …
자바 객체를 SQL로 ...
SQL을 자바 객체로 ...
객체 CURD
public class Member {
private String memberId;
private String name;
.....
}
INSERT INTO MEMBER(MEMBER_ID, NAME) VALUES
SELECT MEMBER_ID, NAME FROM MEMBER M
UPDATE MEMBER SET …
객체 CURD - 필드 추가
SQL에 의존적인 개발을 피하기 어렵다
패러다임의 불일치 객체 vs 관계형 데이터베이스
‘객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.
여러 선택지가 있지만 가장 현실적인 대안은 관계형 데이터베이스이다.
개발자 ≒ SQL 매퍼
객체와 관계형 데이터베이스의 차이
1. 상속
2. 연관관계
3. 데이터 타입
4. 데이터 식별 방법
상속
Album 저장
객체 분해 -> INSERT INTO ITEM ... -> INSERT INTO ALBUM …
Album 조회
각각의 테이블에 따른 조인 SQL 작성... -> 각각의 객체 생성... -> 상상만 해도 복잡 -> 더 이상의 설명은 생략한다. -> 그래서 DB에 저장할 객체에는 상속 관계 안쓴다
자바 컬렉션에 저장하면?
list.add(album);
자바 컬렉션에서 조회하면?
Album album = list.get(albumId);
부모 타입으로 조회 후 다형성 활용
Item item = list.get(albumId);
연관관계
- 객체는 참조를 사용: member.getTeam()
- 테이블은 외래 키를 사용: JOIN ON M.TEAM_ID = T.TEAM_ID
객체를 테이블에 맞추어 모델링
class Member {
String id; //MEMBER_ID 컬럼 사용
Long teamId; //TEAM_ID FK 컬럼 사용 //**
String username;//USERNAME 컬럼 사용
}
class Team {
Long id; //TEAM_ID PK 사용
String name; //NAME 컬럼 사용
}
테이블에 맞춘 객체 저장
객체다운 모델링
class Member {
String id; //MEMBER_ID 컬럼 사용
Team team; //참조로 연관관계를 맺는다. //**
String username;//USERNAME 컬럼 사용
Team getTeam() {
return team;
}
}
class Team {
Long id; //TEAM_ID PK 사용
String name; //NAME 컬럼 사용
}
객체 모델링 저장
객체 모델링 조회
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
public Member find(String memberId) {
//SQL 실행 ...
Member member = new Member();
//데이터베이스에서 조회한 회원 관련 정보를 모두 입력
Team team = new Team();
//데이터베이스에서 조회한 팀 관련 정보를 모두 입력
//회원과 팀 관계 설정
member.setTeam(team); //**
return member;
}
객체 모델링, 자바 컬렉션에 관리
list.add(member);
Member member = list.get(memberId);
Team team = member.getTeam();
객체 그래프 탐색
- 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
처음 실행하는 SQL에 따라 탐색 범위 결정
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
member.getTeam(); //OK
member.getOrder(); //null
엔티티 신뢰 문제
class MemberService {
...
public void process() {
Member member = memberDAO.find(memberId);
member.getTeam(); //???
member.getOrder().getDelivery(); // ???
}
}
모든 객체를 미리 로딩할 수는 없다.
- 상황에 따라 동일한 회원 조회 메서드를 여러벌 생성
memberDAO.getMember(); //Member만 조회
memberDAO.getMemberWithTeam();//Member와 Team 조회
//Member,Order,Delivery
memberDAO.getMemberWithOrderWithDelivery();
계층형 아키텍처 진정한 의미의 계층 분할이 어렵다.
비교하기
String memberId = "100";
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);
member1 == member2; //다르다.
class MemberDAO {
public Member getMember(String memberId) {
String sql = "SELECT * FROM MEMBER WHERE MEMBER_ID = ?";
...
//JDBC API, SQL 실행
return new Member(...);
}
}
비교하기 - 자바 컬렉션에서 조회
String memberId = "100";
Member member1 = list.get(memberId);
Member member2 = list.get(memberId);
member1 == member2; //같다.
고민점
- 객체답게 모델링 할수록 매핑 작업만 늘어난다.
- 객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?
반응형