[개발일지1] 다중 파일 업로드 & 데이터 가져와 출력하기 & List안에 Map저장하기 꺼내기

김희주·2022년 10월 11일
2

개발일지

목록 보기
1/10
post-thumbnail

1. 구현 목표 화면


일단 내가 이 중 구현해야하는 화면은 리뷰 리스트였다.
그냥 리스트 출력이라 쉬울 줄 알고 별 생각없이 지원자 이름에 내 이름을 썼고...나는 이 리스트 때문에 5일을 집에서 소리지르고 노트북을 부여잡고 별 짓을 다하게 된다...(아찔)
그럼 이 리뷰 리스트를 어떻게 구현했는지 기록으로 남긴다.🌟

2. 맞닥트린 문제점

2-1. 하나의 리뷰 묶음에 필요한 dto의 갯수가 여러개

일단 Review라는 dto를 만들어 가져오면 되겠지?라고 생각했으나, 리뷰 dto 외에 user dto(유저의 프로필 이미지 출력), 객실 dto, 리뷰 이미지 dto까지 총 4개의 dto가 필요했다.

2-2. 어떻게 네개의 dto를 가져와서 jsp에서 for문으로 돌리지?

각가의 dto마다 list를 추출해 for문을 네 번 이용해 일일해 돌려야하나? 라고 생각하며 이것 저것 삽질을 하며 하루를 날려먹었다. 이때가 가장 큰 고민이었고, 팀원과 고민 이야기를 하다가 다른 팀원도 같은 고민을 하고 있다는 것을 알고 내가 대표로 강사님께 질문을 하기로 했다.

3. 해결

3-1. 강사님의 답변 : Map을 이용해 dto의 각각의 list들을 하나의 list로 만들어라.

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 (객실 테이블도 가져와야 하는데 이미 고민하다 리뷰테이블에 객실명 필드를 넣어버려서 바꾸기 애매해 유지했다. 다음 프로젝트 때는 객실명은 예약nojoin해 외부 테이블에서 가져와 깔끔한 테이블을 만들어야겠다) 리뷰이미지 TABLE 유저 TABLE을 map에 저장해 list에 저장해 순서를 유지했다.
그리고 내가 3일을 밤새 고민하게 했던 리뷰 이미지 여러개를 어떻게 가져오는가...

imageList = reviewImageDao.selectImageByReviewNO(conn,rs.getInt("review_no") );

이것은 리뷰 이미지 list를 다시 map에 넣는 방식으로 해결했다. 지금 보면 별거 아닌데, 나는 SQL developer에서 order by한 것이 이미지 리스트가 여러개 나와 계속 중복되는 행이 생겨 while(rs.next)를 못 쓰는 것에 대해 한참을 고민했다.
하지만 결국 해결한 나 자신...치얼스🌟

3-2. List에 저장한 Map의 객체를 어떻게 꺼내지?

여기서 헤매며 내가 아직 java 자료구조에 부족하다는 것을 느꼈다. 자바의 정석 책을 2회독이나 했는데도...이제 곧 3회독 시작해야겠다.

3-2-1. 아래는 내가 작성한 해결 코드다.

 <%	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_UserReview든 내가 원래 저장했던 dto형변환을 해줘야 한다!
간단한 건데도 헤맸다...하지만 값진 소득이었다.
자료구조를 하나하나 알아가는 맛🌟

profile
백엔드 개발자입니다 ☘

0개의 댓글