스프링 공부 77

[스프링] 21. MemberCustomRepository : 조회를 엔티티로 반환하는게 과연 좋을까?

이전에 만든 검색기능을 조금 더 최적화 시켜야 할 필요가 있다. 이러한 생각이 든 이유는, 멤버를 검색하는 기능에서 엔티티가 바로 클라이언트 단으로 나가도 괜찮을까? 일반 사용자가 다른 사용자를 검색했을 때 나와야 할 것은 기본적인 정보(아이디, 닉네임, 이메일)외에 다른 게 없는데 굳이 많은 데이터를 끌어올 필요가 있을까? 정도였다. 그래서, 이번엔 바로 dto로 데이터를 검색시키는 방법으로 최적화를 시키려고 한다. 일단, @QueryProjection public SearchMemberDto(String username, String nickname, String email) { this.username = username; this.nickname = nickname; this.email = ema..

[스프링] 20. QueryDsl을 이용해 MemberCustomRepository를 더 깨끗하게!!!

저번에 만든 QueryDsl을 어디에 써먹는지, 이제 적어볼 생각이다. 저번에 만든 MemberCustomRepositoryImpl의 search를 전부 지워버렸다. 이후, QueryDsl을 위해 만들어야 할 것들을 정리해보았다. JPAQueryFactory 인스턴스를 초기화 하는 생성자 search : 아이디, 닉네임, 이메일을 가지고 검색을 수행한다. null값은 스킵한다. usernameEq : 아이디가 null이면 null을 반환하고, 아니면 쿼리문을 반환한다. nicknameEq : 닉네임이 null이면 null을 반환하고, 아니면 쿼리문을 반환한다. emailEq : 이메일이 null이면 null을 반환하고, 아니면 쿼리문을 반환한다. 이제 이걸 만들어보자. public class Member..

[스프링] 19. QueryDsl 넣어주기

실질적으로 지난 블로그 공백기(!) 중에 제일 공부하기 잘했다고 생각이 드는, queryDsl을 설정해줄 것이다. 일단 build.gradle에 이러한 의존성과, 설정 주입을 해주어야 한다. buildscript { ext { queryDslVersion = "5.0.0" } } plugins { id 'java' id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } 제일 위에 queryDslVersion을 적어주고, plugins에 마지막줄에 queryDsl을 넣..

[스프링] 18. MemberRepository커스텀해서 검색기능 만들기

저번에 만든 멤버 리포지토리를 가지고, 이제 새로운 기능들을 주입시켜볼 것이다. 기본적으로 메서드의 이름을 가지고 생성, 조회, 삭제를 할 수 있다. 그러면 조회하는 요소를 이름, 이메일, 닉네임중에 몇개를 골라서 수행하는, 동적 방식의 조회는 어떻게 할까? 이걸 JPQL(노가다)로 한번 만들어보고, 테스트를 수행시켜보고, QueryDSL을 통해 업그레이드 시켜볼 계획이다. 일단, 검색을 시켜줄 dto와 예외처리부터 만들었다. @Data public class SearchMemberDto { private String username; private String nickname; private String email; public SearchMemberDto(String username, String n..

[스프링] 17. MemberRepository 테스트해보기

일단 클래스를 만들었다. @SpringBootTest는 이 테스트가 스프링 부트 상에서 돌아간 다는 것을 의미하고, @Transactional은 해당 클래스가 트랜잭션을 만듦을 의미한다. 일단 C, R, U, D를 다 테스트해보아야 하는데, 생각해보면, 만든게 조회가 제대로 되면, 내 머리같이(?) 비어있는 데이터베이스에 데이터가 생기는 것이다. 즉, 생성은 테스트하지 말고, 그냥 생성시키는 로직을 만든 뒤, 조회를 시키면 되는 것! 그래서! @Autowired private MemberRepository memberRepository; @Autowired private EntityManager em; @BeforeEach public void initData(){ RegisterRequestDto re..

[스프링] 16. MemberRepository 만들기

사실 게시판 만들기를 하다가 대략 2~3주 정도를 쉰 것 같다. 이유인 즉슨, 리포지토리를 테스트하는 방법을 찾다가 여러 강의들을 찾게되었다. 공부하다가 로드맵? 이라는 게 있었다. 로드맵을 보니까 또 이게 다 뭔지 알고싶었다 (또 호기심이 미쳐 날뛰어 버렸다) 그래서 이제 할 수 있겠냐고? ㅆㄱㄴ 가능하니까 이제 다음 과정들을 써보려고 한다. 일단 리포지토리의 기본적인 기능들을 만들어볼 생각이다. 우리가 백엔드 프로그래밍을 배우면 기본적으로 CRUD라는 것을 듣게 된다. Create Read Update Delete 이렇게 4가지가 존재한다. 이에 대한 기능들을 Spring Data JPA에서 지원하는 리포지토리를 이용해 만들어보려고 한다. package com.board.Board_Upgraded.r..

[JPA] 28. Re.Zero : JPQL : 뻘크업(연)산

벌크 연산 쉽게 생각하면 sql의 update, delete문을 일컫는다. Row 하나를 골라 실행하는 것이 아닌, 전체를 기준으로 실행시키는 방식이다. 이를 JPA에서 기본 제공하는 변경 감지로 실행하려면 변경해야할 대상들을 쿼리문으로 가져온다. 가져온 엔티티의 값을 변경시킨다. 변경될 때 마다 변경 감지가 발생해 바꿀 때 마다 update문이 발생한다. 쓸데없이 쿼리를 많이 쓰게 된다.(이것도 N+1처럼 쿼리 하나 후에 N번의 쿼리를 또 처리하는 모습이다) 이럴 때 .executeUpdate를 실행하면 한번에 테이블 단위로 조작이 가능하다. 이런식으로 나이를 1~100으로 만들어둔 후, 모든 멤버의 나이를 20으로 update시키는 쿼리문을 날렸다. (벌크 연산) 이 후 나이가 20인 멤버를 셌을 때..

[JPA] 27. Re.Zero : JPQL 그냥 다 끍어오기.(fetch join)

페치 조인 돼지꼬리 그리고 별 세개 박고 밑줄 쫙 긋고 하이라이트까지 칠해라. 겁나 중요하다. SQL 조인 종류는 아니다. JPQL에서 성능 최적화를 위해 따로 만든 기능으로, 연관된 엔티티나 모든 컬렉션을 한번에 조회하는 기능이다. Join fetch 명령어를 이용한다. 2번으로 나뉘는 쿼리들을 한방에 나가게 할 수 있다. Select m from Member m join fetch m.team; 이러한 페치 조인은, 회원을 조회하며 연곤 팀도 같이 구해올 수 있다. 즉, 멤버의 정보와 멤버가 속한 팀의 정보를 모두 구해오게 해준다. (즉시로딩과 똑같이 동작한다. 하지만 쿼리를 통한 명시적 방식이다) 이렇게 만들어진 상황에서, 페치 조인이 아닌 그냥 멤버 조회를 했을 때, 멤버에서 팀을 가져온다고 해보..

[JPA] 26. Re.Zero : JPQL 함수/경로 표현

JPQL에서 사용하는 함수 함수는 JPQL표준함수 Concat : 두 문자를 더해준다. 이를 concat(‘A’, ‘B’) 로 써도 되지만, ‘A’ || ‘B’ 를 써도 된다. Substring : 자바의 substring은 문자열의 일부를 떼어내는 방식이다. Trim : 공백을 제거한다. Lower, upper : 전부 소문자/ 대문자로 바꾸어준다. Length : 길이를 반환해준다. Locate : locate(찾아야 하는 부분, 찾는 대상)으로 넣어 해당 위치를 반환해준다. Abs, sqrt, mod : 일반적인 수학의 방식으로, 순서대로 절대값/제곱근/제곱을 구해준다. Size, index : 팀을 기준으로, 팀에 속한 멤버의 수를 세어줄 수 있다. Select size(t.members) fro..

[JPA] 26. Re.Zero : JPQL 의 타입표현

JPQL의 타입 표현 문자 : ‘~’(작은 따옴표)에 넣어주어야 한다. 숫자 : Integer를 제외한 경우에는, L(Long), D(Double), F(Float)를 숫자 뒤에 입력해주어야 한다. Boolean : TRUE, FALSE ENUM : entity.Role.USER ( 패키지를 모두 포함시켜야 한다 ) 엔티티 타입 : TYPE(m) = MEMBER( 보통은 상속관계에서 사용된다 ) 조건식 기본 case : select case when m.age = 60 then ‘경로요금’ else ‘일반요금’ end from Member m; 단순 case : select case t.name when ‘A’ then ‘+110%’ when ‘B’ then ‘+120%’ else ‘+105%’ end ..