// SQL
// SELECT MEMBER_ID, NAME FROM MEMBER M WHERE MEMBER_ID = ?
// JDBC API 사용
ResultSet rs = stmt.executeQuery(sql);
// 조회 결과 매핑
String memberId = rs.getString("MEMBER_ID");
String name = rs.getString("NAME");
Member member = new Member();
//getter && setter.....
// 반복, 반복, 반복.......
ex) 컬럼 추가 -> CRUD 코드 변경
// 저장
jpa.persist(member);
// 검색
String memberId = "member1";
Member member = jpa.find(Member.class, memberId);
// 수정
Member member = jpa.find(Member.class, memberId);
member.setName("new name");
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
객체와 관계형 데이터베이스는 지향하는 목적도 다르고, 표현하는 방법도 다르며, 이런 문제는 개발자가 중간에서 해결해야 한다.
abstract class Item {
Long id;
String name;
int price;
}
class Album extends Item {
String artist;
}
class Movie extends Item {
String director;
String actor;
}
class Book extends Item {
String author;
String isbn;
}
DTYPE
이라는 필드 역시 추가해야 한다.INSERT INTO ITEM ...
INSERT INTO ALBUM ...
// persist() 메소드를 사용하여 객체 저장
jpa.persist(album);
// JPA는 객체를 ITEM, ALBUM 두 테이블에 나누어 저장
INSERT INTO ITEM ...
INSERT INTO ALBUM ...
// find() 메소드를 사용하여 객체 조회
String albumId = "id100";
Album album = jpa.find(Album.class, albumId);
// ITEM, ALBUM 두 테이블을 조인해서 필요한 데이터를 조회, 반환
SELECT I.*, A.*
FROM ITEM I
JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
// java
class Member {
String id; // MEMBER_ID
Long teamId; // TEAM_ID (FK) -> 객체에서는 참조가 불가능
String username; // USERNAME
}
class Team {
Long id; // TEAM_ID (PK)
String name; // NAME
}
// java
class Member {
String id; // MEMBER_ID
Team team; // 참조로 연관관계를 맺는다.
String username; // USERNAME
Team getTeam() {
return team;
}
}
class Team {
Long id; // TEAM_ID (PK)
String name; // NAME
}
// 저장
member.getId(); // MEMBER_ID (PK)
member.getTeam().getId(); // TEAM_ID (FK)
member.getUsername(); // USERNAME
// 조회
public Member find (String memberId) {
// SQL 실행...
...
Member member = new Member();
... // DB에서 조회한 회원 관련 정보 입력
Team team = new Team();
...
member.setTeam(team);
... // 팀 관련 정보 입력
member.setTeam(team); // 회원과 팀 관계설정
return member;
}
// team의 참조를 외래 키로 변환해서 적절한 INSERT를 실행
member.setTeam(team); // 회원과 팀 연관관계 설정
jpa.persist(member); // 회원과 연관관계를 함께 저장
// 조회 역시 외래키를 참조로 변환해준다.
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
// member.getOrder(); => NULL
memberDAO.getMember(); // Member 조회
memberDAO.getMemberWithTeam(); // Member, Team 조회
memberDAO.getMemberWithOrderWithDelivery(); // Member, Order, Delivery 조회
실제 객체를 사용하는 시점까지 데이터베이스 조회를 미룬다(지연로딩)
// 처음 조회 점에서 SELECT MEMBER
Member member = jpa.find(Member.class, memberId);
Order order = member.getOrder();
order.getOrderDate(); // Order를 사용하는 시점에 SELECT ORDER
Member와 Order를 항상 함께 사용하면, 동시에 조회하는 것이 효과적이다.
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);
// member1 == member2???
// 새로운 인스턴스를 생성해서 반환하기 때문에, 동일성 비교는 안된다.
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2
Member member1 = jpa.find(memberId);
Member member2 = jap.find(memberId);
같은 트랜잭션 안에서 같은 회원을 조회하면, 처음만 SQL을 전달하고, 두번째는 조회한 회원 객체를 재사용한다.