객체 : 상속 O , 객체의 상속 관계(부모 - 자식)
데이터베이스 : 상속 X , 상속과 비슷한 외래 키 참조를 통한 테이블의 슈퍼 타입 - 서브 타입 관계
이러한 객체와 데이터베이스 간 패러다임의 차이가 존재
객체 세상에서 상속관계에서 자식 객체를 데이터베이스에 저장하려면 부모 객체와 매핑되는 슈퍼 타입 테이블 및 자식 객체와 매핑되는 서브 타입 테이블에 각각 INSERT 쿼리를 날려야됨
조회할 때는 저장할 때보다 훨씬 복잡함 , 상속관계에서 자식 객체를 조회하고싶은 경우 슈퍼 타입 및 서브 타입 테이블에서 각각 JOIN 질의를 통해 자식 객체에 대한 데이터를 가져온 후 데이터를 합치는 작업까지 해야됨
하지만 만약 자바 세상에서 저장소 역할을 하는 컬렉션에 저장 및 조회할 경우 매우 수월
저장의 경우 단순히 add()만 하면 되고, 조회의 경우 단지 get(key)만 하면 됨 , 즉 메서드 한 줄로 가볍게 끝날 수 있게 됨
객체 연관관게 : 참조 객체 사용
테이블 연관관계 : 외래키 사용
이렇게 객체와 테이블 연관관계 참조 방식도 다르다
테이블에 맞춰서 객체 연관관계 모델링 시 객체지향적이지 않은 코드가 되기 때문에 참조를 사용한 객체지향 모델링을 해야함
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())와 같은 형태로 굉장히 편리하게 조회가 가능!
==> member.getTeam() , member.getOrder() , item.getOrderItem() , ...
각 계층형 아키텍처(컨트롤러 , 서비스 ,리포지토리)에선 하위 계층으로부터 넘어온 데이터를 믿고 쓸 수 있어야됨 하지만 객체 그래프 탐색 문제와 같이 내가 데이터를 반환하려 했는데 null이 나올 경우 넘어온 데이터로부터 신뢰가 떨어지는 문제가 발생하게됨
그렇다고 모든 연관관계에 대한 엔티티 객체를 로딩하기에도 성능적으로 큰 이슈가 발생할 수 있음
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
이처럼 테이블에선 다른 인스턴스를 반환해주지만 객체 컬렉션은 같은 인스턴스를 반환