일단 내가 이 중 구현해야하는 화면은 리뷰 리스트였다.
그냥 리스트 출력이라 쉬울 줄 알고 별 생각없이 지원자 이름에 내 이름을 썼고...나는 이 리스트 때문에 5일을 집에서 소리지르고 노트북을 부여잡고 별 짓을 다하게 된다...(아찔)
그럼 이 리뷰 리스트를 어떻게 구현했는지 기록으로 남긴다.🌟
일단 Review
라는 dto
를 만들어 가져오면 되겠지?라고 생각했으나, 리뷰 dto 외에 user dto
(유저의 프로필 이미지 출력), 객실 dto
, 리뷰 이미지 dto
까지 총 4개의 dto가 필요했다.
각가의 dto마다 list를 추출해 for문을 네 번 이용해 일일해 돌려
야하나? 라고 생각하며 이것 저것 삽질을 하며 하루를 날려먹었다. 이때가 가장 큰 고민이었고, 팀원과 고민 이야기를 하다가 다른 팀원도 같은 고민을 하고 있다는 것을 알고 내가 대표로 강사님께 질문을 하기로 했다.
Map은 저장순서가 없기 때문에 처음에는 뭔 소리지? 했으나 map을 결국 마지막으로 감싸는 것은 list라는 것을 깨닫고 바로 코드 짜기에 돌입했다!
아래는 내가 ReviewDaoImpl
에서 완성한 코드다.
@Override
public List<Map<String, Object>> selectReviewsByDateByHotelNo(Connection conn, int hotel_no) {
//SQL작성
String sql = "";
sql += "select s.user_name, s.user_phone, s.user_pw, s.user_pic, t.pay_no, t.review_no, t.hotel_no, t.booking_no, t.user_email, t.review_content, t.review_score, t.user_no, t.room_type, t.review_date, t.reviewimage_no, t.originname, t.storedname from";
sql += " (select r.pay_no, r.review_no, r.hotel_no, r.booking_no, r.user_email, r.review_content, r.review_score, r.user_no, r.room_type, r.review_date, i.reviewimage_no, i.originname, i.storedname from review r";
sql += " join reviewimage i";
sql += " on r.review_no = i.review_no) t";
sql += " join semi_user s";
sql += " on t.user_no = s.user_no";
sql += " where hotel_no = ?";
sql += " order by t.review_date desc";
//결과 저장할 List
List<Map<String, Object>> resultlist = new ArrayList<>();
Map<String, Object> map;
List<ReviewImage> imageList;
ReviewImageDao reviewImageDao = new ReviewImageDaoImpl();
try {
ps = conn.prepareStatement(sql); //SQL수행 객체
ps.setInt(1, hotel_no);
rs = ps.executeQuery(); //SQL수행 및 결과 집합 저장
//조회 결과 처리
while(rs.next()) {
//결과값 저장 객체
Review r = new Review();
ReviewImage ri = new ReviewImage();
Semi_User u = new Semi_User();
//결과값 한 행씩 처리
r.setPay_no(rs.getInt("pay_no"));
r.setReview_no(rs.getInt("review_no"));
//System.out.println(rs.getInt("review_no"));
r.setHotel_no(rs.getInt("hotel_no"));
r.setBooking_no(rs.getInt("booking_no"));
r.setUser_email(rs.getString("user_email"));
r.setReview_content(rs.getString("review_content"));
r.setReview_score(rs.getInt("review_score"));
r.setUser_no(rs.getInt("user_no"));
r.setRoom_type(rs.getString("room_type"));
String dateStr = rs.getString("review_date");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.mm.dd hh:mm");
Date date = formatter.parse(dateStr);
r.setReview_date(date);
//결과값 한 행씩 처리
// ri.setReviewimage_no( rs.getInt("reviewimage_no") );
// ri.setReview_no( rs.getInt("review_no") );
// ri.setOriginname( rs.getString("originname") );
// ri.setStoredname( rs.getString("storedname") );
imageList = reviewImageDao.selectImageByReviewNO(conn,rs.getInt("review_no") );
//결과값 한 행씩 처리
u.setUser_no(rs.getInt("user_no"));
u.setUser_name(rs.getString("user_name"));
u.setUser_email(rs.getString("user_email"));
u.setUser_phone(rs.getString("user_phone"));
u.setUser_pw(rs.getString("user_pw"));
u.setUser_pic(rs.getString("user_pic"));
//넣을 map 생성
map = new HashMap<>();
map.put("r", r);
map.put("ri", imageList);
map.put("u", u);
//list에 map 넣기
resultlist.add(map);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//DB객체 닫기
JDBCTemplate.close(rs);
JDBCTemplate.close(ps);
}
//최종 결과 반환
return resultlist;
}
겁나 길지만, 하나하나 뜯어보면 결국 리뷰 TABlE
(객실 테이블도 가져와야 하는데 이미 고민하다 리뷰테이블에 객실명 필드를 넣어버려서 바꾸기 애매해 유지했다. 다음 프로젝트 때는 객실명은 예약no
로 join
해 외부 테이블에서 가져와 깔끔한 테이블을 만들어야겠다) 리뷰이미지 TABLE
유저 TABLE
을 map에 저장해 list에 저장해 순서를 유지했다.
그리고 내가 3일을 밤새 고민하게 했던 리뷰 이미지 여러개를 어떻게 가져오는가...
imageList = reviewImageDao.selectImageByReviewNO(conn,rs.getInt("review_no") );
이것은 리뷰 이미지 list
를 다시 map
에 넣는 방식으로 해결했다. 지금 보면 별거 아닌데, 나는 SQL developer
에서 order by
한 것이 이미지 리스트가 여러개 나와 계속 중복되는 행이 생겨 while(rs.next)
를 못 쓰는 것에 대해 한참을 고민했다.
하지만 결국 해결한 나 자신...치얼스🌟
여기서 헤매며 내가 아직 java 자료구조에 부족하다는 것을 느꼈다. 자바의 정석
책을 2회독이나 했는데도...이제 곧 3회독 시작해야겠다.
<% for(int i=0; i< list.size(); i++) { %>
<ul class="reviewList">
<li>
<div class="profile">
<img src="/upload/<%= ((Semi_User) list.get(i).get("u")).getUser_pic() %>" alt="이미지 아님" width="50" height="50">
<div class="reviewInfo">
<div><%=((Review)list.get(i).get("r")).getReview_score() %>점</div>
<div>
<span><%= ((Semi_User) list.get(i).get("u")).getUser_email() %></span><span><%= sf.format( ((Review)list.get(i).get("r")).getReview_date() ) %></span><span><%=((Review)list.get(i).get("r")).getRoom_type() %></span>
</div>
</div>
</div>
<div class="reviewContent">
<div class="imgArea">
<% for(int j=0; j < ((List<ReviewImage>) list.get(i).get("ri")).size() ; j++) { %>
<img src="/upload/<%=((List<ReviewImage>) list.get(i).get("ri")).get(j).getStoredname() %>" alt="이미지 아님" width="50" height="50">
<% } %>
</div>
<p>
<%=((Review)list.get(i).get("r")).getReview_content() %>
</p>
</div>
</li>
</ul>
<% } %>
보면 알겠지만
<%= ((Semi_User) list.get(i).get("u")).getUser_email() %>
뭐를 하나 꺼낼 때 마다 바로 get원하는 데이터
으로 꺼내서 접근하는게 아니다. 애초에 Map<String, Object>
로 만들었기에, 꺼낼 때 객체들의 형태는 Object
다. 그러므로 이를 다시 Semi_User
든 Review
든 내가 원래 저장했던 dto
로 형변환
을 해줘야 한다!
간단한 건데도 헤맸다...하지만 값진 소득이었다.
자료구조를 하나하나 알아가는 맛🌟