즉, 객체답게 모델링 할수록 매핑 작업만 늘어난다.
객체를 자바 컬렉션에 저장하고 불러오듯(ex list.get)이 DB에 저장할 수는 없을까?
이 고민의 결과가 바로 JPA(Java Persistence API) 이다.
https://gmlwjd9405.github.io/2019/08/03/reason-why-use-jpa.html
애플리케이션의 데이터를 객체지향 관점으로 바라보고 다룰 수 있게 해주는
자바 진영의 ORM 기술표준인 객체지향 기술
jpa.persist(member)
Member member = jpa.find(memberId)
member.setName(“변경할 이름”)
jpa.remove(member)
중요한 것은 JPA가 SQL을 자동으로 생성해 준다는 것과, 패러다임 불일치를 해결해 준다는 것!
저장
-개발자가 할일
jpa.persist(album);
-나머진 JPA가 처리
INSERT INTO ITEM ...
INSERT INTO ALBUM ...
조회
-개발자가 할일
Album album = jpa.find(Album.class, albumId);
-나머진 JPA가 처리
SELECT I.*, A.*
FROM ITEM I
JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
// 연관관계 저장
member.setTeam(team);
jpa.persist(member);
// 객체 그래프 탐색
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
-> 마치 객체를 자바 컬렉션에 저장하고 불러오듯(ex list.get)이 DB에 저장, 조회함
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId); // SQL
Member member2 = jpa.find(Member.class, memberId); // 캐시
member1 == member2; // 같다.
-> 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장 (약간의 조회 성능 향상)
바로 위 코드처럼 같은 트랜잭션 안에서는 같은 엔티티를 반환하여 약간의 조회 성능 향상
(transactional write-behind)
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit(); // [트랜잭션] 커밋
만약 persist를 따로 보낸다면 3번의 네트워크를 타기 때문에 효율적이지 않다.
하지만 JPA는 JDBC BATCH SQL 기능으로 한번에 보내기 때문에 효율적이다.
(Lazy Loading)
객체가 실제 사용될 때 로딩
JOIN SQL로 한번에 연관된 객체까지 미리 조회
옵션에 따라 지연로딩을 할지 즉시 로딩을 할지 정할 수 있음
예를 들어, 멤버와 팀을 같이 많이 사용하는 경우에는 즉시 로딩이 유리하고 팀을 가끔 사용하는 경우에는 지연 로딩이 유리함
강사님은 개발할 때는 다 지연 로딩으로 하고 나중에 최적화 할 때 필요한 경우에만 즉시 로딩을 사용한다고 함
JPA는 특정 데이터베이스에 종속되지 않는다.
하이버네이트는 40가지 이상의 데이터베이스 방언 지원