2 minute read

스프링 데이터 JPA - MemberRepository 생성

public interface MemberRepository extends JpaRepository<Member, Long>{
    List<Member> findByUsername(String username);
}


//스프링 데이터 JPA테스트

@SpringBootTest
@Transactional
class MemberRepositoryTest{

    @Autowired
    EntityManager em;
    @Autowired
    MemberRepository memberRepository;

    @Test
    public void basicTest() {
        Member member = new Member("member1",10);
        memberRepository.save(member);

        Member findMember = memberRepository.findById(member.getId()).get();
        assertThat(findMember).isEqualTo(member);

        List<Member> result1 =
         memberRepository.findAll();
        assertThat(result1).containsExactly(member);

        List<Member> result2 = memberRepository.findByUsername("member1");
        assertThat(result2).containsExactly(member);
    }
}

//Querydsl 전용 기능인 회원 search 작성 X -> 사용자 정의 리포지토리 필요   


사용자 정의 리포지토리

사용자 정의 리포지토리 사용법

  • 사용자 정의 인터페이스 작성
  • 사용자 정의 인터페이스 구현
  • 스프링 데이터 리포지토리에 사용자 정의 인터페이스 상속

1


사용자 정의 인터페이스 작성

public interface MemberRepositoryCustom{
    List<MemberTeamDto> search(MemberSearchCondition condition);
}


사용자 정의 인터페이스 구현


public class MemberRepositoryImpl implements MemberRepositoryCustom{
    private final JPAQueryFactory queryFactory;

    public MemberRepositoryImpl(EntityManager em){
        this.queryFactory = new JPAQueryFactory(em);
    }

    @Override
    public List<MemberTeamDto> search(MemberSearchCondition condition){
        return queryFactory
            .select(new QMemberTeamDto(
                member.id,
                member.username,
                member.age,
                team.id,
                team.name
            ))
            .from(member)
            .leftJoin(member.team, team)
            .where(usernameEq(condition.getUsername()),
                 teamNameEq(condition.getTeamName()),
                 ageGoe(condition.getAgeGoe()),
                 ageLoe(condition.getAgeLoe()))
            .fetch();
    }

      private BooleanExpression usernameEq(String username) {
          return isEmpty(username) ? null : member.username.eq(username);
}
      private BooleanExpression teamNameEq(String teamName) {
          return isEmpty(teamName) ? null : team.name.eq(teamName);
}
      private BooleanExpression ageGoe(Integer ageGoe) {
          return ageGoe == null ? null : member.age.goe(ageGoe);
}
      private BooleanExpression ageLoe(Integer ageLoe) {
          return ageLoe == null ? null : member.age.loe(ageLoe);
}
 }


스프링 데이터 리포지토리에 사용자 정의 인터페이스 상속

public interface MemberRepository extends JpaRepository<Member, Long>,
  MemberRepositoryCustom {
      List<Member> findByUsername(String username);
  }

//커스텀 리포지토리 동작 테스트 추가
 @Test
  public void searchTest() {
      Team teamA = new Team("teamA");
      Team teamB = new Team("teamB");
      em.persist(teamA);
      em.persist(teamB);
      Member member1 = 
      new Member("member1", 10, teamA);
      Member member2 = 
      new Member("member2", 20, teamA);
      Member member3 = 
      new Member("member3", 30, teamB);
      Member member4 = 
      new Member("member4", 40, teamB);
      em.persist(member1);
      em.persist(member2);
      em.persist(member3);
      em.persist(member4);

      MemberSearchCondition condition = 
      new MemberSearchCondition();
      condition.setAgeGoe(35);
      condition.setAgeLoe(40);
      condition.setTeamName("teamB");
      List<MemberTeamDto> result = memberRepository.search(condition);
      assertThat(result).extracting("username").containsExactly("member4");
  }


스프링 데이터 페이징 활용1 - Querydsl 페이징 연동

//사용자 정의 인터페이스에 페이징 2가지 추가
public interface MemberRepositoryCustom {
      List<MemberTeamDto> search
      (MemberSearchCondition condition);
      Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition,
  Pageable pageable);
      Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition,
  Pageable pageable);
  }


//전체 카운트를 한번에 조회하는 단순한 방법
@Override
  public Page<MemberTeamDto> searchPageSimple(MemberSearchCondition condition,
  Pageable pageable) {
      QueryResults<MemberTeamDto> results = queryFactory
              .select(new QMemberTeamDto(
                      member.id,
                      member.username,
                      member.age,
                      team.id,
                      team.name))
              .from(member)
              .leftJoin(member.team, team)
              .where(usernameEq(condition.getUsername()),
                      teamNameEq(condition.getTeamName()),
                      ageGoe(condition.getAgeGoe()),
                      ageLoe(condition.getAgeLoe()))
              .offset(pageable.getOffset())
              .limit(pageable.getPageSize())
              .fetchResults();
      List<MemberTeamDto> content = results.getResults();
      long total = results.getTotal();
      return new PageImpl<>(content, pageable, total);
  }

//Querydsl이 제공하는 fetchResults() 사용하면 전체 카운트를 한번에 조회가능(쿼리 2번 호출)


//데이터 내용과 전체 카운트를 별도로 조회하는 방법
@Override
public Page<MemberTeamDto> searchPageComplex(MemberSearchCondition condition,
Pageable pageable) {
    List<MemberTeamDto> content = queryFactory
            .select(new QMemberTeamDto(
                    member.id,
                    member.username,
                    member.age,
                    team.id,
                    team.name))
            .from(member)
            .leftJoin(member.team, team)
            .where(usernameEq(condition.getUsername()),
                    teamNameEq(condition.getTeamName()),
                    ageGoe(condition.getAgeGoe()),
                    ageLoe(condition.getAgeLoe()))
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();
    long total = queryFactory
            .select(member)
            .from(member)
            .leftJoin(member.team, team)
            .where(usernameEq(condition.getUsername()),
                    teamNameEq(condition.getTeamName()),
                    ageGoe(condition.getAgeGoe()),
                    ageLoe(condition.getAgeLoe()))
            .fetchCount();
    return new PageImpl<>(content, pageable, total);
}


//PageableExecutionUtils.getPage()로 최적화
JPAQuery<Member> countQuery = queryFactory
        .select(member)
        .from(member)
        .leftJoin(member.team, team)
        .where(usernameEq(condition.getUsername()),
                teamNameEq(condition.getTeamName()),
                ageGoe(condition.getAgeGoe()),
                ageLoe(condition.getAgeLoe()));
  return new PageImpl<>(content, pageable, total);
          return PageableExecutionUtils.getPage(content, pageable,
  countQuery::fetchCount);


# 스프링 데이터 페이징 활용3 - 컨트롤러 개발

 @RestController
  @RequiredArgsConstructor
  public class MemberController {
      private final MemberJpaRepository memberJpaRepository;
      private final MemberRepository memberRepository;
      @GetMapping("/v1/members")
      public List<MemberTeamDto> searchMemberV1(MemberSearchCondition condition)
  {
          return memberJpaRepository.search(condition);
      }
      @GetMapping("/v2/members")
      public Page<MemberTeamDto> searchMemberV2(MemberSearchCondition condition,
  Pageable pageable) {
          return memberRepository.searchPageSimple(condition, pageable);
      }
      @GetMapping("/v3/members")
      public Page<MemberTeamDto> searchMemberV3(MemberSearchCondition condition,
  Pageable pageable) {
          return memberRepository.searchPageComplex(condition, pageable);
      }
}

카테고리:

업데이트:

댓글남기기