[v2] Spring 게시판 조금 알고 따라하기-2
게시글 상세보기 페이지에서 작성자의 이름을 표시하려면 ORM(Object-Relational Mapping)을 활용해야 합니다.
Aug 21, 2024
1. 게시글 상세보기에서 작성자 표시하기 (ORM 활용)
게시글 상세보기 페이지에서 작성자의 이름을 표시하려면 ORM(Object-Relational Mapping)을 활용해야 합니다.


상세보기 페이지에 접속하면,
LAZY
로딩 전략을 사용했기 때문에 board
만 조회하는 쿼리가 실행됩니다.하지만 상세보기에서는 작성자의 이름도 필요합니다. 이를 해결하기 위해
EAGER
로딩 전략을 사용할 수도 있지만, 이는 불필요한 IO가 과도하게 발생할 수 있습니다. 따라서, JOIN
을 사용하여 문제를 해결하는 것이 더 효율적입니다.
public Board findById(int id) {
Query query = em.createNativeQuery("select * from board_tb bt inner join user_tb ut on bt.user_id = ut.id where bt.id=?", Board.class);
query.setParameter(1, id);
try {
Board board = (Board) query.getSingleResult(); // 다운캐스팅 필요
return board;
} catch (Exception e) {
// 익세션을 내가 잡은것 까지 배움 - 처리 방법은 v2 에서 배우기
throw new RuntimeException("게시글 id를 찾을 수 없습니다");
//e.printStackTrace();
}
}
사용된 쿼리문입니다
select * from board_tb bt inner join user_tb ut on bt.user_id = ut.id where bt.id=1;
이때
Board.class
는 결과를 Board
객체로 매핑해줍니다.
2. 테스트


H2 데이터베이스에서는 쿼리가 정상적으로 실행되지만, 테스트 코드에서는 오류가 발생합니다.
에러 상황 파악을 위해 코드 내부에서
e.printStackTrace();
를 주석 해제하고 throw 줄을 주석한 뒤 다시 테스트 합니다.
위처럼 에러내용을 자세히 볼 수 있게됩니다.
오류메세지 :
Encountered a duplicated sql alias [ID] during auto-discovery of a native-sql query
이는 board_tb
의 id
컬럼과 user_tb
의 id
컬럼이 중복되어 매핑할 수 없다는 의미입니다.
이 문제를 해결하려면 네이티브 쿼리에서 필드를 개별적으로 매핑하게 되면 이처럼 복잡합니다…
#gpt 제공 참고만 하기
Query query = em.createNativeQuery(
"select bt.id as bt_id, bt.title, bt.content, bt.user_id, " +
"ut.id as ut_id, ut.username, ut.email " +
"from board_tb bt " +
"inner join user_tb ut on bt.user_id = ut.id " +
"where bt.id = ?",
"BoardMapping"
);
코드의 복잡성을 피하기 위해
createQuery
사용 하여 JPQL 로 쿼리를 작성하겠습니다. public Board findById(int id) {
Query query = em.createQuery("select b from Board b join fetch b.user u where b.id = :id", Board.class); // 객체지향 쿼리
query.setParameter("id", id);
try {
Board board = (Board) query.getSingleResult(); // 다운캐스팅 필요
return board;
} catch (Exception e) {
// 익세션을 내가 잡은것 까지 배움 - 처리 방법은 v2 에서 배우기
throw new RuntimeException("게시글 id를 찾을 수 없습니다");
}
}
createQuery
는 JPQL을 사용하여 데이터베이스 쿼리로 자동 변환되므로 마이그레이션이 필요하지 않습니다.👍3. 템플릿 코드 변경
이후, Mustache 템플릿에서 작성자의 이름을 표시할 부분을 다음과 같이 수정합니다:
<div class="d-flex justify-content-end">
<b>작성자</b> : {{model.user.username}}
</div>
model.title
과 같은 다른 필드들은 Board
객체 내부의 속성을 바로 가져오지만, 작성자 이름은 Board
객체의 user
속성 안에 있으므로 model.user.username
형태로 접근해야 합니다.4. 확인

createNativeQuery와 createQuery 의 차이를 다룬 포스팅
스프링부트 게시판 시리즈 v2 -1. https://inblog.ai/hj/27190 (User 테이블 생성 및 쿼리 수정) -2. https://inblog.ai/hj/27193 (User, Board 테이블 조인 과 JPQL) -3. https://inblog.ai/hj/27224 (회원 가입) -4. https://inblog.ai/hj/27225 DTO 를 통한 리팩토링 -5. https://inblog.ai/hj/27310 로그인, 로그아웃 -6. https://inblog.ai/hj/27316 서비스 레이어 추가 및 DTO 활용 -7. https://inblog.ai/hj/27430 예외처리 핸들러 설정과 User 서비스 리팩토링 -8. https://inblog.ai/hj/27431 Board 기능 리팩토링 -9. https://inblog.ai/hj/27560 게시글 수정, 더티체킹(flush) -10. https://inblog.ai/hj/27561 인터셉터, AOP 사용 / 마무리
Share article