원칙적으로 구 list에 있는 team을 제거하도록 코드를 작성하는 것이 맞습니다.
다만 이 관계에서 list는 연관관계의 주인이 아니므로 실제 데이터베이스에 영향을 주지는 않습니다.
객체까지 고려하면 list에 있는 team을 제거하는 것이 맞지만, 실용적인 관점에서 그냥 두어도 DB에서 삭제되지 않으므로 크게 상관은 없습니다^^
→ Team내의 members 객체는 우리가 만든거다. DB관점에서 보면 team테이블 안에 members컬럼이 있는게 아니므로 지장이 없다!!
예시
@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names")Collection<String> names);
조회 결과가 많거나 없으면?
있는지 없는지 모르면 → Optional 사용
List 비어있으면
List<Member> result = memberRepository.findListByUsername(”asdfasdf”);
if (result != null)
//이렇게 List가 비어있는지 확인하는 거는 실무에서 안좋은 코드다.
//List는 절대 null이 아니니까 받아라, 없으면 empty collection이 반환된다.
모바일에서 더보기 기능으로 페이징 구현하는거는 Slice로 이용, 추가 count쿼리 없이 다음 페이지만 확인가능(내부적으로 limit + 1 조회)
반환타입 Page냐,Slice냐에 따라서 totalCount를 날릴지 안날릴지를 결정
페이징처리 성능이 안나오면? countQuery 분리해서만들기
예시코드
@Query(value = "select m from Member m left join m.team t",
countQuery = "select count(m) from Member m")
Page<Member> findByAge(intage,Pageablepageable);
카운트 쿼리 분리(이건 복잡한 sql에서 사용, 데이터는 left join, 카운트는 left join 안해도 됨)
실무에서 매우 중요!!!
query result에 findTop3by 해서 가져온 것 중 상위 3개 이렇게 뽑을 수도 있다.
다시 강조 Entity를 그대로 반환하면 안된다.!!
Dto로 반환해라
Page<MemberDto> toMap = page.map(member -> new MemberDto(member.getId(), member.getUsername(), null));
SpringDataJPA에서 벌크연산할 때 @Modifying넣어줘야 executeUpdate가 실행된다.! 중요
간단할 때는 →EntityGraph, 복잡할 때는 JPQL + Fetch Join
JPA Hint → JPA 쿼리 힌트(SQL 힌트가 아니라 JPA 구현체에게 날리는 힌트)
"org.hibernate.readOnly"
를 쿼리 힌트로 주면 읽기만 해서 변경 감지를 체크 안한다.(스냅샷 생성x)
실시간 서비스가 많은 곳에는 Lock을 걸면 안된다. 실제로는 versioning이나 메커니즘으로 해결
사용자 정의 인터페이스 구현 클래스명을 [class 명 + Impl]로 구현해야 Spring Data JPA가 인터페이스로 상속한 메소드를 찾아준다.
(참고) 화면상 API Repository / 핵심 비즈니스로직 or 복잡한 통계결과값이 나와야하는 API Repository는 분리하는 경우도 있다.
(개인 복습) API 응답값으로 나갈 때는 []처럼 Array형식이 아니라 {}형식으로 나가야 한다.(이유: Array형식은 유연성이 떨어진다. fetch조인 해도 service단에서 dto로 .stream.map.collect하기
테이블 만들 때 등록일,수정일 필수로 넣으면 좋다!(모든 테이블에 적용)
등록일,수정일 처럼 속성만 가져오고싶으면 @MappedSuperclass
를 속성만든 곳에 선언해라
등록자 수정자는 필수가 아니므로, 필수인 BaseTimeEntity를 상속받게 해서 필요할 때만 BaseEntity 구현하게끔 하면 된다.
도메인 클래스 컨버터는 “조회용"이다. 엔티티를 변경해도 DB에 반영되지 않는다.(간단하게 사용할 때만 가능하다고 생각하자)
localhost:8080/members?page=1&size=3 Pageable 인터페이스를 통해 값을 이렇게 넣을 수 있다.
페이징 정보가 둘 이상일 때 → 접두사 이용
Entity 는 Dto를 보면 안되는데 , Dto는 Entity를 봐도 된다.
서비스 계층에서 트랜잭션을 시작하지 않으면 리파지토리에서 트랜잭션 시작
서비스 계층에서 트랜잭션을 시작하면 리파지토리는 해당 트랜잭션을 전파 받아서 사용
병합(merge)는 쓰면 안된다 →변경감지 (기존의 것은 set으로 변경하는거)
save()는 값이 있으면 자동으로 merge가 나간다
엔티티 대신에 DTO에서 멤버 이름만 조회하고 싶을 때(=select절의 내용을 정하는 것) → Projection
projection의 한계 entity가 1개가 넘어가면 쓰기가 애매해진다.
네이티브 SQL은 보통
QueryDSL로 해결, 안되면 JPQL
둘 다 안되면 JdbcTemplate,mybatis 사용하자
→ 하지만 네이티브를 사용할 일은 거의 없다.