
1) JPA는 같은 트랜잭션안에서 수행된 건 == 비교를 모두 같은 객체로 가져오도록 함.
영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
-> 왜냐하면 영속성 컨텍스트에 엔티티가 있다는건 find가 호출되었다는 뜻이니까. 또는 프록시 초기화가 호출되었다는 이야기니까.
-> 따라서 그 반대도 성립함. em.find()해도 프록시가 반환될수있다. ==를 일치시키기 위해서
2) getReference는 기본적으로 프록시 객체를 반환하는데, 함수 호출시,(getXXX) 프록시 초기화가 발생함.
3) JPA에서는 Member를 조회할떄, 1개의 쿼리만 나갈지라도 JPQL에서는 Member를 조회할때 Team 쿼리가 따로 나간다 . 즉시로딩일떄! JPQL일때만임. 왜냐하면 쿼리로 변환되서 나가니까 SQL로 전달되는거니까
그래서 JPQL에서는 fetch join이라는게 있다.
4) Cascade는 단일 소유자일때만 써야함. 다른곳에서도 child를 쓰게되는 경우에는 쓰면 안됨. ALL이나 PERSIST 정도 사용함.
5) 임베디드타입은 임베디드타입을 내부 가질수 있다.
6) 임베디드타입은 내부에 엔티티를 가질 수있다.
7) 값 타입 컬렉션은 식별자가 따로 없기 때문에 별도의 테이블을 만들때 값타입의 모든 속성이 PK가 된다.
8) 값타입 컬렉션은 ElementCollection 애노테이션을 사용해서 DB와 맵핑함.
9) CollectionTable로 테이블이름 지정
10) joinColumns로 외래키 지정함
11) JPA에서는 직접 조회보다 getter를 사용하도록 해야함. 왜냐하면 프록시를 사용하는 경우가 있기 때문. 따라서 hahscode와 equal을 재정의할때도 getter를 사용해서 참조하도록 체크해줘야함.
n
12) JPQAL에서 가져온값들도 영속성 컨텍스트에 의해 관리된다.(엔티티 프로젝션들은 영속성 컨텍스트에 의해서 관리됨.)
13) query타입으로 조회하면 object[]로 캐스팅해서 사용함.
14) 프로젝션이 여러값일떄는 new 오퍼레이션을 사용하자.
15) 세타조인 := 막조인
16) JPQL에서 조인시 ON은 필터링 역할과 세터조인시 조인조건 역할을 수행함.
17) ENUM 타입을 표현할떄 하드코딩을 하는 경우에만 패키지명을 다써주고 그렇지 않고 파라미터바인딩하면 안써줘도 됨
18) 이미 하이버네이트는 함수를 이미 등록해놓음. 방언에 맞는 함수들을!!
사용자정의함수를등록하기 위헤서느느 H2Dialog 를 상속받아서 registerFunction으로 등록함.
19) 일대다 패치조인은 데이터가 뻥튀기된다.
20) 페치조인은 조인 대상에 별칭을 주면 안된다.
왜냐하면 페치조인은 조건 없이 관련된 객체를 모두 조회할 수 있어야하기 때문이다. 가능은 하지만 쓰면 안된다.
21) 컬렉션 패치 조인은 일대다인경우(팀->멤버)라서 데이터가 뻥튀기 되기 때문에 페이징 기능을 사용할 수 없다. 정합성이 맞지 않기 때문이다.왜냐하면 페이징은 DB중심적임. 그렇기 때문에 방향을 뒤집어서 패치 조인함. 다대일로! 또는 batchsize를 줘서 특정 개수만큼 미리 가져올수있도록 함. 이걸 글로벌 세팅으로 줄수도 있음.
22) 엔티티라는 값 자체가 JPQL에서 db로 넘어가게 되면 DB는 엔티티의 키값을 기준으로 쿼리를 생성한다.
23) 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리한다.
다만 여기서 말하는 문제점은 벌크연산을 수행하고나면 기존 영속성 컨텍스트의 값이 DB와 달라지는 문제를 말한다.
벌크 연산도 SQL을 수행하기 떄문에 벌크연산을 수행할때 flush 연산을 수행한 후에 벌크 연산을 수행한다. 하지만, 실제 영속성 컨텍스트값과 DB값은 다를 수 있다.
24) spring-boot-devtools 조사해보자.
25) @PersistenceContext 애노테이션이 있으면 EntityManager를 의존성 주입해줌. 근데 내기억엔 생략 가능함.
스프링부트의 JPA 라이브러리를 사용하면 @PersistenceContext대신 @Autowired로도 사용가능함. 그래서 생략이 가능한것!
26) 도메인과 밀접한 비지니스 로직은 도메인 객체안에 만들어주는게 좋다. 왜냐하면 가장 가까우니까!
27) 서비스가 아닌 대부분의 비지니스 로직이 도메인에 있는 형태를 도멩니 모델 패턴이라 함. 서비스에서 대부분 처리하는건 트랜잭션 스크립트 패턴이라함 도메인 모델 패턴은 서비스 계층에서 위임해서 처리함.
JPA에서는 도메인 모델 패턴이 주로 사용됨.
28) @Valid를 쓰면 Validation할수있음.
29) @PathVariable("itemId")
30) Merge
31) 앤티티에는 화면 validation을 위한 로직이 있으면 안됨.왜냐하면 앤티티는 매우 여러곳에서 사용하기 때문에 스펙이 바뀔수가 없음.
앤티티와 API 스펙은 1:1 매핑되어야함.
32) 다시 한번 말하지만 앤티티를 직접 외부에 노출하면 안된다.
33) 양방향 연관관계에서는 한쪽 방향을 JsonIgnore해줘야함. 안그러면 Json에서 무한루프빠짐..
34) 지연로딩에서는 Json에서 오류를 내뱉는다. 프록시라서 type 오류가남.
그래서 하이버네이트 관련 모듈을 다운로드해서 사용해야함.
근데 이 경우는 앤티티를 노출하는 경우임. 다시 말하지만 앤티티는 노출하지 말자.
35) n+1문제는 즉시로딩으로도 해결되지 않음. -> 왜냐하면 쿼리예측이 안되니까.
36)JPA에서 바로 DTO를 출력하려면 jpsq에서 new 연산자를 써야함.
new 연산자 사용시 앤티티를 생성자로 넣을순없어서 다 나열해줘야함.
근데 단점도 있어서 별로임. 이렇게 쓰려면 쿼리용 리포지토리를 따로 뽑아서 쓰는게 나음.
컬렉션 조회 최적화 시작!!
37) XXToMany를 성능 최적화를 위해서 패치조인하면 데이터가 뻥튀기 된다. 일대다조인이니까
JPA에 distinct는 키값만 같으면 중복을 제거해줌. 실제 데이터베이스에서는 쿼리가 중복이 아니더라도!! (완전 똑같지는 않더라도!)
38) jpql에서는 new 오퍼레이션에서 앤티티를 바로 집어넣을 수 없다.
그리고 컬렉션도 넣을 수 없다. 근데 컬렉션을 넣을 수 없는건 당연하다. sql에 리스트를 넣을 순 없으니까.
39) @Param이 필요한 경우는 Spring Data JPA에서 NamedQuery를 수행할때, JPQL에 파라미터가 필요한 경우임.
네임드쿼리도 규칙이 있다. 먼저 네임드쿼리를 찾고, 그다음에 없으면 ByXXX에 의해서 쿼리를 만들어서 수행함. 그래서 네임드쿼리가 먼저 우선순위이긴함.
네임드쿼리는 실무에서 잘안씀. 근데 장점이 한개있는데, 이건 문자가 아니라 컴파일시간에 에러 체크가 가능함.
40) 스프링 데이터 JPA에서 패치조인을 사용하려면 @QUery를 적어서 해야할까? 그렇지 않다. 그래서 나온게 EntityGraph 애노테이션임 근데 left outer join이 나가는데 패치조인은 일반적으로 left outer join을 사용함.
41) prepersistence
persist 되기전에 발생하는 이벤트에 대한 어노테이션
42) preupdate도 존재함.
43) MappedSuperclass 는 속성값만 공유하는것. 진짜 JPA의 상속관계는 아님.