* 아이디 중복확인 체크로직
두가지 방법으로 실행속도 비교
1. JPA Repository 메소드 사용
2. QueryDSL 사용
1. JPA Repository _ existBy~ 메소드
* UserRepository
public interface UserRepository extends JpaRepository<User> {
boolean existsByUserIdAndCode(String userId, String code);
}
* UserService
// 아이디 중복확인 체크 로직
// param: String userId, String code
if(UserRepository.existsByUserIdAndCode(userId, code)){
throw new CustomException(CustomErrorCode.ID_DUPLICATE);
}
=> existsByUserIdAndCode 메소드 : parameter로 받은 userId와 code가 db에 있는지 존재여부를 boolean으로 반환.
true ===> "ID_DUPLICATE" 에러
대부분 4~5 msec 정도.
2. QueryDSL _ selectOne(), fetchFirst()
* UserService
private final EntityManager em;
// ... 생략
// 아이디 중복확인 체크 로직
// param: String userId, String code
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QUser userInfo = QUser.userInfo;
Integer isExist = queryFactory.selectOne()
.from(userInfo)
.where(userInfo.userId.eq(userId)
.and(userInfo.code.eq(code)))
.fetchFirst();
if(isExist != null) {
throw new CustomException(CustomErrorCode.ID_DUPLICATE);
}
=> selectOne 쿼리 : parameter로 받은 userId와 code가 db에 있는지 존재여부를 boolean으로 반환. (isExist)
true ===> "ID_DUPLICATE" 에러
대부분 4~5 msec 정도이나 5 msec 이상으로 넘어가는 경우도 있었다.
두 경우 모두 select limit1 쿼리를 실행하지만 내부적으로 차이가 있다고 한다.
1번의 existsBy... 메소드는 데이터의 존재여부만 확인 후 존재하면 즉시 1을 반환 (없는경우 반환X)
2번의 fetchFirst() 는 조건을 만족하는 결과 중 첫번째 항목을 반환. (없는경우 null 반환.)
' limit 1 ' 쿼리를 수행해서 제한을 하지만 db에서 결과를 가져와 해당 데이터 타입으로 매핑하는 작업이 포함되어 있음!!
테스트 결과 db에 데이터가 많지 않아서 그런지 큰 차이는 없었지만
단순히 존재여부만을 확인하고자 한다면 1번방법이 더 효율적인듯 하다.
* QueryDSL 관련 추가 *
결과로 반환되는 데이터(매핑된 객체)를 활용할 필요가 없다면
.fetchFirst() != null 로 처리해 결과를 boolean으로 받아도 된다. (하지만 객체를 활용할 이유로 fetchFirst()를 쓰지 않을까)
private final EntityManager em;
// ... 생략
// 아이디 중복확인 체크 로직
// param: String userId, String code
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QUser userInfo = QUser.userInfo;
boolean isExist = queryFactory.selectOne()
.from(userInfo)
.where(userInfo.userId.eq(userId)
.and(userInfo.code.eq(code)))
.fetchFirst() != null;
if(isExist) {
throw new CustomException(CustomErrorCode.ID_DUPLICATE);
}
=> 조건에 만족하는 반환데이터의 null여부를 쿼리에서 체크하고 boolean으로 반환. (isExist)
true ===> "ID_DUPLICATE" 에러
* QueryDSL _ count(), fetchOne() *
결과로 반환되는 데이터의 count값이 필요하다면
private final EntityManager em;
// ... 생략
// 아이디 중복확인 체크 로직
// param: String userId, String code
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QUser userInfo = QUser.userInfo;
long count = queryFactory.select(userInfo.count())
.from(userInfo)
.where(userInfo.userId.eq(userId)
.and(userInfo.code.eq(code)))
.fetchOne();
if (count > 0) {
throw new CustomException(CustomErrorCode.ID_DUPLICATE);
}
=> 조건에 만족하는 테이블의 갯수를 long타입으로 반환. (count)
count > 0 ===> "ID_DUPLICATE" 에러
* count vs exist *
count는 db에서 결과데이터의 갯수를 가져오기 때문에 데이터를 객체로 매핑하는 작업이 없지만,
테이블 전체를 탐색하기 때문에 exist보다는 시간이 오래걸릴 수 있음!
필요한 정보가 결과데이터인지 결과데이터 존재여부인지에 따라 적절한 메소드 선택하기!!
* fetchOne(), fetchFirst() : QueryDSL 에서 데이터를 조회할 때 쿼리의 결과를 반환하는 메소드.
- fetchOne()
단 하나의 결과만을 반환 (결과가 하나 이상이면 NonUniqueResultException, 없으면 null)
=> 결과가 없거나 정확이 하나임이 보장될 때.
- fetchFirst()
첫 번째 결과만을 반환 (추가적인 결과는 무시, 결과가 없으면 null)
> 내부적으로 limit(1).fetchOne() 을 수행. (결과를 단건으로 치환 후 반환하는 방식)
=> 정렬된 데이터 중 조건에 만족하는 최상위 데이터가 필요할 때.
'Java > JPA' 카테고리의 다른 글
[JPA] 네이티브 쿼리 (조건문) + 오류 (0) | 2024.10.12 |
---|---|
[JPA] findBy~ 일부 필드값만 가져오기 (JPQL, 네이티브쿼리) / (+ 오류) (0) | 2024.07.28 |
[JPA] List<Entity> 비교 (0) | 2024.06.19 |
[JPA] findById, existsById, getById (0) | 2024.06.19 |
[JPA] Querydsl 벌크삭제 (0) | 2024.06.19 |