20221005_tue
실습내용
- 상품관리 페이지에서 조건검색기능 중 목록조회기능구현
- 날짜 기능 구현
: 한달 전날짜와 오늘날짜를 세팅해야한다-> 자바로 구현
: 자바로 날짜를 세팅하는 방법이 여러가지가 있다.
: Date,Calendar(가장쉬움),LocalDateTime(실무에서 최근 많이 사용)
: 이전 상품등록에서 조회할 때 사용하던 조회기능을 그대로 가져와서 컨트롤러에서 적용하여 사용하면 된다. 단, 사용중인 것만 조회하는 것이아니라 모든 상품의 카테고리 목록조회문을 사용하도록 주의해야한다.
: 이후, 상품관리 html에서 컨트롤러에서 뿌려진 데이터 가져와서 사용하면된다.
- adminController
//상품관리 클릭시 @GetMapping("/itemManage") public String itemManage(Model model, ItemVO itemVO) { // 등록된 상품목록조회 model.addAttribute("regItemList", itemService.selectRegItemList()); // 카테고리 목록조회 model.addAttribute("cateListAll",adminService.cateListAll()); return "content/admin/item_manage"; }
- item_manage.html
<td> 카테고리 </td> <td colspan="2"> <select > <option>전체</option> <option th:each="cateList : ${cateListAll}" th:text="${cateList.cateName}"></option> </select> </td>
날짜기능 구현
오늘/한달전 날짜 세팅하기
- 패키지와 컨트롤러 파일 생성
Calendar
문법 사용하기@RestController
어노테이션 사용nowDate
리턴값이 페이지이동은 안가고 데이터를 그대로 보내줘서 화면에 띄워진다.날짜 세팅 방법
: Calendar 사용
: 생성방법은 조금 다르다.
: 왜? 객체가 하나만 있어도 돌려사용가능하기때문
: 디자인패턴 : 싱글톤 패턴
: 오늘의 년월일 데이터를 가져올 때, 반드시 월은 +1을 해줘야한다.
: 그 이유는 기본값이 0 이기때문이다.
package Kh.study.shop.date;
@RestController
@RequestMapping("/date")
public class DateController {
// 현재 날짜
@GetMapping("/test1")
public String test1() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int date = cal.get(Calendar.DATE);
//삼항연산자) 0000-00-00 날짜형식에맞게 만들기
String monthStr = month/10 == 0 ? "0" + month: month + "" ;
String dateStr = date/10 == 0 ? "0" + date: date + "" ;
String nowDate = year + "-" + monthStr + "-" + dateStr;
System.out.println("@@@@@@@@@@@@@@@@@@@@@@ "+nowDate);//2022-10-05
return nowDate;
}
}
package Kh.study.shop.config;
import java.util.Calendar;
public class ShopDateUtil {
//오늘 날짜 구하기 (문자열형태 ToString으로 리턴하는 메소드)
// static을 사용하면,
//많이 호출할 객체들을 굳이 객체만들지않고도 클래스명을 호출하여 사용할 수 있어 편이하다.
public static String getNowDateToString() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH)+1;
int date = cal.get(Calendar.DATE);
String monthStr = month/10 == 0 ? "0" + month: month + "" ;
String dateStr = date/10 == 0 ? "0" + date: date + "" ;
String nowDate = year + "" + monthStr + "" + dateStr;//"20221005"
return nowDate;
}
//오늘날짜를 문자열로 리턴 + 포맷지정
//ex) 20221005,2022-10-05, 22/10/05...
// 사용방법
// 만약 getNowDateToString("-"); 호출하면, 2022-10-05 형식으로 사용가능하다!
public static String getNowDateToString(String format) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH)+1;
int date = cal.get(Calendar.DATE);
String monthStr = month/10 == 0 ? "0" + month: month + "" ;
String dateStr = date/10 == 0 ? "0" + date: date + "" ;
String nowDate = year + format + monthStr + format + dateStr;
return nowDate;
}
//한달 전 날짜 구하기 (문자열형태 ToString으로 리턴하는 메소드)
public static String getMonthAgoDateToString(String format) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int date = cal.get(Calendar.DATE);
String monthStr = month/10 == 0 ? "0" + month: month + "" ;
String dateStr = date/10 == 0 ? "0" + date: date + "" ;
String nowDate = year + format + monthStr + format + dateStr;//"20221005"
return nowDate;
}
}
상품관리 페이지에서 조건검색기능 사용시
- 위의 date컨트롤러에서 만든 객체를 사용하여 getter로 호출하여 현재날짜와 한달전날짜를 기본값으로 받아와 사용하도록 한다.
- 상품관리 페이지이동
- itemVO 매개변수로 넘기면(커맨드객체로 사용하겠다는 뜻) 오류발생
- itemStock은 int 로 정수형이기때문에 itemVO로 매개변수를 넘기면 검색버튼누르면
- 재고에 아무값도 넣지 않으면 빈값(null아님)으로 넘어가기때문에
- 빈값은 문자열로 인식하여 오류가 발생한다.
- 보내야하는 데이터가 무엇인지 명확히알고 itemVO라는 매개변수로 넘기지 않도록 주의할 것!!
매개변수 커맨드 객체 사용시 주의할점!
- html에 toDate와 fromDate 라는 변수명이 새로 생겼기 때문에 이를 어떻게 데이터를 받을것인가?
- 커맨드객체인 itemVO를 사용하면, itemVO에 있는 데이터 이외의 추가로 생성한 데이터들은 못받는데
- 단, Map 에도 단점이 있다.
- 단점① 잘못된 데이터나 오타가 나도 그대로 들고오기 때문에 거를 수 없다.
- 단점② 자동 형변환이 안 된다.
- Map을 쓰면 데이터를 추가로 만들어진 것들도 모두 받아올 수 있다.
- map에 key값과 value값의 각각 데이터를 다음과 같이 넣을수도 있다.
paramMap.put("itemName", "java");
- map의 itemName 이라는 이름을 가진 key 값의 value를 가져온다
- 처음에는 null 값이 뜬다.
- 상품관리를 클릭하여 관리자메뉴에서 페이지이동시,
:기존에 있던 목록조회와 검색조건기능을 모두 출력하는 기능은 컨트롤러에서 get매핑으로 되어있었다.
:이때, 같은 화면에 있는 조건검색기능도 검색버튼을 클릭하여 데이터를 던져주려면 post매핑을 사용해야한다.
:그런데 이때도 경로가 똑같이 상품관리 페이지이기때문에 request매핑으로 변경하여 사용하면 된다.
package Kh.study.shop.admin.controller;
@Controller
@RequestMapping("/admin")
public class AdminController {
@Resource(name = "adminService")
private AdminService adminService;
@Resource(name = "memberService")
private MemberService memberService;
@Resource(name = "itemService")
private ItemService itemService;
@RequestMapping("/itemManage")// para (파라매터) : 매개변수로받아오는데이터
public String itemManage(@RequestParam Map<String, String> paramMap,Model model) {
System.out.println("상품명 : " + paramMap.get("itemName"));
System.out.println("카테고리코드 : " + paramMap.get("cateCode"));
System.out.println("재고 : " + paramMap.get("itemStock"));
System.out.println("fromDate : " + paramMap.get("fromDate"));
System.out.println("toDate : " + paramMap.get("toDate"));
System.out.println("상품상태 : " + paramMap.get("itemStatus"));
// 등록된 상품목록조회
model.addAttribute("regItemList", itemService.selectRegItemList(paramMap));
// 카테고리 목록조회
model.addAttribute("cateListAll",adminService.cateListAll());
//오늘날짜
String nowDate = ShopDateUtil.getNowDateToString("-");
//한달전 날짜
String aMonthAgoDate = ShopDateUtil.getMonthAgoDateToString(("-"));
model.addAttribute("nowDate",nowDate);
model.addAttribute("aMonthAgoDate",aMonthAgoDate);
return "content/admin/item_manage";
}
}
- 위 컨트롤러에서 paraMap으로 불러오는 key값의 value값 데이터를 가져오려면, html파일에서 해당하는 값들을 데이터로 불러와야한다.그러려면 해당 값들을 잘 던져줘야하기때문에 파일에 가서 name값이나 value값들을 설정해줘야한다.
- 조건검색기능에서 검색 버튼을 클릭시, form태그사용하여 submit으로 넘겨준다.
- form태그로 데이터 넘겨주려면 반드시 name값 설정을 vo변수명과 동일하게 해줘야한다.
- 단, form태그에서 경로는 상품관리페이지와 이동경로가 동일하다.
-><form th:action="@{/admin/itemManage}" method="post">
- 카테고리 목록조회에서
- '전체'값: 쿼리실행시 빈값("")이면 cateCode값이 쿼리문 조건절에서 생략되기때문에 전체 목록조회가 된다 ->
<option value="">전체</option>
- 타임리프밸류를 사용하는이유는? 변수명으로 데이터 들고 가기위해서
->
<td><input type="date" name="fromDate" th:value="${aMonthAgoDate}"></td>
<td><input type="date" name="toDate" th:value="${nowDate}"></td>
Map 사용하는 이유는?
- 기존 itemVO에는 없던 변수명인 fromDate와 toDate라는 값을 name으로 설정하여 검색버튼클릭시 데이터를 넘겨주려할 때나, value값을 설정하여 화면에 띄워주려고 할때
: 기존에 없는 변수명을 임의로 추가하여도 map에 데이터를 넣으면 꺼내어서 언제든 사용하기 편이하기 때문이다.
cf) name값은 아파트 호수명이고 value값은 우편물내용물이다.그래서 itemStatus라는 호수명에 판매중 이라는 우편내용물 데이터값을 전달한 것과 같다.
: mapper쿼리문에서 decode함수를 사용하여 itemStatus를 한글로 변경했기때문에 영어로된 변수명이 아닌 변경한 한글값으로 넣어야 오류가 발생하지 않는다!
-><input type="radio" name="itemStatus" value="" th:text="전체" checked="checked">
<input type="radio" name="itemStatus" value="판매중" th:text="판매중">
<input type="radio" name="itemStatus" value="매진" th:text="매진">
<div layout:fragment="content">
<div class="row">
<div class="col">
<h1>상품관리페이지</h1>
<div class="row"><!-- 좌우측화면 담고있는 화면 -->
<!-- 검색 -->
<form th:action="@{/admin/itemManage}" method="post">
<div class="col-12 mb-5">
<div>
<table class="table table-striped table-hover">
<tr>
<td> 카테고리 </td>
<td colspan="2">
<select name="cateCode">
<!-- '전체'값: 쿼리실행시 빈값이면 카테코드조건절이 실행이 안되기때문에 모든 목록이 조회된다 -->
<option value="">전체</option>
<option th:each="cateList : ${cateListAll}" th:text="${cateList.cateName}"></option>
</select>
</td>
<td>상품명</td>
<td><input type="text" name="itemName"> </td>
<td>재고</td>
<td><input type="number" name="itemStock"> </td>
</tr>
<tr>
<td>등록일</td><!-- 타임리프밸류를 사용하는이유는? 변수명으로 데이터 들고갈때 -->
<td><input type="date" name="fromDate" th:value="${aMonthAgoDate}"></td>
<td><input type="date" name="toDate" th:value="${nowDate}"></td>
<td>상태</td>
<td colspan="3"><!-- '전체'값 : 쿼리실행시 빈값이면 카테코드조건절이 실행이 안되기때문에 모든 목록이 조회된다 -->
<input type="radio" name="itemStatus" value="" th:text="전체" checked="checked">
<input type="radio" name="itemStatus" value="판매중" th:text="판매중">
<input type="radio" name="itemStatus" value="매진" th:text="매진">
</td>
</tr>
</table>
</div>
<div align="center">
<button class="btn btn-outline-secondary" type="submit">검색</button>
</div>
</div>
</form>
<설명>
parameterType="hashMap"
추가 사용해서 select 쿼리문 작성하기
: itemVO클래스에는 선언되지 않던 fromDate,toDate 데이터값을 map을 만들어 데이터값을 넣어서 사용해준다.
: if문을 사용하여 각각의 검색조건에 해당하는 where조건절에 걸어준다.
if문은 해당하는 컬럼값이 null값이 아니면서 빈값이 아니어야 실행하도록 해준다.
<select id="selectRegItemList" resultMap="item" parameterType="hashMap">
SELECT
ITEM_CODE
,ITEM_NAME
,ITEM_PRICE
,to_char(REG_DATE, 'YYYY-MM-DD') REG_DATE
,ITEM_STOCK
,SHOP_ITEM.CATE_CODE
,CATE_NAME
,DECODE(ITEM_STATUS,'ON_SALE','판매중','매진') ITEM_STATUS
FROM SHOP_ITEM,ITEM_CATECGORY
WHERE SHOP_ITEM.CATE_CODE = ITEM_CATECGORY.CATE_CODE
<if test="cateCode != null and !cateCode.equals('') ">
AND SHOP_ITEM.CATE_CODE = #{cateCode}
</if>
<if test="itemName != null and !itemName.equals('')">
AND UPPER(ITEM_NAME) LIKE UPPER('%'||#{itemName}||'%')
</if>
<if test="itemStock != null and !itemStock.equals('')">
AND ITEM_STOCK <= #{itemStock}
</if>
<!-- <if test=" != null and ">
AND TO_CHAR(REG_DATE,'YYYY-DD-MM') >= '#{fromDate}'
AND TO_CHAR(REG_DATE,'YYYY-DD-MM') <= '#{toDate}'
</if> -->
<if test="itemStatus != null and !itemStatus.equals('')">
AND ITEM_STATUS = #{itemStatus}
</if>
</select>
- service와 serviceImpl에 상품관리페이지이동시의 컨트롤러에서 사용하는 모든 상품목록조회쿼리문을 (등록된 상품목록조회가 아님) 수정해야한다.
- 왜? 새로운 데이터 fromDate와 toDate값을 넣어줘야하기때문이다.
- 이때 모든데이터를 넣어서 사용가능한 map을 이용하기위해 매개변수로 넣어준다.
List<ItemVO> selectRegItemList(Map<String, String> paramMap);
@Override
public List<ItemVO> selectRegItemList(Map<String, String> paramMap) {
return sqlSession.selectList("itemMapper.selectRegItemList",paramMap);
}
아나콘다 설치하기
: 오른쪽 상단 다운로드 d드라이브 dev폴더에 설치한다.
https://www.anaconda.com/products/distribution
왜 설치하는가?
java의 경우, 사용하려면 아래와 같이 프로그램을 설치해야한다.
jdk + 이클립스(sts) : 원하는 기능을 구현하기위해 jar,lib 등 다운로드 및 추가..
파이썬도 마찬가지로 아래와 같은 프로그램을 설치해야 사용가능하다
python + pycharm
anoconda..
다운로드 후 설치하면서, next계속 누르다가 install 하면 완료
로딩 완료후, 마지막 두 칸 체크박스 해제후 완료한다
윈도우에서 아나콘다3 폴더 클릭후, 크롬으로 열면 된다.
새로운 폴더 생성 후 체크한다
rename 왼쪽 상단 버튼 클릭 후 다른이름으로 저장한다.
실제 pc폴더에서 연동된 파일명을 볼 수 있다.
새로 생성한 파일 클릭 하여 들어간다
오른쪽 상단 new 클릭시 파이선을 선택하면 코드실행가능하다.
컨트롤 + 엔터 누르면 코드가 실행되어 값이 나타난다.
<참고> https://bio-info.tistory.com/15
주피터 노트북의 테마를 다운로드 -> 아나콘다3의 프롬프트에 입력한다.
pip install jupyterthemes
다운로드 받은 테마목차보기 : jt -l
(jt띄우고 하이픈 영어소문자 엘 입력)
테마 배경색상 적용 : jt -t(jt띄우고) 테마명
: monokai 나 onedork를 적용하면 블랙화면으로 보여진다.
새로고침하여 블랙화면으로 변경되지 않으면, 다시 윈도우키를 눌러 주피터노트북을 클릭하여 다시 창을 열면 변경이된다.
윈도우키 누르면 왼쪽하단 화면처럼 창이 뜨는데 그 중 주피터 노트북 클릭하기
테마 폰트 적용: jt -t 테마명 -fs 18 -ofs 18 -nfs 18
: 테마명 뒤에 한칸 띄우고 -T를 붙이면 위에 메뉴상단도 같이 뜬다
- fs : 코드의 폰트사이즈
- ofs : 실행 결과의 폰트사이즈(output font size)
- nfs : 메뉴 폰트사이즈 (menu font size)
커서 밖으로 하는 경우 :esc 키 누르기
커서가 밖에 있을 경우
a : 현재 위치의 위에 코드를 작성할 수 있는 공간을 추가
b : 현재 위치의 아래에 코드를 작성할 수 있는 공간을 추가
단축키 y : 코드입력
단축기 m : markdown 마크다운(주석) 가능
ctrl + enter : 실행활성화 종료되어 저장가능
마크다운_한줄개행: 마크다운에서 한 줄개행을 위해서 스페이스바를 두번 누른 후 엔터를 친다.