김영한 강사님의 해당 강의를 통해 해당 글을 작성하였습니다.
지나치게 많고 반복적인 SQL 코드는 개발자에게 하나의 시련이였다.
왜일까?
그 때마다 우리는 SQL을 수정해주어야 할 것이다.
만약 그 쿼리가 길고 무수하다면 일일히 수정하는 일은 비효율적일 것이다...
관계형 DB는 데이터를 잘 정규화해서 보관하는 것이 목표
객체는 속성과 기능이 잘 묶여서 캡슐화하는 것이 목표
이 둘의 패러다임이 안 맞는데 객체를 관계형 DB에 넣으려고 하니까 문제가 되는 것이다
생각해보자 우리 객체를 영구 보관하는 곳에는 다양한 저장소가 있다.
RDB(관계형 DB), NoSQL , File, OODB(지금은 잘 안 쓴다)
관계형 DB에 넣는 것이 제일 좋다.
(현실적으로 File에 넣으면 검색이 x)
Q. 상속
객체 (ㅇ), RDB(ㅇ 객체랑은 유사하지 x)
Q. 연관관계 *
객체: 참조 , RDB: PK-FK로 조인해서 찾아냄
이의 경우 Album에서
중간 매핑과정이 너무 복잡한 것이 문제가 된다.
좀 더 문제가 단순해진다. 직접 가져와서 일일히 매핑해줄 때와 다르게
테이블은 PK,FK 덕에 조인을 이용해서 양방향으로 접근이 가능한데, 객체는 단방향 밖에 접근이 안됨.
여기서 드는 생각은 DB의 외래키는... 객체지향적으로 보면 '참조'로 연관관계를 맺어야 한다는 생각이 든다.
[저장의 경우]
외래키 값 대신 참조가 있네? 그렇다면 값(외래키 값=> teamId)을 뽑아오면 된다.
[조회의 경우]
참 길고 복잡해진다..
코드 한 줄로 되니까 너무 편하다.. 근데 DB에 넣게 되면 이런 것들이 전부 헝클어지니 문제가 된다...
곧 엔티티의 신뢰 문제가 발생한다.
왜냐하면 이전에 select 가 어떤 쿼리가 날라갔고 왔는지를 일일히 확인할 수 없어서
이 코드를 직접 눈으로 보지 않는 이상 신뢰가 없다...
물리적으로 나뉘어져 있지만 논리적으로는 연관이 있어서...
결국 이 대안으로 상황에 따라 여러벌의 메서드를 생성해주는 식이 있다...😥
결과적으로 코드가 번잡해진다..
왜 다를까?
SQL문으로 일일히 생성해서 new로 반환을 해주다 보면 참조하는 곳이 달라진다.
레퍼런스 곧 참조 값이 같으니까 둘이 같다.
정리
해답은 JPA!
• 저장: jpa.persist(member)
• 조회: Member member = jpa.find(memberId)
• 수정: member.setName(“변경할 이름”)
• 삭제: jpa.remove(member)
되게 명령어가 단순해졌고 편리해졌다.
그냥 필드만 추가해주면 된다.
나머지 SQL은 JPA가 알아서 생성해줄 것이기 때문이다.
같은 트랜잭션 내에서 이전에 같은 엔티티를 다시 한 번 조회한다면 SQL문을 다시 쓰는게 아니라 캐시를 이용해서 반환한다. => SQL 1번만 씀
- 트랜잭션을 커밋할 때까지 SQL을 모음 (INSERT)
- JDBC BATCH SQL 기능을 사용해 한번에 모아서 SQL 전송
• 지연 로딩: 객체가 실제 사용될 때 로딩
• 즉시 로딩: JOIN SQL로 한번에 연관된 객체까지 미리 조회
즉시로딩의 경우 가져올 때 매번 같이 가져온다면 차라리 한 번에 미리 조회할 때 쓰인다.