JPA
객체지향 쿼리 언어
JPA는 다양한 쿼리 방법을 지원한다. JPQL JPA criteria QueryDSL 네이티브 SQL JDBC 직접 사용, Mybatis, SpringJDBCTemplate 함께 사용 JPQL JPA를 사용하면 엔티티 객체를 중심으로 개발한다. 문제는 검색 쿼리이다. 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색한다. 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하다. 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다. JPQL이란? JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다. SQL과 문법이 유사하며, SELECT, FROM, WHERE, GROUP BY, HAVING JOIN을 지원한다. JPQL은 엔티..
값 타입
JPA의 테이터 타입 분류 엔티티 타입 - @Entity로 정의하는 객체 - 데이터가 변해도 식별자로 지속해서 추적 가능 값 타입 - int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체 - 식별자가 없고 값만 있으므로 변경 시 추적 불가 값 타입 분류 - 기본값 타입 생명주기를 엔티티에 의존 값 타입은 공유하면 안 됨 - 임베디드 타입 새로운 값 타입을 직접 정의할 수 있음 JPA는 임베디드 타입이라 함 주로 기본값 타입을 모아서 만들어서 복합 값 타입이라고도 함 int, String과 같은 값 타입 임베디드 타입 사용법 @Embeddable : 값 타입을 정의하는 곳에 표시 @Embedded : 값 타입을 사용하는 곳에 표시 기본 생성자 필수 임베디드 타입의 장점 ..
프록시, 즉시 로딩과 지연 로딩
Proxy - em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회한다. - em.find() : 데이터베이스를 통해서 실제 엔티티 객체를 조회한다. getReference를 호출하는 시점에는 쿼리가 나가지않고, 이 값이 실제로 사용되는 시점에 쿼리가 나가게 된다. 위의 코드를 해석해 보자면 em.getReFerence로 Member클래스를 상속받고 있는 프록시 객체를 생성하게 되고, 이 생성된 프록시객체는 findMember.getUsername()처럼 실제로 사용하는 요청이들어올때 영속성 콘텍스트로부터 초기화 요청을 보내게 된다. 영속성컨텍스트는 실제 Member엔티티를 생성하게 되고 프록시는 타깃으로 엔티티를 참조하게 된다. 하이버네이트가 강제로 만든 가짜 ..
고급 매핑
상속관계 매핑 관계형 데이터베이스는 상속 관계가 없다. 슈퍼 타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사하다 상속관계 매핑 : 객체의 상속과 구조와 DB의 슈퍼 타입 서브타입 관계를 매핑 슈퍼 타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법은 다음과 같다. 1. 각각 테이블로 변환 -> 조인 전략 2. 통합 테이블로 변환 -> 단일 테이블 전략 3. 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략 일반적으로 클래스에서 상속을 받은 객체들로 매핑을 하게 되면 하나의 테이블에 모든 컬럼이 생기게 된다. 여기서 부모 클래스에 아래의 코드와 같이 어노테이션을 추가하면 조인 전략으로 테이블을 설계할 수 있다. 조인 전략 위의 DB의 테이블을 보면 단일 테이블 전략 같은 경우 ITEM..
다양한 연관관계 매핑
연관관계 매핑 시 고려사항 - 다중성 - 단방향, 양방향 - 연관관계 주인 N : 1 위의 코드를 보면 @ManyToOne으로 N:1의 관계로 매핑되어있다. 즉 이 엔티티는 연관관계의 주인이자 TEAM_ID의 외래 키를 가지고 있는 엔티티이다. 그리고 그 반대로 @OneToMany로 서로 대칭으로 이루어져 있는데, 이 엔티티는 연관관계의 주인이 아니다. 따라서 mappedBy로 연관관계의 주인의 변수를 참조하고 이 엔티티는 읽기 전용이 된다. 1:1 관계 일대일 관계는 그 반대도 일대일 주 테이블이나 대상 테이블 중에 외래 키 선택 가능 - 주 테이블에 외래 키 - 대상 테이블에 외래 키 외래 키에 데이터베이스 유니크 제약조건 추가 위의 코드를 보면 OneToOne 관계인데 1:N 관계의 양방향 연관관계..
연관관계 매핑
연관관계가 필요한 이유? - 객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다. 객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다. -테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다. -객체는 참조를 사용해서 연관된 객체를 찾는다. -테이블과 객체 사이에는 이런 큰 간격이 있다. 단방향 연관관계 위의 연관관계와 같이 Member는 Teamid의 객체를 가지고 있다.(객체 참조) MEMBER 테이블은 TEAM_ID를 FK로 가지고 있다. (N:1) @Entity public class Member { @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; @Column(name = "US..
엔티티 매핑
객체와 테이블 매핑 : @Entity, @Table @Entity @Table(name = "MBR") public class Member { @Entity가 붙은 클래스는 JPA가 관리하는 엔티티이며, JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수이다. @Table은 엔티티와 매핑할 테이블을 지정하는 어노테이션이다 위의 코드와 같이 name을 지정할 수 있다. @Entity의 default name은 클래스명과 같다. 주의 -기본 생성자 필수(public, protected) -final클래스, enum, inteface, inner 클래스 사용 x 저장할 필드에 final 사용 x - 필드와 컬럼 매핑 : @Column - 기본 키 매핑 : @Id - 연관관계 매핑 : @ManyToO..
flush, 준영속 상태
플러시(flush)란? 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것이다. 데이터베이스 commit시점에서 플러시가 일어나게 된다. 즉 영속성컨텍스트와 데이터베이스를 맞추는 것이다. 플러시 발생 -변경 감지 -수정된 엔티티 쓰기 지연 sql저장소에 등록 영속성 컨텍스트를 플러시 하는 방법 em.flush(직접 호출) 트랜잭션 commit - 자동호출 jpql쿼리 실행 -자동호출 예를 들자면 아래 코드와 같다. Member member = new Member(20L, "member20"); em.persist(member); em.flush(); tx.commit(); 위의 코드와 같이 flush()를 호출하여 직접 쿼리를 보내고 commit을 하였다. 플러시는 영속성 콘텍스트를 비우는 것이 아니..