공부한 내용
QueryDsl 적용
랭킹 API를 구현하면서, No Offset 방식으로 페이징을 해주면서 QueryDSL의 필요성을 느꼈다.
JPA Query method로 하려고 뻐팅기다가 결국 GG,,
QueryDSL 적용은 아래 순서대로 적용해주면 된다.
1.
build.gradle에 의존성 추가
//querydsl 추가 시작
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
//querydsl 추가 끝
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.8'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" //QueryDsl
}
...
dependencies {
...
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" //QueryDsl
implementation "com.querydsl:querydsl-apt:${queryDslVersion}" //QueryDsl
}
tasks.named('test') {
useJUnitPlatform()
}
//querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
//querydsl 추가 끝
Java
복사
2.
DBConfig.java로 설정 추가
package beachcombine.backend.common.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
@Configuration
public class DBConfig {
@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
return new JPAQueryFactory(entityManager);
}
}
Java
복사
3.
MemberRepository.java에 extends 추가
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {}
Java
복사
4.
MemberRepositoryCustom.java → 인터페이스
public interface MemberRepositoryCustom {
List<Member> findByTotalPointRanking(int pageSize, Long lastId, Integer lastPoint);
List<Member> findByMonthPointRanking(int pageSize, Long lastId, Integer lastPoint);
}
Java
복사
5.
MemberRepositoryImpl.java → 구현체. 꼭 impl로 끝나야함
import static beachcombine.backend.domain.QMember.member;
public class MemberRepositoryImpl implements MemberRepositoryCustom{
private final JPAQueryFactory queryFactory;
public MemberRepositoryImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
}
@Override
public List<Member> findByTotalPointRanking(int pageSize, Long lastId, Integer lastPoint) {
return queryFactory
.select(member)
.from(member)
.where(whereClauseTotal(lastId, lastPoint))
.orderBy(member.totalPoint.desc(), member.id.asc())
.limit(pageSize)
.fetch();
}
private BooleanExpression whereClauseTotal(Long lastId, Integer lastPoint) {
if(lastId != null && lastPoint != null) {
return member.totalPoint.loe(lastPoint).and(member.id.gt(lastId));
}
return null;
}
}
Java
복사
에러
•
non-transient entity has a null id:
◦
cascade 넣기
논의 사항
•
해변 이미지로 default이미지랑 hidden 이미지는 클라에서 띄울지, 서버에서 이미지 보내줄지 정해야 할 거 같음. 회의 때 이야기해보기
◦
해변 이미지로 사용자 프로필 띄우는 건 사용자가 해변에서 기록을 하고 나면 정상적으로 뜰 거임
◦
클라에서 띄우기로 함.
•
purchasePoint 필드는 필요한가 → 필요함
◦
성능 vs 일관성
▪
일관성은 transaction으로 해결하기.
▪
구매를 엄청 많이 한 사용자의 경우 join 연산 반복적으로 수행되어야 해서 성능 저하 클 우려 있음.
▪
일관성보다 성능을 우선시하기로 결정함.
•
더보기 요청 클라와 합의하기.
◦
합의함
•
토요일까지 커뮤니티 기능까지 끝내기.
하루 정리
TIL 작성하기
BeachCombine
랭킹 API 구현
QueryDsl 적용
Dto 변환 방식으로 통일
오늘은 학교에 갔다,,, 아침 수업을 몇 년 만에 들어봤는데 아침 공기가 상쾌하고 좋았다! 진작 아침수업 들을 걸 그랬다. 오히려 낮 수업을 들으러 갈 때면 버스에서 졸기 바빴는데 잠을 적당히 자고 아침 수업을 들으러 가니 버스에서 정신이 굉장히 말똥말똥했다.
버스 타고 가는 길에 줍기 성공한 예술 교양!(사실 교수님께서 정정 메일에 긍정적으로 답변해주셔서 정정으로 들으려 했는데,, 우연히 잡아버렸다,,)을 들었고, 전공 수업으로 정보 보안 수업을 들었다. 다 OT라서 편히 듣고 왔다.
정보 보안 교수님 되게 좋으신 분 같다,,, 한 학기 재밌게 들을 수 있을 거 같은 느낌! 근데 담주 학교 가기 전엔 노션에 수업 내용 적을 거 페이지 정리랑 놑북 파일 정리를 한 번 해야겠다,, 집에서 맨날 데탑으로만 개발하다보니까 놑북이 작년 종강 이후로 그대로인 상태,,,
(추가)
아띠즈 프로젝트를 함께 했던 PM님께서 아띠즈 프로젝트를 가지고 창업을 같이 해보자는 제안을 주셨다.
아띠즈는 팀원 모두가 너무나 열정적이셨고, 개인적으로도 끝내기엔 아까운 서비스란 생각이 들어 함께 하고 싶단 의사를 밝혔다.
물론, 거창한 창업은 아니구, ‘예비 창업 패키지’를 통해 창업을 시작해보는 것에 대해 내부적으로 논의 중이다.
연이 닿아 만난 좋은 팀원분들과 함께 더 성장하고 싶은 욕심이 있기에 잘 됐으면 좋겠다!