인텔리제이 한글깨짐 해결법
한글깨지는거 해결함
Article에 달릴 댓글을 위해 엔티티, 리포지토리를 만들어보자
Article과 Comment는 1대 다 관계
댓글은 PK와 FK를 가진다
PK : 나의 id
FK : 대상을 가리키는 id
댓글에서 게시글을 찾아갈 수 있는 구조로 엔티티를 만들어야 한다.
리포지토리는 CrudRepository를 확장한 리포지토리를 확장한 JpaRepository를 사용한다
package com.example.firstproject.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne // 댓글 엔티티 여러개가 하나의 Article에 연관됨
@JoinColumn(name = "article_id") // article_id 컬럼에 연결된 Article의 대표값을 저장(필드명 지정)
private Article article;
@Column
private String nickname;
@Column
private String body;
}
Comment 엔티티의 코드다.
article 필드의 @ManyToOne은 Article 엔티티 하나에 Comment 엔티티 여러개가 연관된다는 의미다.
@JoinColumn은 Comment 엔티티의 article_id 필드에 Article의 대표값을 저장한다는 뜻이다.
확인해보면 Comment 테이블이 DB에 생긴 것을 확인할 수 있다.
insert into article(id, title, content) values(1, 'aaaa', '1111');
insert into article(id, title, content) values(2, 'bbbb', '2222');
insert into article(id, title, content) values(3, 'cccc', '3333');
-- article 더미 데이터
insert into article(id,title,content) values(4, '당신의 인생 영화는?', '댓글 ㄱ');
insert into article(id,title,content) values(5, '당신의 소울 푸드는?', '댓글 ㄱ');
insert into article(id,title,content) values(6, '당신의 취미는?', '댓글 ㄱ');
-- comment 더미 데이터
insert into comment(id,article_id,nickname,body) values(1,4,'Park','굳 윌 헌팅');
insert into comment(id,article_id,nickname,body) values(2,4,'Kim','아이 엠 샘');
insert into comment(id,article_id,nickname,body) values(3,4,'Choi','쇼생크 탈출');
insert into comment(id,article_id,nickname,body) values(4,5,'Park','치킨');
insert into comment(id,article_id,nickname,body) values(5,5,'Kim','샤브샤브');
insert into comment(id,article_id,nickname,body) values(6,5,'Choi','초밥');
insert into comment(id,article_id,nickname,body) values(7,6,'Park','조깅');
insert into comment(id,article_id,nickname,body) values(8,6,'Kim','유튜브');
insert into comment(id,article_id,nickname,body) values(9,6,'Choi','독서');
data.sql에 article과 comment의 더미데이터를 만들어준다.
내 id : PK
다른 테이블의 id : FK
package com.example.firstproject.repository;
import com.example.firstproject.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface CommentRepository extends JpaRepository<Comment, Long> {
// 특정 게시글의 모든 댓글 조회
@Query(value = "SELECT * FROM comment WHERE article_id = :articleId",nativeQuery = true)
List<Comment> findByArticleId(Long articleId);
// 특정 닉네임의 모든 댓글 조회
List<Comment> findByNickname(String nickname);
}
CommentRepository는 인터페이스로 만들어준다.
JpaRepository를 상속한다.
findByArticleId는 특정 게시글의 모든 댓글을 조회하는 메소드다
Comment의 List를 반환하고 @Query 어노테이션으로 쿼리문을 넣어줬다
쿼리문의 :articleId 부분이 매개변수 articleId와 매칭된다.
findByNickname 메소드느 특정 닉네임의 모든 댓글을 조회하는 메소드다.
이 메소드는 어노테이션 말고 xml 파일을 만들어서 쿼리를 연결해보자.
resources 에 META-INF > orm.xml을 만들어준다.
<?xml version="1.0" encoding="utf-8" ?>
<entity-mappings xmlns="https://jakarta.ee/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence/orm
https://jakarta.ee/xml/ns/persistence/orm/orm_3_0.xsd"
version="3.0">
<named-native-query
name="Comment.findByNickname"
result-class="com.example.firstproject.entity.Comment">
<query>
<![CDATA[
SELECT
*
FROM
comment
WHERE
nickname = :nickname
]]>
</query>
</named-native-query>
</entity-mappings>
orm.xml의 내용은 위와 같이 작성해준다.
바깥의 entitiy-mappings는 구글링 해서 작성하면 됨
name-native-query 태그의 내용을 보면 된다.
name의 메소드가 query의 쿼리문을 실행하고 결과로 result-class 타입을 반환한다는 뜻이다.
쿼리가 단순한 경우엔 어노테이션, 쿼리가 복잡하거나 최적화가 필요한 경우엔 xml을 사용하면 좋다.
테스트하기 위해서 CommentRepositoryTest 클래스를 만들어준다.
package com.example.firstproject.repository;
import com.example.firstproject.entity.Article;
import com.example.firstproject.entity.Comment;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@DataJpaTest // 리포지토리 테스트니까 Jpa와 연동해서 테스트할 수 있다
class CommentRepositoryTest {
@Autowired CommentRepository commentRepository;
@Test
@DisplayName("특정 게시글의 모든 댓글 조회")
void findByArticleId() {
{
// 입력 데이터 준비
Long articleId = 4L;
//실제 수행
List<Comment> comments = commentRepository.findByArticleId(articleId);
//예상하기
Article article = new Article(4L, "당신의 인생 영화는?","댓글 ㄱ");
Comment a = new Comment(1L,article,"Park","굳 윌 헌팅");
Comment b = new Comment(2L,article,"Kim","아이 엠 샘");
Comment c = new Comment(3L,article,"Choi","쇼생크 탈출");
List <Comment> expected = Arrays.asList(a,b,c);
// 검증
assertEquals(expected.toString(),comments.toString(),"4번 글의 모든 댓글을 출력");
}
}
@Test
void findByNickname() {
}
}
findByArticleId의 테스트는 이렇게 작성했다.
CommentRepositoryTest의 어노테이션을 @DataJpaTest로 Jpa와 연동해 테스트 클래스를 만든다
클래스의 멤버로 commentRepository를 만들어줬다
그리고 전에 테스트 만들 때는 직접 메소드 이름에 내용을 넣어줬는데 그렇게 안하고 @DisplayName으로 작성할 내용을 넣어도 된다.
메소드 내용은 4번 게시글의 모든 댓글을 얻는 findByArticleId와 실제 데이터를 만들어서 비교한다.
참고 ) 계속 테스트에 실패해서 확인해보니 Comment 클래스에 @ToString 어노테이션을 안달았었다..
void findByArticleId() {
/* Case 1: 4번 게시글의 모든 댓글 조회 */
{
// 준비
Long articleId = 4L;
// 수행
List<Comment> comments = commentRepository.findByArticleId(articleId);
// 예상
Article article = new Article(4L, "당신의 인생 영화는?", "댓글 ㄱ");
Comment a = new Comment(1L, article, "Park", "굳 윌 헌팅");
Comment b = new Comment(2L, article, "Kim", "아이 엠 샘");
Comment c = new Comment(3L, article, "Choi", "쇼생크의 탈출");
List<Comment> expected = Arrays.asList(a, b, c);
// 검증
assertEquals(expected.toString(), comments.toString(), "4번 글의 모든 댓글을 출력!");
}
/* Case 2: 1번 게시글의 모든 댓글 조회 */
{
// 준비
Long articleId = 1L;
// 수행
List<Comment> comments = commentRepository.findByArticleId(articleId);
// 예상
Article article = new Article(1L, "가가가가", "1111");
List<Comment> expected = Arrays.asList();
// 검증
assertEquals(expected.toString(), comments.toString(), "1번 글은 댓글이 없음");
}
}
추가해서 1번 게시물에 대해 테스트를 진행한다
1번 게시글은 댓글이 없어서 빈 List를 대상으로 비교햔다
@Test
@DisplayName("특정 닉네임의 모든 댓글 조회")
void findByNickname() {
// Case 1 : Park의 모든 댓글 조회
{
// 입력 데이터 준비
String nickname = "Park";
//실제 수행
List<Comment> comments = commentRepository.findByNickname(nickname);
//예상하기
Comment a = new Comment(1L, new Article(4L, "당신의 인생 영화는?", "댓글 ㄱ"), nickname, "굳 윌 헌팅");
Comment b = new Comment(4L, new Article(5L, "당신의 소울 푸드는?", "댓글 ㄱㄱ"), nickname, "치킨");
Comment c = new Comment(7L, new Article(6L, "당신의 취미는?", "댓글 ㄱㄱㄱ"), nickname, "조깅");
List<Comment> expected = Arrays.asList(a, b, c);
//검증
assertEquals(expected.toString(),comments.toString(),"Park의 모든 댓글을 출력");
}
}
닉네임을 통해 댓글을 찾는 findByNickName도 테스트 메소드 만들어준다
package com.example.firstproject.repository;
import com.example.firstproject.entity.Article;
import com.example.firstproject.entity.Comment;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.repository.query.Param;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@DataJpaTest // 리포지토리 테스트니까 Jpa와 연동해서 테스트할 수 있다
class CommentRepositoryTest {
@Autowired CommentRepository commentRepository;
@Test
@DisplayName("특정 게시글의 모든 댓글 조회")
void findByArticleId() {
/* Case 1: 4번 게시글의 모든 댓글 조회 */
{
// 준비
Long articleId = 4L;
// 수행
List<Comment> comments = commentRepository.findByArticleId(articleId);
// 예상
Article article = new Article(4L, "당신의 인생 영화는?", "댓글 ㄱ");
Comment a = new Comment(1L, article, "Park", "굳 윌 헌팅");
Comment b = new Comment(2L, article, "Kim", "아이 엠 샘");
Comment c = new Comment(3L, article, "Choi", "쇼생크의 탈출");
List<Comment> expected = Arrays.asList(a, b, c);
// 검증
assertEquals(expected.toString(), comments.toString(), "4번 글의 모든 댓글을 출력!");
}
/* Case 2: 1번 게시글의 모든 댓글 조회 */
{
// 준비
Long articleId = 1L;
// 수행
List<Comment> comments = commentRepository.findByArticleId(articleId);
// 예상
Article article = new Article(1L, "가가가가", "1111");
List<Comment> expected = Arrays.asList();
// 검증
assertEquals(expected.toString(), comments.toString(), "1번 글은 댓글이 없음");
}
}
@Test
@DisplayName("특정 닉네임의 모든 댓글 조회")
void findByNickname() {
// Case 1 : Park의 모든 댓글 조회
{
// 입력 데이터 준비
String nickname = "Park";
//실제 수행
List<Comment> comments = commentRepository.findByNickname(nickname);
//예상하기
Comment a = new Comment(1L, new Article(4L, "당신의 인생 영화는?", "댓글 ㄱ"), nickname, "굳 윌 헌팅");
Comment b = new Comment(4L, new Article(5L, "당신의 소울 푸드는?", "댓글 ㄱㄱ"), nickname, "치킨");
Comment c = new Comment(7L, new Article(6L, "당신의 취미는?", "댓글 ㄱㄱㄱ"), nickname, "조깅");
List<Comment> expected = Arrays.asList(a, b, c);
//검증
assertEquals(expected.toString(),comments.toString(),"Park의 모든 댓글을 출력");
}
}
}
CommentRepositoryTest.java 전체 코드
이렇게 어떤 부분이 틀렸는지 확인할 수 있다.