[v2] Spring 게시판 조금 알고 따라하기-2

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

1. 게시글 상세보기에서 작성자 표시하기 (ORM 활용)

게시글 상세보기 페이지에서 작성자의 이름을 표시하려면 ORM(Object-Relational Mapping)을 활용해야 합니다.
notion image
notion image
상세보기 페이지에 접속하면, 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. 테스트

notion image
notion image
H2 데이터베이스에서는 쿼리가 정상적으로 실행되지만, 테스트 코드에서는 오류가 발생합니다.
에러 상황 파악을 위해 코드 내부에서 e.printStackTrace(); 를 주석 해제하고 throw 줄을 주석한 뒤 다시 테스트 합니다.
notion image
위처럼 에러내용을 자세히 볼 수 있게됩니다.
오류메세지 : Encountered a duplicated sql alias [ID] during auto-discovery of a native-sql query 이는 board_tbid 컬럼과 user_tbid 컬럼이 중복되어 매핑할 수 없다는 의미입니다.
이 문제를 해결하려면 네이티브 쿼리에서 필드를 개별적으로 매핑하게 되면 이처럼 복잡합니다…
#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. 확인

notion image

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

[HootJem] 개발 기록 블로그