Member 엔티티의 @NotEmpty는 화면에서 필요한 프레젠테이션 계층.
프레젠테이션 계층 위한 검증 로직이 entity에 다 들어가있음.
-> 화면 validation 로직이 들어간 것.
api마다 필요 할수도 필요 없을 수도 있음.
entity 스펙을 name에서 userName으로 바꾼다면?
ㄴ api 스펙자체가 바뀌어 버림. api 동작 안함.
-> 문제는 엔티티를 손대서 api 스펙 자체가 변해버린 것.
엔티티는 여러곳에서 쓰임.
엔티티 바꿨다고 해서 엔티티 스펙 바뀌면 안됨.
지금은 엔티티랑 api 스펙이 1:1 매핑되어 있음.
-> API 스펙을 위한 별도의 DTO 만들어야 함.
-> api 만들 때 entity 파라미터로 받지 말자 !
엔티티 외부 노출도 X.
수정시에는 가급적이면 변경 감지 쓰기
templates - application.yaml
jpa:
hibernate:
ddl-auto: none # create: 앱 실행시 엔티티 다 지우고 다시 생성, none: drop하지 않고 게속 사용
@GetMapping("/api/v2/members")
public Result membersV2() { // 응답값 껍데기 클래스 Result
List<Member> findMembers = memberService.findMembers(); // 가져와서 memberDto로 변환
// 멤버 엔티티에서 이름 꺼내와서 dto로 넣고 변환
List<MemberDto> collect = findMembers.stream()
.map(m -> new MemberDto(m.getName()))
.collect(Collectors.toList());// 리스트로 변환
// -> list Member를 list MemberDto로 변환
return new Result(collect);
// return new Result(collect.size(), collect); // count 넣는 경우
}
@Data
@AllArgsConstructor
// 오브젝트 타입으로 반환하기 때문에 Result라는 껍데기 씌워 줌.
// 이런식으로 한번 감싸줘야 한다. 리스트를 바로 내면 json 배열 타입으로 나가버리기 때문에 유연성 떨어짐.
static class Result<T> { // 제네릭
// private int count; // 이런식으로 바로 넣으면 됨.
private T data;
}
엔티티 절대 외부에 직접 반환하지 말자 !!
항상 다 DTO로 바꾸자.
성능 문제 대부분 조회에서 발생.
지연 로딩 (lazy)
아직 db에서 조회한게 아님.
lazy loading 갯수만큼 쿼리 반복해서 나감 - 성능 문제
fetch join
실무에서 매우 자주 씀. 꼭 알아두기!!
쿼리 하나만 길게 나감.
쿼리 방식 선택 권장 순서
앞에서의 조회는 xToOne 관계. fetch join으로 최적화 할 수 있었음.
하지만 컬렉션 조회(일대다 조회)의 경우 fetch join 시 페이징 불가.
컬렉션 fetch join 시 일대다 조인이 발생하므로 데이터가 예측할 수 없이 증가한다.
일대다에서 1을 기준으로 페이징 하는것이 목적인데, 데이터는 다(N)를 기준으로 row가 생성됨.
ToOne관계(OneToOne, ManyToOne) 관계는 모두 fetch join. ToOne관계는 row 수 증가시키지 않으므로 페이징 쿼리에 영향 주지 않음.
컬렉션은 지연 로딩으로 조회 (default_batch_fetch_size로 최적화 하자)
default_batch_fetch_size
memberRepository.find(), save() 등등 typeorm처럼 다 제공해줌.
findByName 같은 경우에도 이름 보고 알아서 만들어줌.
select m from member m where m.name = ? (jpql)
public interface MemberRepository extends JpaRepository<Member, Long> {
// 이렇게만 하면 끝!!
// 스프링 data jpa 가 알아서 다 만들어 줌.
// select m from member m where m.name = ? (jpql)
List<Member> findByName(String name);
}
실무에선 스프링, jpa, 스프링 데이터 jpa, 쿼리 dsl -> 생산성 향상.
하지만 스프링 데이터 jpa는 jpa 활용해서 이런 기능 제공할 뿐.
결국 jpa 잘 이해하는것이 중요.