RelationRepository
Relaiton 엔티티를 DB에서 가져오는 RelationRepository를 생성한다.
복잡한 Query문이 들어가거나 Paging을 해야 하는 경우에는 QueryDsl을 사용한다.
1. Spring Data JPA
■ RelationRepository
[RelationRepository]
public interface RelationRepository extends JpaRepository<Relation, Long>, RelationRepositoryCustom {
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " +
"where fromAccount.id = :accountId and relations.relationState = 'REQUEST'")
List<Relation> findAllRequest(@Param("accountId") Long accountId);
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " +
"where fromAccount.id = :accountId and relations.relationState = 'FRIEND'")
List<Relation> findAllFriend(@Param("accountId") Long accountId);
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " +
"where fromAccount.id = :accountId and relations.relationState = 'BLOCK'")
List<Relation> findAllBlock(@Param("accountId") Long accountId);
Optional<Relation> findByFromAccountAndToAccountAndRelationStateEquals(Account fromAccount, Account toAccount,
RelationState relationState);
boolean existsByFromAccountAndToAccountAndRelationStateEquals(Account fromAccount, Account toAccount,
RelationState relationState);
Optional<Relation> findByFromAccountAndToAccount(Account fromAccount, Account toAccount);
}
QueryDsl이 사용된 클래스의 인터페이스인 RelationRepositoryCustom을 상속받는다.
□ findAllRequest
파라미터로 받은 accountId의 Account가 Relation의 주체(fromAccount)이고, "친구 요청"인 상태인 모든 Relation을 List로 가져온다.
[findAllRequest]
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " + //[1]
"where fromAccount.id = :accountId and relations.relationState = 'REQUEST'")
List<Relation> findAllRequest(@Param("accountId") Long accountId);
● [1] : 나중에 결국 조회되는 것은 Relation의 객채(toAccount) 이므로 미리 fetch join 해서 데이터를 가져와 놓는다.
□ findAllFriend
파라미터로 받은 accountId의 Account가 Relation의 주체(fromAccount)이고, "친구" 상태인 모든 Relation을 List로 가져온다.
[findAllFriend]
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " +
"where fromAccount.id = :accountId and relations.relationState = 'FRIEND'")
List<Relation> findAllFriend(@Param("accountId") Long accountId);
□ findAllBlock
파라미터로 받은 accountId의 Account가 Relation의 주체(fromAccount)이고, "차단" 상태인 모든 Relation을 List로 가져온다.
[findAllBlock]
@Query("select relations from Relation relations " +
"join relations.fromAccount fromAccount " +
"join fetch relations.toAccount toAccount " +
"where fromAccount.id = :accountId and relations.relationState = 'BLOCK'")
List<Relation> findAllBlock(@Param("accountId") Long accountId);
□ findByFromAccountAndToAccountAndRelationStateEquals
파라미터로 받은 Account와 RelationStae가 일치하는 Relation을 찾는다.
[findByFromAccountAndToAccountAndRelationStateEquals]
Optional<Relation> findByFromAccountAndToAccountAndRelationStateEquals(Account fromAccount, Account toAccount,
RelationState relationState);
Spring Data JPA의 Query Methods 기능 중 하나로, 메서드의 이름을 기준으로 자동으로 JPQL을 작성해주는 기능이 있다.
이 기능에 의해, "findByFromAccountAndToAccountAndRelationStateEquals" 는 다음과 같은 JPQL이 작성된 것이라고 볼 수 있다.
[JPQL]
select relation from Relation relation
where fromAccount.id = :fromAccountId
and toAccount.id = :toAccountId
and relation.relationState = :relationState
□ existsByFromAccountAndToAccountAndRelationStateEquals
파라미터로 주어진 Account와 RelationState가 일치하는 Relation이 존재하는지를 boolean으로 반환
[existsByFromAccountAndToAccountAndRelationStateEquals]
boolean existsByFromAccountAndToAccountAndRelationStateEquals(Account fromAccount, Account toAccount,
RelationState relationState);
□ findByFromAccountAndToAccount
파라미터로 주어진 Account와 일치하는 Relation을 찾아서 Optional로 반환.
[findByFromAccountAndToAccount]
Optional<Relation> findByFromAccountAndToAccount(Account fromAccount, Account toAccount);
2. QueryDsl
■ RelationRepositoryCustom
QueryDsl을 사용하는 Repository의 인터페이스
[RelationRepositoryCustom]
public interface RelationRepositoryCustom {
public QueryResults<Relation> findRequestsByPage(Long accountId, Pageable pageable);
public List<Relation> findAllRequestFromOther(Long accountId);
public QueryResults<Relation> findRequestsFromOtherByPage(Long accountId, Pageable pageable);
public QueryResults<Relation> findFriendsByPage(Long accountId, Pageable pageable);
public QueryResults<Relation> findBlocksByPage(Long accountId, Pageable pageable);
}
■ RelationRepositoryImpl
[RelationRepositoryImpl]
public class RelationRepositoryImpl extends QuerydslRepositorySupport implements RelationRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
public RelationRepositoryImpl(EntityManager entityManager) {
super(Relation.class);
this.jpaQueryFactory = new JPAQueryFactory(entityManager);
}
@Override
public QueryResults<Relation> findRequestsByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.REQUEST));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
@Override
public List<Relation> findAllRequestFromOther(Long accountId) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
QAccount inFromAccount = new QAccount("inFromAccount");
QAccount inToAccount = new QAccount("inToAccount");
return jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount).fetchJoin()
.join(relation.toAccount, toAccount)
.where(toAccount.id.eq(accountId),
relation.relationState.eq(RelationState.REQUEST),
fromAccount.notIn(JPAExpressions.select(inToAccount)
.from(relation)
.join(relation.fromAccount, inFromAccount)
.join(relation.toAccount, inToAccount)
.where(inFromAccount.id.eq(accountId), relation.relationState.eq(RelationState.BLOCK))))
.fetch();
}
@Override
public QueryResults<Relation> findRequestsFromOtherByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
QAccount inFromAccount = new QAccount("inFromAccount");
QAccount inToAccount = new QAccount("inToAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount).fetchJoin()
.join(relation.toAccount, toAccount)
.where(toAccount.id.eq(accountId),
relation.relationState.eq(RelationState.REQUEST),
fromAccount.notIn(JPAExpressions.select(inToAccount)
.from(relation)
.join(relation.fromAccount, inFromAccount)
.join(relation.toAccount, inToAccount)
.where(inFromAccount.id.eq(accountId),
relation.relationState.eq(RelationState.BLOCK))));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
@Override
public QueryResults<Relation> findFriendsByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.FRIEND));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
@Override
public QueryResults<Relation> findBlocksByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.BLOCK));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
}
□ findRequestsByPage
파라미터로 받은 accountId의 Account가 Relation의 fromAccount이고 "친구 요청" 상태인 Relation을 찾아 Paging 한 뒤 QueryResult로 반환.
[findRequestsByPage]
@Override
public QueryResults<Relation> findRequestsByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount"); //[1]
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.REQUEST));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
● [1] : 동일한 객체의 별칭은 다른 QClass가 사용돼야 하므로 미리 사용될 QClass를 생성해 놓는다.
□ findAllRequestFromOther
파라미터로 받은 accountId가 Relation의 객체(toAccount)이고 "친구 요청" 상태인 Relation을 전부 찾아서 List로 반환한다.
파라미터로 받은 accountId가 Relation의 주체(fromAccount)로써 "차단"한 Account는 조회하지 않는다.
[findAllRequestFromOther]
@Override
public List<Relation> findAllRequestFromOther(Long accountId) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
QAccount inFromAccount = new QAccount("inFromAccount");
QAccount inToAccount = new QAccount("inToAccount");
return jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount).fetchJoin()
.join(relation.toAccount, toAccount)
.where(toAccount.id.eq(accountId),
relation.relationState.eq(RelationState.REQUEST),
fromAccount.notIn(JPAExpressions.select(inToAccount) //[1], [2]
.from(relation)
.join(relation.fromAccount, inFromAccount)
.join(relation.toAccount, inToAccount)
.where(inFromAccount.id.eq(accountId), relation.relationState.eq(RelationState.BLOCK))))
.fetch();
}
● [1] : where의 not in. 조건에 부합되는 fromAccount(toAccount가 차단한 Account)는 조회되지 않는다
● [2] : QueryDsl에서 SubQeury는 JPAExpressions을 사용해서 작성한다.
□ findRequestsFromOtherByPage
파라미터로 받은 accountId가 Relation의 객체(toAccount)이고 "친구 요청" 상태인 Relation을 찾아 Paging 한 후, QueryResults로 반환한다.
파라미터로 받은 accountId가 Relation의 주체(fromAccount)로써 "차단"한 Account는 조회하지 않는다.
[findRequestsFromOtherByPage]
@Override
public QueryResults<Relation> findRequestsFromOtherByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
QAccount inFromAccount = new QAccount("inFromAccount");
QAccount inToAccount = new QAccount("inToAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount).fetchJoin()
.join(relation.toAccount, toAccount)
.where(toAccount.id.eq(accountId),
relation.relationState.eq(RelationState.REQUEST),
fromAccount.notIn(JPAExpressions.select(inToAccount)
.from(relation)
.join(relation.fromAccount, inFromAccount)
.join(relation.toAccount, inToAccount)
.where(inFromAccount.id.eq(accountId),
relation.relationState.eq(RelationState.BLOCK))));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
□ findFreindsByPage
파라미터로 받은 accountId가 Relation의 주체(fromAccount)이고 "친구" 상태인 Relation을 찾아 Paging한 후, QueryResults로 반환한다.
[findFreindsByPage]
@Override
public QueryResults<Relation> findFriendsByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.FRIEND));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
□ findBlocksByPage
파라미터로 받은 accountId가 Relation의 주체(fromAccount)이고 "차단" 상태인 Relation을 찾아 Paging한 후, QueryResults로 반환한다.
[findBlocksByPage]
@Override
public QueryResults<Relation> findBlocksByPage(Long accountId, Pageable pageable) {
QAccount fromAccount = new QAccount("fromAccount");
QAccount toAccount = new QAccount("toAccount");
JPAQuery<Relation> query = jpaQueryFactory.selectFrom(relation)
.join(relation.fromAccount, fromAccount)
.join(relation.toAccount, toAccount).fetchJoin()
.where(fromAccount.id.eq(accountId), relation.relationState.eq(RelationState.BLOCK));
Objects.requireNonNull(getQuerydsl()).applyPagination(pageable, query);
return query.fetchResults();
}
'프로젝트 > PongGame' 카테고리의 다른 글
RelationController (0) | 2022.06.03 |
---|---|
RelationService (0) | 2022.06.03 |
Relation API 명세 (0) | 2022.05.30 |
myLogin (0) | 2022.05.18 |
Account Controller (0) | 2022.05.11 |
댓글