Spring/게시판API서버

[Spring] 게시판 API (2) Repository

wans10 2023. 3. 7. 14:03

Entity를 만들었으니 Repository를 작성해보자.

Repository는 DataJPA를 사용해서 구현한다.

 

 

사용법은 인터페이스로 파일을 만들고 JpaRepository를 상속하고 해당 객체와 해당 객체 PK타입을 넣어주면 된다.
JpaRepository에 기본적인 기능들은 전부 구현되어 있다. 이를 Override 해서 고치거나 있는 그대로 사용하면 된다.

MemberRepository

public interface MemberRepository extends JpaRepository<Member, Long> {

    //아이디로 검색
    @Override
    Optional<Member> findById(Long id);
    //이름으로 검색
    Optional<Member> findByUsername(String username);
    //모든 유저이름 리스트만 조회
    @Query("select m.username from Member m")
    List<String> findUsernameList();

}

PostRepository

@Repository
public interface PostsRepository extends JpaRepository<Posts, Long> {
    //member를 join fetch하여 posts를 불러올때 member를 포함하여 조회
    @Override
    @EntityGraph(attributePaths = {"member"})
    //@Query("select p from Posts p join fetch p.member m)
    List<Posts> findAll();

    //멤버 입력시 해당 유저가 쓴 모든 게시글을 조회
    List<Posts> findPostByMember(Member member);


    //게시글의 id로 본문을 조회
    @EntityGraph(attributePaths = {"member","mainText"})
    @Query("select p from Posts p where p.id = :id")
    Optional<Posts> findMainTextById(@Param("id") Long id);

}

Posts Entity 내부에는 member 가 @ManyToOne(fetch = FetchType.LAZY) 지연로딩으로 되어있어 findAll()을 해도 member까지 끌고 오지 못한다.

위의 findAll()을 예시로 원래는 @Query("select p from Posts p join fetch p.member m) 쿼리를 작성해야 한다.
@EntityGraph는 JPA 쿼리 join fetch를 간편하게 attributePaths 안에 join fetch 할 대상을 넣어주면 따로 쿼리를 작성하지 않아도 된다.

CommentRepository

public interface CommentRepository extends JpaRepository<Comment, Long> {
    //본문id에 소속된 모든 댓글들을 조회
    @EntityGraph(attributePaths = {"posts","member"})
    @Query("select c from Comment c where c.posts.id = :id")
    List<Comment> findCommentByPostId(@Param("id") Long postId);
}

@EntityGraph와 @Query를 동시에 사용할 수도 있다.
@EntityGraph를 사용하지 않는다면 @Query("select c form Comment c join fetch c.posts p join fetch c.member m where c.posts.id = :id")로 너무 길어진다.

MainTextRepository

public interface MainTextRepository extends JpaRepository<MainText, Long> {

}

MainTextRepository는 아직까지는 기본 기능만 사용 할 것이다. 나중에 추가되는 기능에 따라 수정이 이루어질 예정.

 

 

Repository를 만들었으니 Controller로 DB에 저장해 보자

@Controller
@RequiredArgsConstructor
@Slf4j
public class PostConstructorController {
    private final PostsRepository postsRepository;
    private final MemberRepository memberRepository;
    private final MainTextRepository mainTextRepository;
    private final CommentRepository commentRepository;

    @PostConstruct
    public void init(){
        for (int i = 1; i < 11; i++) {
            memberRepository.save(new Member("user"+i,"1234"));
        }
        Optional<Member> firstMember = memberRepository.findAll().stream().findFirst();

        for (int i = 1; i < 5; i++) {
            MainText mainText = new MainText("본문쓰"+i);
            mainTextRepository.save(mainText);
            Posts posts = new Posts("게시글 " + i, firstMember.get(),mainText);
            postsRepository.save(posts);
        }

        //게시판테이블 1번 게시물에 회원2가 댓글을 담
        Comment comment = new Comment("댓글1", postsRepository.findAll().stream().findFirst().orElseThrow(), memberRepository.findById(2L).orElseThrow());
        commentRepository.save(comment);
        List<Comment> commentByPostId = commentRepository.findCommentByPostId(1L);
        Comment comment1 = commentByPostId.stream().findFirst().get();
        log.info("댓글: \"{}\", 댓글입력자: {}", comment1.getComment(), comment1.getMember().getUsername());

    }
}

DB에 저장된 데이터

Done !!