[mybatis, oracle] 날짜형식, List<Map<String,Object>> value 가져오기

Mybatis

목록 보기
5/7

문제상황

  • servlet/mybatis/oracle을 이용한 프로젝트 진행 중에
    마이페이지에서 본인의 쿠폰 목록을 조회하거나, 상품을 주문 할 때 쿠폰 리스트를 불러오는 메서드를 service에서 만들어야 했다.
    여기서 문제가 됐던 부분은

1) List<Map<String, Object>> 로 dao에서 select해서 꺼내온 객체들이 있는데, 이 중에서 created_date라는 컬럼 값이 created_date + 7일이 지나면 만료된 쿠폰이다. 그래서 쿠폰 리스트를 불러올 때 현재 시간 기준으로 만료된 쿠폰이 있다면, status=만료 로 변경하는 메서드를 하나 더 불러서 분기처리하고 사용가능한 쿠폰 목록만 불러와야 했다.

  • 일단 List<Map<String, Object>> 였기 때문에 list에서 map을 하나 씩 꺼내오고 created_date이라는 key값에 해당하는 value인 date를 받아와야했다.
    여기서, map에 해당하는 value값을 어떻게 받아와야 하는지가 첫번째 문제였다.
    • 시도해본 것
      • String date = couponList.get(i).get("CREATED_DATE") : date에 아무것도 담기지 않았음
      • 찾아보니 map을 Entry<String, Object>로 받아서 .getKey() 와 .getValue()를 사용하는 방법이 있었음
        => 해봤는데 이건 아닌것 같아서 다른 방법을 찾음. keySet()은 key값만 받아오기 때문에 안됨
        => 근데 이거 해결하려고 구글링을 했는데 map의 key를 이용해서 value를 찾기는 없고, 보통 value를 이용해서 key값을 받아오기만 많이있더라....?
      • 결국 https://jjung-a.tistory.com/19 이 블로그에서 보고 힌트를 찾음.
        String date = couponList.get(i).get("CREATED_DATE") 만으로는 받아올 수 없고, toString() 메서드를 이용해서 가져올 수 있었다.
        정답은 String date = couponList.get(i).get("CREATED_DATE").toString()
      • 근데 여기서 get(" ") ""안에 컬럼값은 console에서 나오는 문자형식(대,소문자 모두 구별)해줘야 한다.!!!!!

2) 두번째 문제. 현재 시간을 어떻게 받아올 것이고, String 으로 받아온 컬럼값을 어떻게 date로 변환해서 7일을 더해서 계산하고 이 둘을 비교하지.....?

  • 처음에 Calendar와 Date를 사용하려고 찾아보고 시도해보다가, 이 둘은 너무 예전버전이라 문제도 많고 mutable한 속성이 있어서 immutable한 LocalDate 혹은 LocalDateTime을 사용하는 것이 좋겠다해서 사용해봄.
  • 나는 쿠폰이 몇시 몇분에 create 됐는지 중요하지 않고 일자만 비교하기 위해서 모든 format설정을 (yy-MM-dd)로 값을 가져왔는데, 이걸 전혀 못받아 오더라.
    그래서 혹시나 해서 오라클에서는 yy-MM-dd HH:mm:ss.S 형식으로 되어있길래 이걸로 바꿔봤더니.... 그제서야 날짜를 받아왔다.....🫠🫠
    3) 그리고 for문으로 돌려서 분기처리 잘 해주고, 새로만든 객체에 add도 잘 되고, Sout으로 확인도 잘 됐는데, return 값만 계속 안들어오는 현상이 있어서 보니까. for문 안에 length를 <= couponList.size() -1 을 안해줘서.... 값을 못받아 왔던 것 ㅠㅠ 에러메시지라도 띄워줘라!!! 제발..!
  • 아무튼 LocalDateTime을 사용했고, LocalDateTime의 일자를 추가해주는 plusDays() 함수와 isBefore 함수를 사용하기 위해서 모든 date를 localDateTime으로 parse해서 사용했음. string으로 나온 날짜끼리 계산을 어떻게해야할지 감도안오고 생각하고 싶지 않았다.

그래서 얻은 결론

  1. List<Map<String,Object>> 에서 key값을 받아올 땐 get("")안에 컬럼명을 콘솔에 나온 그대로 적어주기
  2. 컬럼명으로 get해온 value값을 toString() 메서드로 string으로 변환해서 받아주기
  3. 대부분 콘솔에 나오는 db결과값이랑 형식 맞춰주기!!
  4. return값 안나오면 for문에 length나 다른 제한이 잘 걸려있는지 확인하기

마지막으로 완성한 코드

@RequiredArgsConstructor
public class CouponService {
	CouponDAO dao = new CouponDAOOracle();

	// 본인 쿠폰 목록 조회 (마이페이지, 주문시)
	public List<Map<String, Object>> findCouponList(String userId) throws FindException {
		List<Map<String, Object>> couponList = dao.selectCouponByUserId(userId);
		// 사용가능한 쿠폰만 담을 map list
		List<Map<String, Object>> availableCoupon = new ArrayList<Map<String, Object>>();
		
		// oracle에서 뽑아오는형식 그대로 가져와야함.. 그냥 yyyy-MM-dd나 HH:mm:ss.SSS 처럼 내가 원하는 형식으로는 안받아와짐..
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"); 
		String now = LocalDateTime.now().format(formatter);
		LocalDateTime today = LocalDateTime.parse(now, formatter);

		// dao에서 받아온 쿠폰 리스트 중에 만료된 쿠폰은 status = 2 로 변경해주는 메서드를 불러와서 처리해줌
		for (int i = 0; i <= couponList.size()-1; i++) {
			String date = couponList.get(i).get("CREATED_DATE").toString();
			LocalDateTime couponDate = LocalDateTime.parse(date, formatter);

			LocalDateTime couponExpired = couponDate.plusDays(7);
			System.out.println("couponExpiredDate : " + couponExpired);
			if (couponExpired.isBefore(today)) {
				int couponNum = Integer.parseInt(couponList.get(i).get("NUM").toString());
				System.out.println(couponNum + "번 쿠폰이 만료됨");
				modifyCouponStauts(userId, couponNum, 2);
			}

			// status = 0 인것만 새로운 객체에 담아주기
			int status = Integer.parseInt(couponList.get(i).get("STATUS").toString());
			if (status == 0) {
				Map<String, Object> coupon = couponList.get(i);
				availableCoupon.add(coupon);
			}
		}
		return availableCoupon;
	}


	// 쿠폰 status 변경
	public void modifyCouponStauts(String userId, int num, int status) throws FindException {
		CouponVo cVo = new CouponVo();
		UserVo uVo = new UserVo();
		uVo.setId(userId);
		cVo.setUser(uVo);
		cVo.setNum(num);
		cVo.setStatus(status);
		dao.updateCouponStatus(cVo);
	}
}
profile
백엔드를 공부하고 있습니다.

0개의 댓글