JPA_Spring-Data-JPA_QueryDSL

기존 객체지향과 RDBM

  1. SQL에 의존적인 개발 : 기존 Mybatis, JDBC API를 사용할때에는 물론 반복되는 매핑코드를 많이 줄여주긴했지만 SQL작성이 필연적이고 반복코드역시 존재했다. 즉 비슷한 CRUD쿼리를 반복해서 작성해야 하고 그 과정에서 실수가 나도 쉽사리 알아채기 어렵다(특히 쿼리내 오타). 또한 기존 테이블의 내용이 변경되면 수많은 코드와 쿼리들을 일괄적으로 바꾸어주어야 하기에 노력이 많이 들어가게 된다. 즉 SQL에 의존적인 개발을 하게 되어 버린다.
  2. 패러다임의 불일치 : 객체지향의 패러다임은 객체의 필드와 메서드를 클래스로 만드는 캡슐화를 통해 정보은닉과 각 객체간의 결합도를 낮추고 응집력을 높이는 것이 목표라고 한다면 관계형 DB는 각테이블로 정규화를 시켜 반복을 줄여 효율적인 데이터관리를 목표로 하기 때문에 둘의 패러다임은 어긋날수 밖에 없다.
  • 객체와 데이터베이스의 대표적 차이
    1. 상속 : 객체지향에서의 상속은 DB에 비슷한것이 있지만 없다고 보는것이 맞다
    2. 연관관계 : 객체지향은 '참조'를 통해, DB는 pk,fk를 통해 연관관계를 구현한다. 기존 Mybatis, JDBC API는 조인된 데이터를 조회시에 가져온값에서 각 엔티티에 맞는 값을 일일히 할당해줘야하는 수고스러움이 있었다.=> 생산성 저하.(물론 mybatis는 map기능이 따로 있긴했다.)
    3. 데이터 타입
    4. 데이터 식별 방법등
  1. 계층신뢰문제
  • 만약 Order와 Team이라는 클래스를 참조하고 있는 Member클래스를 MemberService 비즈니스내에서 MemberDAO의 find시 Team과 Order를 과연 마음대로 사용할수 있나? 아니다. 우리는 MemberDAO의 find 쿼리를 까보지 않는이상 모른다. 만약 find쿼리가 Team과 member테이블을 조인한 쿼리라면 order는 null상태일 것이고 원하는 정보를 알수가 없다. 물론 각 기능 마다 알맞는 쿼리를 나눠놓고 사용하면 되지 않냐라는 생각도 할수 있지만 그렇게되면 생산성, 재사용성 모두 떨어진다. 하나의 기능을 위해 비슷한 쿼리를 여러개 만들어 놓는다? 음...? 스프링은 계층구조이다. 각계층은 연관계층을 신뢰하고 신뢰 되야한다.
  1. DAO로 조회한 member1과 member2가 같음을 보장할수 있을까? 할 수 없다. 싱글톤으로 구현했다면 가능하겠지만 대부분 그렇지 않을 것이다. 결국 member1 == member2는 같음을 보장할수 없다. 이외에도 크고작은 문제들이 있다

왜 ORM 즉 JPA를 사용해야하나?

JPA의 사상은 DB데이터를 자바 컬렉션에 데이터를 넣다 뺏다하는 것처럼 사용하기 위함이다

  1. 생산성 : 밑은 영속성 컨택스트를 예시로 들었지만 Spring Data JPA 역시 미리 구성되어있다. * 저장: jpa.persist(member) * 조회: Member member = jpa.find(memberId) * 수정: member.setName(“변경할 이름”) 수정은 내용만 바꿔주면 구지 적용하지 않아도 트랜잭션이 끝나는 시점에 DB에 update쿼리가 적용이 된다. * 삭제: jpa.remove(member)
  2. 유지보수 * 기존 : 필드 변경시 모든 SQL이 수정되어야 했다 * JPA : 필드 변경시 JPA가 알아서 SQL을 만들기 때문에 필드만 추가해 주면 된다. * 또한 RDBM의 종류에 관계없이 사용가능하고 중간에 DB를 변경한다고 해도 바꿔줄 포인트가 많지 않다 기존 SQL을 직접 사용했을땐 해당 DB에 알맞는 SQL로 다시 바꿔줘야 했다....
  3. JPA와 패러다임 불일치 해결 * JPA와 상속 : DB의 계층구조는 객체지향의 상속과 비슷하지만 하위 테이블의 데이터를 사용하기 위해선 복잡한 쿼리들을 만들어 생성해야했지만 JPA는 형식에 맞게 구성하면 알아서 쿼리를 날려준다. * 연관관계 : 연관관계 조회시 바로 알맞게 할당된 즉 연관된 pk에 맞는 데이터를 객체로 가져올 수 있다. Member member = jpa.find(Member.class,memberId); Team team = member.getTeam(); 위처럼 Team을 바로 가져올수 있다. * 신뢰할 수 있는 엔티티, 계층
    • jpa를 활용하여 가져온 엔티티는 따로 쿼리를 정의한것이 아니라면 데이터 자체를 가져와주기 때문에 참조 객체들을 신뢰할 수 있다.(정확힌 지연로딩을 통해 해당 객체에 접근하는 순간 쿼리로 알맞는 객체를 가져오게됨.) 4) JPA와 비교,성능
    • JPA에서 가져오는 Member는 동일한 트랜잭션내에선 영속성 컨택스트의 1차캐시에 존재하는 내용으로 왔다갔다 하기 때문에 같음을 보장해준다.
    • 또한 DB 데이터 자체를 캐시기능을 사용해서 관리하기 때문에 성능측면에서 효율적이다

JPA의 단점

  • JPA는 통계처리와 같은 복잡한 쿼리보다는 실시간 실용적으로 사용되는 쿼리에 특화되어있다. 복잡한 쿼리를 자주 사용해야 할 시에는 Mybatis같은 SQL mapper를 사용하는게 효율적이라고 한다.