skarltjr / Memory_Write_Record

나의 모든 학습 기록
0 stars 0 forks source link

Spring data JPA #11

Open skarltjr opened 3 years ago

skarltjr commented 3 years ago

스프링 데이터 jpa의 쿼리 메소드 기능 - 매서드이름을 통해

필드명이 변하면 매서드의 이름도 바꿔줘야한다 -> 컴파일시점에 에러를 잡아낼 수 있는 큰 장점

spring data jpa의 NamedQuery

public interface MemberRepository
 extends JpaRepository<Member, Long> {
 List<Member> findByUsername(@Param("username") String username);
} 
- findById처럼 Username을 파라미터로받아 Username으로 찾기

@Query를 통해 매소드에 쿼리 정의하기

public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.username= :username and m.age = :age")
List<Member> findUser(@Param("username") String username, @Param("age") int
age);
}
skarltjr commented 3 years ago

파라미터 바인딩 - 이름기반으로 바인딩하자

select m from Member m where m.username = ?0 //위치 기반
select m from Member m where m.username = :name //이름 기반
public interface MemberRepository extends JpaRepository<Member, Long> {
 @Query("select m from Member m where m.username = :name")
 Member findMembers(@Param("name") String username);
}

컬렉션타입으로 in절도 지원한다.

@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names") List<String> names);

반환타입

List<Member> findByUsername(String name); //컬렉션
Member findByUsername(String name); //단건
Optional<Member> findByUsername(String name); //단건 Optional

spring data jpa의 페이징과 정렬

PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "username")); Page page = memberRepository.findByAge(10, pageRequest);

- 페이지는 0부터
- 만약 페이징한 엔티티를 DTO로 가져간다면

Page page = memberRepository.findByAge(10, pageRequest); Page dtoPage = page.map(m -> new MemberDto());


#### 참고로 카운트쿼리를 따로 뺄 수 있는데 . 복잡한sql에선 카운트쿼리가 매우 무겁기때문에 따로빼주는게 중요!

@Query(value = “select m from Member m”, countQuery = “select count(m.username) from Member m”) Page findMemberAllCountBy(Pageable pageable);

skarltjr commented 3 years ago

벌크연산과 주의점

public int bulkAgePlus(int age) {
 int resultCount = em.createQuery(
 "update Member m set m.age = m.age + 1" +
 "where m.age >= :age")
 .setParameter("age", age)
 .executeUpdate();
 return resultCount;
}

주의!!!!

skarltjr commented 3 years ago

스프링데이터 jpa - 엔티티그래프와 페치조인

등등

- 사용

@EntityGraph(value = "Study.withManagersAndMembers",type = EntityGraph.EntityGraphType.FETCH) Study findWithAllMemberByPath(String path);


#### 스프링데이터jpa의 확장기능
규칙: 리포지토리 인터페이스 이름 + Impl
스프링 데이터 JPA가 인식해서 스프링 빈으로 등록
- Querydsl에서 사용예시 

1. 스터디레포지토리 

@Transactional(readOnly = true) public interface StudyRepository extends JpaRepository<Study,Long>,StudyRepositoryExtension {

2. 커스텀스터디레퍼지토리

@Transactional(readOnly = true) public interface StudyRepositoryExtension {

Page<Study> findByKeyword(String keyWord, Pageable pageable);

List<Study> findByAccountWithTagsAndZones(Account current);

}

3.  2번 커스텀스터디레퍼지토리를 구현하는 Impl

public class StudyRepositoryExtensionImpl extends QuerydslRepositorySupport implements StudyRepositoryExtension { public StudyRepositoryExtensionImpl() { super(Study.class); }

@Override
public Page<Study> findByKeyword(String keyWord, Pageable pageable) {
    JPQLQuery<Study> query = from(study)
            .where(study.published.isTrue()
                    .and(study.title.containsIgnoreCase(keyWord))
                    .or(study.tags.any().title.containsIgnoreCase(keyWord))
                    .or(study.zones.any().localNameOfCity.containsIgnoreCase(keyWord)))
            .leftJoin(study.tags, tag).fetchJoin()
            .leftJoin(study.zones, zone).fetchJoin()
            .distinct();
    JPQLQuery<Study> studyJPQLQuery = getQuerydsl().applyPagination(pageable, query);
    QueryResults<Study> result = studyJPQLQuery.fetchResults();
    return new PageImpl<>(result.getResults(), pageable, result.getTotal());
}

@Override
public List<Study> findByAccountWithTagsAndZones(Account current) {
    JPQLQuery<Study> query = from(study)
            .where(study.tags.any().in(current.getTags())
                    .or(study.zones.any().in(current.getZones()))
                    .and(study.published.isTrue()))
            .leftJoin(study.tags, tag).fetchJoin()
            .leftJoin(study.zones, zone).fetchJoin()
            .orderBy(study.publishedDateTime.desc())
            .limit(9)
            .distinct();
    return query.fetch();
}

}

skarltjr commented 3 years ago

DTO로 변환하여 내보내기 - map

@GetMapping("/members")
public Page<MemberDto> list(Pageable pageable) {
 Page<Member> page = memberRepository.findAll(pageable);
 Page<MemberDto> pageDto = page.map(MemberDto::new);
 return pageDto;
}