🐷 (주저리주저리 시작, 문제 해결은 2부터)
스프링 부트가 아닌 스프링으로 다중 테이블에서 값을 가지고 온 뒤에 controller를 이용해서 jsp로 값을 보내야했다.
단일 테이블의 데이터를 가지고 오는 것은 select * from movie where movieid = #{movie_id} 이런 식으로 간단했지만 다중 테이블에서 값을 가지고 오는 문제는 차원이 달랐다........ 책에도 스프링에서 이럴땐 어떻게 해야하는 지에 대해서는 나와있지 않았다.... (해결하고나서 스프링 부트 책을 보니 부트에는 있더라 🤯)_
조인을 사용해서 값을 가지고 오는 것 자체도 이번에 DB를 처음 설계해보고 sql을 고작 일주일정도 배운 나에게는 시작부터 어떻게 해야하지...하는 문제가 있었지만 다행히 생각보다 빨리(?) 해결<- 했다.
문제는 값을 movie_id 그냥 이런식으로 가져와서 movie 테이블에 대한 값만 jsp에서 출력이 가능했다...
이 문제 때문에 엄청나게 많은 문서를 보면서 방법들을 시도해봤지만 쉽게 해결이 되지 않았다.
movie table을 메인으로 genre, actor, director table에서 movie_id가 1이라고 했을 때 1에 매핑되는 값들을 가지고 와야했다.
SELECT g.genre, m.movie_title, a.actor_name, d.director_name
FROM movie m
JOIN movie_genre mg ON m.movie_id = mg.movie_id
JOIN genre g ON mg.genre_id = g.genre_id
JOIN movie_actor ma ON m.movie_id = ma.movie_id
JOIN actor a ON ma.actor_id = a.actor_id
JOIN movie_director md ON m.movie_id = md.movie_id
JOIN director d ON md.director_id = d.director_id
WHERE m.movie_id = 1;
sql문은 이렇게 만들어놨고 값을 잘 찾아오는 것도 확인했다.
이 문제에 대해서 다양한 문서들을 봤는데 테이블마다 VO를 만드는 방법과 MyBatis의 resultMap을 이용하는 방법 등등...
내 생각에 VO를 여러 개로 만든다면 지금처럼 겨우 actor에는 actor_name 만 가지고 올거고, director에서는 director_name만 가지고 올건데... 이걸 하나하나 만들어서 movieVO랑 연결하고... 이런 건 너무 낭비라고 생각했다. 잘 사용하지 않는 테이블의 VO를 굳이 만들 필요가 있을까?🤨 개인적인 의견이다.
그러던 중 어떤 글의 댓글에서 스프링의 객체지향 특성을 이용해서 Arraylist<HaspMap<String, Object>> 를 이용해 값들을 담아오는게 좋다는 것을 봤다!!!
이게 무슨 소리인가? 싶었는데 이건 될 것 같다는 예감이 들어서 하루종일 붙잡고 씨름을 하다가 드디어 성공을 했다...... 👍
1. MovieVO
데이터베이스 테이블과 일치하게 만들어야 한다! (@Data를 이용해서 게터와 세터를 구현)
2. xml 파일
여기에서 주의해야할 점은
1. resultMap의 type이 HashMap
2. id가 select의 id와 같아야한다
3. result property="VO에서 선언한 변수명" column="필드에서 선언한 이름" 이 같아야 한다.
위의 쿼리문을 실행하면 movie_id
에 해당하는 결과 집합이 HashMap<String, Object>
형식으로 반환이 될건데 HaspMap의 키(Key)는 열(column) 이름이 되고 값(value)는 해당 열의 데이터가 된다!
예시를 들자면
HashMap<String, Object> resultMap =
String title = (String) resultMap.get("movie_title");
String genre = (String) resultMap.get("genre");
이런 식으로 데이터들이 반환되어서 필요한 것만 추출해서 사용하면 된다!!
3. MovieDAO, MovieDAOImpl
DAO에서는 SQL쿼리를 실행해서 데이터베이스에서 데이터를 추출하고 ArrayList<HashMap<String, Object>> 형식으로 반환해준다.
간단히 설명하자면 HashMap으로 movie_id=1을 해서 받아온 값이 여러 개라면 ArrayList가 그걸 목록 형식으로 만들어 준다!
ArrayList<HashMap<String, Object>> resultList =
// 첫 번째 행 데이터 추출
HashMap<String, Object> firstRow = resultList.get(0);
String movieTitle1 = (String) firstRow.get("movie_title"); // "제목"
int genre1 = (int) firstRow.get("genre"); // 0
// 두 번째 행 데이터 추출
HashMap<String, Object> secondRow = resultList.get(1);
String movieTitle2 = (String) secondRow.get("movie_title"); // "제목"
int genre2 = (int) secondRow.get("genre"); // 1
자세한 건.... Click
4. MovieService / MovieServiceImpl
데이터베이스에서 필요한 정보를 갖고오기 위해 DAO에서 만들어둔 getMovieDetails
의 메서드를 호출한다.
5. MovieController
Service에서 DAO를 통해 호출해둔 getMovieDetails()
를 이용해서 비즈니스 로직을 수행한다. 이 비즈니스 로직은 'movie_id'에 해당하는 데이터를 다중 테이블에서 가지고 온다.
6. 브라우저에서 URL 요청
'http://localhost/movie/details?movie_id=1' 을 요청
7. movie_id=1을 찾아와!
위의 과정을 반복해 다시 5. MovieController로 돌아와 service에서 movie_id = 1
에 해당하는 데이터를 "movie"라는 키로 model에 담아 jsp로 전달한다.