본문 바로가기
프로젝트/PongGame

RelationRepository

by 히포파타마스 2022. 6. 1.

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

댓글