mjeongriver
article thumbnail
Published 2023. 2. 15. 18:04
day85-spring boot TIL/Spring boot

1. 어제 이어서 mySQL에서 테이블 생성

<java />
CREATE TABLE PRODUCT( PROD_ID INT PRIMARY KEY AUTO_INCREMENT, ## PK 자동증가값 PROD_REGDATE TIMESTAMP DEFAULT NOW(), ## 등록일 기본값 시간형 PROD_ENDDATE VARCHAR(20), ## 판매종료일 문자형 시간 PROD_CATEGORY VARCHAR(20), ## 카테고리 키 PROD_WRITER VARCHAR(20), ## 작성자 FK PROD_NAME VARCHAR(300), ## 상품명 PROD_PRICE INT NOT NULL, ## 가격 PROD_COUNT INT NOT NULL, ## 재고 PROD_DISCOUNT INT DEFAULT 0, ## 할인율 기본값 숫자 0 PROD_PURCHASE_YN CHAR(1) DEFAULT 'N' CHECK (PROD_PURCHASE_YN IN ('Y', 'N')), ##체크제약 PROD_CONTENT VARCHAR(5000), ##내용 PROD_COMMENT VARCHAR(5000) ##메모 );

 

2. VO 생성, productReg 수정, productController 수정

 

 

- productVO 생성, 2~5번째 사진처럼 productReg 수정

- 다음에 productController에 registForm 추가

 

* productVO, productController

더보기

- productVO: 처음에 선언 하고, 어노테이션은 후에 추가로 → 그리고 컨트롤러에서 @valid 처리해줄 것!

<java />
package com.coding404.myweb.command; import java.time.LocalDateTime; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @Builder public class ProductVO { /* * @NotNull - null값만 허용하지 않음(wrapper의 Integer, Long, String 등등) * @NotBlack - 좀 더 강력한 제약 조건, null값과 공백을 허용하지 않음(String에만 적용) * @Pattern - 정규 표현식에 맞는 문자열을 정의할 수 있음(String에만 적용) * @NotEmpty - null값을 허용하지 않음(Array, list에 적용) * @Email - 이메일 형식 검증(공백은 통과) * @Min - 최소값 * @Max - 최대값 */ private int prod_id; private LocalDateTime prod_regdate; @NotBlank(message = "공백일 수 없습니다.") @Pattern(regexp = "[0-9]{4}-[0-9]{2}-[0-9]{2}") private String prod_enddate; private String prod_category; @NotBlank(message = "공백일 수 없습니다.") private String prod_writer; @NotBlank(message = "공백일 수 없습니다.") private String prod_name; @Min(value = 0, message = "0원 이상이어야 합니다.") private int prod_price; private int prod_count; private int prod_discount; private String prod_purchase_yn; private String prod_content; private String prod_comment; }

 

- productController: 등록 요청 추가

<java />
package com.coding404.myweb.controller; import javax.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.coding404.myweb.command.ProductVO; @Controller @RequestMapping("/product") public class ProductController { @GetMapping("/productReg") public String reg() { return "product/productReg"; } @GetMapping("/productList") public String list() { return "product/productList"; } @GetMapping("/productDetail") public String detail() { return "product/productDetail"; } //등록 요청 @PostMapping("/registForm") public String registForm(/*@Valid*/ ProductVO vo) { return "redirect:/product/productList"; //목록으로 } }

 

 

* 순서

- 매퍼.xml에 매퍼 선언하고 매퍼.java에는 mapper 어노테이션 붙이기

- 서비스 임플에 @Service("productService") 얘 선언해줄 것

- 컨트롤러에서 연결 해줄 것!

<java />
@Autowired @Qualifier("productService") private ProductService productService;

- 서비스랑 매퍼.java에 public int regist(ProductVO vo);  선언해주기

- impl 오버라이딩 한 후에 autowired 매퍼

<java />
@Autowired private ProductMapper productMapper;

- 매퍼.xml에 insert구문 넣기

- 그 다음에 컨트롤러 int result = productService.regist(vo);추가하고 위에 매개변수에 RedirectAttributes ra 추가

(필수는 아니지만 상황에 따라서 필요할 수 있습니다)

<java />
@PostMapping("/registForm") public String registForm(/*@Valid*/ ProductVO vo, RedirectAttributes ra) { int result = productService.regist(vo); String msg = result == 1 ? "정상 입력되었습니다." : "등록에 실패하였습니다"; ra.addFlashAttribute("msg", msg); return "redirect:/product/productList"; //목록으로 }

 

- 임플에서 return값에 productMapper.regist(vo);

- 다시 화면 productList 돌아와서 스크립트 태그 추가

 

 

- 컨트롤러에서 productList 수정

 

 

- 조회

 

하고 나서 writer가 admin인 사람만 읽을 수 있음(컨트롤러에서 user_id를 admin이라고 지정했음)

 

- 상세 보기: 컨트롤러에서 detail 부분은 자율적 숙제입니다.

 

첫번째 사진은 productList.html

 

- detail에서 저장 누르면 update, 삭제는 post 방식으로 

 

 

* ProductMapper.xml, ProductMapper.java, productservice, productServiceImpl, productController

더보기

- ProductMapper.xml

<java />
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.coding404.myweb.product.service.ProductMapper"> <insert id="regist" parameterType="ProductVO"> <!-- vo 참고 --> insert into PRODUCT(prod_enddate, prod_writer, prod_name, prod_price, prod_count, prod_discount, prod_purchase_yn, prod_content, prod_comment ) values( #{prod_enddate}, #{prod_writer}, #{prod_name}, #{prod_price}, #{prod_count}, #{prod_discount}, #{prod_purchase_yn}, #{prod_content}, #{prod_comment}) </insert> <select id="getList" resultType="ProductVO"> select * from PRODUCT where prod_writer = #{user_id} order by prod_id desc </select> </mapper>

 

- ProductMapper.java

<java />
package com.coding404.myweb.product.service; import java.util.ArrayList; import org.apache.ibatis.annotations.Mapper; import com.coding404.myweb.command.ProductVO; @Mapper //선언 꼭 해줄 것 public interface ProductMapper { public int regist(ProductVO vo); public ArrayList<ProductVO> getList(String user_id); }

 

- productservice

<java />
package com.coding404.myweb.product.service; import java.util.ArrayList; import com.coding404.myweb.command.ProductVO; public interface ProductService { public int regist(ProductVO vo); public ArrayList<ProductVO> getList(String user_id); //조회: 특정 회원 정보만 조회함 }

 

- productServiceImpl

<java />
package com.coding404.myweb.product.service; import java.util.ArrayList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.coding404.myweb.command.ProductVO; @Service("productService") public class ProductServiceImpl implements ProductService{ @Autowired private ProductMapper productMapper; @Override public int regist(ProductVO vo) { return productMapper.regist(vo); } @Override public ArrayList<ProductVO> getList(String user_id) { return productMapper.getList(user_id); } }

 

- productController

<java />
package com.coding404.myweb.controller; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.coding404.myweb.command.ProductVO; import com.coding404.myweb.product.service.ProductService; @Controller @RequestMapping("/product") public class ProductController { @Autowired @Qualifier("productService") private ProductService productService; @GetMapping("/productReg") public String reg() { return "product/productReg"; } @GetMapping("/productList") public String list(HttpSession session, Model model) { /*, HttpServletRequest request */ //프로세스 //admin이라고 가정 session.setAttribute("user_id", "admin"); //로그인 한 회뭔만 조회 String user_id = (String)session.getAttribute("user_id"); ArrayList<ProductVO> list = productService.getList(user_id); model.addAttribute("list", list); return "product/productList"; } @GetMapping("/productDetail") public String detail() { return "product/productDetail"; } //등록 요청 @PostMapping("/registForm") public String registForm(/*@Valid*/ ProductVO vo, RedirectAttributes ra) { int result = productService.regist(vo); String msg = result == 1 ? "정상 입력되었습니다." : "등록에 실패하였습니다"; ra.addFlashAttribute("msg", msg); return "redirect:/product/productList"; //목록으로 } }

 

2. 페이징

* 순서

1) 첫번째 작업: 10개 페이지 화면에 보여지게 만들기

 

 

- testCode 작성한 후 run as → JUnit : 돌리고 나서는 주석 처리 해둘 것!(나도 모르게 돌리면 계속 생성되니까)

- util 패키지 만들고 criteria 생성: SQL에 전달할 page, amount을 가지고 다니는 클래스

- 그 다음에 productMapper.java

 

이렇게 하면 실행이 안됨(단일값 String만 넣어서 사용했었음) 2개는 마이바티스가 인식할 수 없음(매개변수가 2개 이상일 때는 param 어노테이션 사용) 3번째 사진 참고할 것!

 

- testcode에서 잘 굴러가는지 확인(test02)

 

여기 누르면 에러코드 확인이 가능합니다.

 

- 서비스, 서비스impl에서 cri 추가

 

 

- 컨트롤러 수정

 

 

- 결과: 화면에서 10개의 페이지만 나옴

 

 

* TestCode, Criteria

더보기

- TestCode

<java />
package com.coding404.myweb; import java.util.ArrayList; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import com.coding404.myweb.command.ProductVO; import com.coding404.myweb.product.service.ProductMapper; import com.coding404.myweb.util.Criteria; @SpringBootTest public class TestCode { @Autowired ProductMapper productMapper; // @Test // public void testCode01() { // for(int i=1; i<=300; i++) { // // ProductVO vo = ProductVO.builder().prod_enddate("2023-02-15") // .prod_writer("admin") // .prod_name("test" + i) // .prod_price(i * 1000) // .prod_count(i * 100) // .prod_discount(i) // .prod_purchase_yn("N") // .prod_content("컨텐츠" + i) // .prod_comment("hello world!") // .build(); // // productMapper.regist(vo); // } // } @Test public void testCode02() { Criteria cri = new Criteria(1, 10); ArrayList<ProductVO> list = productMapper.getList("admin", cri); System.out.println(list.toString()); } }

 

- Criteria

<java />
package com.coding404.myweb.util; import lombok.Data; @Data public class Criteria { //SQL에 전달할 page, amount을 가지고 다니는 클래스 private int page; //조회하는 페이지 번호 private int amount; //데이터 갯수 public Criteria() { this.page = 1; this.amount = 10; } //생성자 생성 public Criteria(int page, int amount) { super(); this.page = page; this.amount = amount; } //앞쪽에 들어갈 변수 public int getPageStart() { return (page - 1) * amount; } }

 

2) 2번째 작업(startPage, endPage, realEnd...)

- PageVO 생성

 

제네릭 알아야 함! 검색할 때도 사용이 가능함

 

더보기

- PageVO

<java />
package com.coding404.myweb.util; import java.util.ArrayList; import lombok.Data; @Data public class PageVO { //페이지 네이션을 계산하는 클래스 private int start; //첫 페이지 번호 private int end; //끝 페이지 번호 private boolean prev; //이전 버튼 private boolean next; //다음 버튼 private int page; //조회하는 번호 private int amount; //데이터 갯수 private int total; //전체 게시글 수 private int realEnd; //실제 끝 번호 private int pageCount = 10; //페이지 네이션 갯수 private Criteria cri; private ArrayList<Integer> pageList; //화면에 반복시킬 페이지 번호 //생성자 public PageVO(Criteria cri, int total) { this.page = cri.getPage(); this.amount = cri.getAmount(); this.total = total; this.cri = cri; //끝 페이지 번호(int)Math.ceil(조회 하는 페이지 번호 / 페이지 네이션 갯수) * 페이지 네이션 갯수 this.end = (int)Math.ceil( this.page / (double)pageCount ) * pageCount; //시작 페이지 번호: 끝페이지 번호 - 페이지 네이션 갯수 + 1 this.start = this.end - pageCount + 1; //실제 끝 번호 //데이터가 141개 라면 → 마지막 페이지 번호는 15번 //(int)Math.ceil(전체 게시글 수 / 데이터 갯수) this.realEnd = (int)Math.ceil( this.total / (double)this.amount ); //실제 끝 번호 재계산 //데이터 141개 라면 → 1~10 end=10번 realEnd=15, // 11~20 end=20 realEnd=15 this.end = this.end > this.realEnd ? this.realEnd : this.end; //이전 버튼 활성화 //start는 1, 11, 21.. this.prev = this.start > 1; //다음 버튼 활성화 //데이터 141개 라면 → 1~10 end=10번 realEnd=15, 이 때 true this.next = this.realEnd > this.end; //화면에서 반복시킬 페이지 데이터 this.pageList = new ArrayList<>(); for(int i = this.start; i <= this.end; i++) { pageList.add(i); } } }

 

- 컨트롤러에서 pageVO 생성

 

위에 1,2,3번에서 6번처럼 String user_id 모두 수정 할 것!

 

- pageList에서 page 부분 수정

 

 

더보기

- pageList: th:href에서 th 안 썼을 때 안넘어가는 오류 생김. 꼭 빠지지 말고 쓸 것!

<java />
<div class="page"> <ul> <li> <a th:href="@{productList(page=1, amount=${pageVO.amount} )}"> <i class="fa fa-angle-double-left" aria-hidden="true"></i> </a> </li> <!-- 이전 버튼 --> <th:block th:if="${pageVO.prev}"> <li style="margin-right: 5px;"> <a th:href="@{productList(page=${pageVO.start -1}, amount=${pageVO.amount} )}"><i class="fa fa-angle-left" aria-hidden="true"></i></a> </li> </th:block> <!-- 1~10번까지 그려짐, on이 들어가있으면 활성화, 이걸 하면 2번, 3번 누를 때 넘어가야함! --> <th:block th:each="page : ${pageVO.pageList}"> <li th:class="${page == pageVO.page ? 'on' : ''}"><a th:href="@{productList(page=${page}, amount=${pageVO.amount})}">[[${page}]]</a></li> </th:block> <!-- 다음 버튼 --> <th:block th:if="${pageVO.next}"> <li style="margin-left: 5px;"> <a th:href="@{productList(page=${pageVO.end + 1}, amount=${pageVO.amount} )}"><i class="fa fa-angle-right" aria-hidden="true"></i></a> </li> </th:block> <!-- 맨 끝 페이지 --> <li> <a th:href="@{productList(page=${pageVO.realEnd}, amount=${pageVO.amount})}"><i class="fa fa-angle-double-right" aria-hidden="true"></i></a> </li> </ul> </div>

 

- 10, 20, 50, 100개 보기 기능 추가

 

 

- 값에 대한 유지

 

 

3. 검색

- 검색의 조건이 많아지면 sql문에 대해 잘 생각해 봐야함(어떤 경우의 수에도 돌아가야 하기 때문에)

- 검색 키워드를 넘기고, sql문 조회가 일어나게 함(판매마감일은 이상, 이하)

 

name값 지정, a태그 submit으로 변경

- 크리테리아에 변수 추가

 

 

- 컨트롤러

 

 

- sql문, xml: 3번째 사진처럼 문자열 비교는 안됨.  date로 형변환 해줄 것. sql문 and로 해야 사이 데이터들이 다 나옴!

 

문자열 비교로 들어가면 문자값을 비교하는게 됨(유니코드 어떤게 더 큰지 비교함)

'TIL > Spring boot' 카테고리의 다른 글

day88-spring boot  (0) 2023.02.17
day86-spring boot  (0) 2023.02.16
day84-spring boot  (0) 2023.02.14
day83-spring boot  (0) 2023.02.13
day82-spring boot  (0) 2023.02.09
profile

mjeongriver

@mjeongriver

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그