[JPA]객체와 데이터베이스 패러다임의 차이

Ceing·2024년 5월 2일

JPA

목록 보기
5/15
post-thumbnail

객체와 데이터베이스 패러다임의 차이

  1. 상속
  2. 연관관계
  3. 객체 그래프 탐색
  4. 객체 비교


1. 상속

  • 객체 : 상속 O , 객체의 상속 관계(부모 - 자식)

  • 데이터베이스 : 상속 X , 상속과 비슷한 외래 키 참조를 통한 테이블의 슈퍼 타입 - 서브 타입 관계

  • 이러한 객체와 데이터베이스 간 패러다임의 차이가 존재

  • 객체 세상에서 상속관계에서 자식 객체를 데이터베이스에 저장하려면 부모 객체와 매핑되는 슈퍼 타입 테이블 및 자식 객체와 매핑되는 서브 타입 테이블에 각각 INSERT 쿼리를 날려야됨

  • 조회할 때는 저장할 때보다 훨씬 복잡함 , 상속관계에서 자식 객체를 조회하고싶은 경우 슈퍼 타입 및 서브 타입 테이블에서 각각 JOIN 질의를 통해 자식 객체에 대한 데이터를 가져온 후 데이터를 합치는 작업까지 해야됨

  • 하지만 만약 자바 세상에서 저장소 역할을 하는 컬렉션에 저장 및 조회할 경우 매우 수월

  • 저장의 경우 단순히 add()만 하면 되고, 조회의 경우 단지 get(key)만 하면 됨 , 즉 메서드 한 줄로 가볍게 끝날 수 있게 됨



2. 연관관계

  • 객체 연관관게 : 참조 객체 사용

  • 테이블 연관관계 : 외래키 사용

  • 이렇게 객체와 테이블 연관관계 참조 방식도 다르다

  • 테이블에 맞춰서 객체 연관관계 모델링 시 객체지향적이지 않은 코드가 되기 때문에 참조를 사용한 객체지향 모델링을 해야함

class Member{
	private String nane;
    private Team team; //private Long teamId (x)
}
  • Member와 Team의 연관관계를 설정했다. 이렇게 Team의 id가 아닌 Team 객체를 통해 연관관계를 맺으니 객체지향적으로 올바른 코드가 될 수 있다.

  • 클라이언트 코드에서 member.getTeam()과 같은 식으로 매우 편리하게 연관관계에 해당되는 객체에 접근할 수 있기 때문!

  • 하지만 객체지향 모델링을 했을 때 데이터베이스 테이블에 저장 및 조회 작업은 매우 복잡

  • 저장 시 INSERT저장 쿼리를 연관관계에 해당되는 각각에게 날리는 것 뿐만 아니라 테이블 세계에선 연관관계를 외래 키를 씀에 따라 참조 객체 => 외래키로 변환해주는 작업이 필연적으로 필요함

  • 즉 INSERT INTO MEMBER VALUES(member.getTeam().getId() , ...)와 같은 지저분한 코드가 되게 됨

  • 조회할 때도 마찬가지로 저장과 같은 체인 형태로 id를 끄집어내서 조회해야됨

  • 하지만 연관관계 역시도 상속처럼 만약 자바 컬렉션에 저장 및 조회할 경우 add(member) , get(member.getId())와 같은 형태로 굉장히 편리하게 조회가 가능!



3. 객체 그래프 탐색

  • 객체 세계에선 객체 그래프 탐색이 가능해야됨

==> member.getTeam() , member.getOrder() , item.getOrderItem() , ...

  • 처음에 어떤 SQL을 DB에 보냈는지에 따라 반환되는 엔티티 객체가 다름
  • 예를 들어 select * from member m join team t on m.team_id = t.team_id;와 같은 형태로 쿼리를 날린 후 반환되는 Member 엔티티 객체는 member.getTeam()은 잘만 조회되지만 Member의 또다른 연관관계에 있는 Order 엔티티 객체는 조회가 되지 않게 됨(member.getOrder() // null 반환)

엔티티 신뢰 문제 발생

  • 각 계층형 아키텍처(컨트롤러 , 서비스 ,리포지토리)에선 하위 계층으로부터 넘어온 데이터를 믿고 쓸 수 있어야됨 하지만 객체 그래프 탐색 문제와 같이 내가 데이터를 반환하려 했는데 null이 나올 경우 넘어온 데이터로부터 신뢰가 떨어지는 문제가 발생하게됨

  • 그렇다고 모든 연관관계에 대한 엔티티 객체를 로딩하기에도 성능적으로 큰 이슈가 발생할 수 있음



4. 객체 비교

테이블 보관의 경우

Member member1 = memberRepository.getMember(memberId);
Member member2 = memberRepository.getMember(memberId);
member1 = member2 //false

객체 컬렉션 보관의 경우

Member member1 = memberRepository.getMember(memberId);
Member member2 = memberRepository.getMember(memberId);
member1 = member2 //true

이처럼 테이블에선 다른 인스턴스를 반환해주지만 객체 컬렉션은 같은 인스턴스를 반환

profile
이유에 대해 끊임없이 생각하고 고민하는 개발자

0개의 댓글