애플리케이션은 주로 객체 지향 언어로 개발 - Java, Scala, ...
객체(데이터)는 주로 관계형 DB에 보관 - Oracle, MySQL, ...
→ 지금 시대는 객체를 관계형 DB에 관리한다!
→ 즉, SQL에 의존적인 개발을 피하기 어렵다!
- SQL 중심적인 개발의 문제점
- 수많은 객체 CRUD, 수많은 SQL 작성
- INSERT INTO …
- SELECT …
- UPDATE …
- DELETE …
- 자바 객체를 SQL로... SQL을 자바 객체로...
- 객체에 필드 추가라도 하게되면..?
→ 무한 반복, 지루한 코드
- ‘객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.’
- 객체(Object)를 영구 보관하는 다양한 저장소(RDB, NoSQL, File, ...) 중, 현실적인 대안은 관계형 데이터베이스(RDB)
- 객체를 SQL로 변환하여, 관계형 데이터베이스(RDB)에 저장
- 객체와 관계형 데이터베이스(RDB)의 차이
- 상속
- 연관관계
- 데이터 타입
- 데이터 식별 방법
1. 상속
- Album 저장
- 객체 분해
- INSERT INTO ITEM ...
- INSERT INTO ALBUM …
- Album 조회
- 각각의 테이블에 따른 조인 SQL 작성...
- 각각의 객체 생성..
- .....(상상만 해도 복잡).....
→그래서 DB에 저장할 객체에는 상속 관계 안쓴다.
- Album을 자바 컬렉션에 저장하면?
- list.add(album);
- Album을 자바 컬렉션에서 조회하면?
- Album album = list.get(albumId);
- 부모 타입으로 조회 후, 다형성 활용
- Item item = list.get(albumId);
2. 연관관계
- 객체는 참조를 사용
- 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 컬럼 사용
}
→ 테이블에 맞춘 객체 저장
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES …
- 객체다운 모델링
class Member {
String id; //MEMBER_ID 컬럼 사용
Team team; /** 참조로 연관관계를 맺는다 */
String username;//USERNAME 컬럼 사용
Team getTeam() {
return team;
}
}
- 객체 모델링 저장
- member에서 team을 조회해서, 그 team의 id(PK)가져옴
- 객체 모델링 조회
//member와 team을 join해서 한번에 가져온다.
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;
}
- 객체 모델링, 자바 컬렉션에 관리한다고 생각해보면?
//member 저장
list.add(member);
//member 조회
Member member = list.get(memberId);
//member의 team 조회
Team team = member.getTeam();
3. 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
- 처음 실행하는 SQL에 따라 탐색 범위 결정
- member.getTeam(); //OK
- member.getOrder(); //null
→ 엔티티 신뢰 문제가 생긴다.
class MemberService {
...
public void process() {
Member member = memberDAO.find(memberId);
member.getTeam(); //???
member.getOrder().getDelivery(); // ???
}
}
→ 그렇다고 모든 객체를 미리 로딩할 수는 없다.
/** 상황에 따라 동일한 회원 조회 메서드를 여러개 생성하면.. SQL이 너무 많이 생성된다 */
memberDAO.getMember(); //Member만 조회
memberDAO.getMemberWithTeam();//Member와 Team 조회
//Member,Order,Delivery
memberDAO.getMemberWithOrderWithDelivery();
→ 즉, 진정한 의미의 계층 분할이 어렵다. (계층형 아키텍처)
4. 비교하기
String memberId = "100";
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);
member1 == member2; //두 인스턴스는 당연히 다르다!
//데이터는 같지만, 실제 인스턴스는 다름
→ 자바 컬렉션에서 조회해보면?
String memberId = "100";
Member member1 = list.get(memberId);
Member member2 = list.get(memberId);
member1 == member2; //같다.
→ 즉, 객체답게 모델링 할수록 매핑 작업만 늘어난다. ( 개발자 ≒ SQL 매퍼 )
- 객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?
- JPA (Java Persistence API)
[자바 ORM 표준 JPA 프로그래밍 -2] ORM 기술, JPA (tistory.com)
728x90
반응형
'JPA Tutorial' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍 3] Hello JPA - 프로젝트 생성 (0) | 2023.09.13 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 2] ORM 기술, JPA (0) | 2023.09.12 |
[자바 ORM 표준 JPA 프로그래밍 0] JPA 공부 목표 (0) | 2023.09.09 |
[스프링 부트와 JPA 활용 2] 도메인 분석: 도메인 모델과 테이블 설계 (1) | 2023.09.07 |
[스프링 부트와 JPA 활용 1] JPA와 DB 설정 (0) | 2023.09.06 |