Spring #13 - Book

김형우·2022년 3월 7일
0

Spring

목록 보기
14/19

admin/insertbatch - 일괄등록

1. Book.java

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "book4")
public class Book {
    @Id
    private long code = 0L;
    private String title = null;
    private long price = 0L;
    private String writer = null;
    // 문자열 = "Hello"
    // 문자하나 = 'A', 'B', 'C'
    private char category;
    private Date regdate = null;
}

2. BookDB.java

  • @Service
@Service
public interface BookDB {
    // 일괄등록
    public long insertBatchBook(List<Book> list);
}

3. BookDBImpl.java

  • @Service
  1. List<Book> 타입으로 파라미터를 넘긴다.

  2. mongoDB.insert 중에서 List 타입을 받는 생성자를 선택한다.

  3. List를 던지면 반환받는 값이 Collection이다
    3-1. 반환값을 Collection 타입으로 정의해두면 Collection 아래의 자식타입을 모두 사용할수 있다.
    3-2. 하지만 Collection 자체만으로는 객체를 생성할수 없다. abstract 추상화 되었기 때문.

// 1. 서비스
@Service
public class BookDBImpl implements BookDB { // 2. 설계 인터페이스 구현

    // 3. DB연동 객체 생성
    @Autowired
    MongoTemplate mongodb;    

    @Override
    public long insertBatchBook(List<Book> list) {
        try {
            // 4. 실제수행(구현)
            // Collection 타입으로 정의해두면 Collection 아래의 자식타입을 모두 사용할수 있다.
            // 하지만 Collection 자체만으로는 객체를 생성할수 없다. abstract 추상화 되었기 때문.
            Collection<Book> retList = mongodb.insert(list, Book.class);
            if (retList.size() == list.size()) {
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }
}

3. AdminController.java

  1. (GET)insertBatch를 수행 할 jsp 페이지 불러오기
    : @GetMapping(value = "/insertbatch")
    : (선택)title값을 model로 만들어서 던져준다
// 127.0.0.1:8080/admin/insertbatch
@GetMapping(value = "/insertbatch")
public String insertbatchGET(Model model) {
    model.addAttribute("title", "책 등록");
    return "admin/insertbatch";
}
  1. (POST)insertBatch 수행
    2-1. jsp에서 받은 변수들을 @RequestParam으로 받는다.
    : 이 때, 여러 항목을 동시에 등록 하기 때문에 모든 변수들의 타입을 배열화해서 받는다.
    = ex) String[], long[], char[] 등
    2-2. 새로운 시퀀스를 이용해서 도서 목록 번호(_id)를 생성한다.
    : @Autowired
    : SequenceService sequenceService;
    2-3. 반복문을 이용해서 빈 리스트(List<Book> list = new ArrayList<>();)에 Book 타입의 book을 목록 형태로 담는다(list.add(book);).

// 도서 일괄 등록
// 127.0.0.1:8080/admin/insertbatch
@PostMapping(value = "/insertbatch")
public String insertbatchPOST(
        @RequestParam(name = "title") String[] title,
        @RequestParam(name = "price") long[] price,
        @RequestParam(name = "writer") String[] writer,
        @RequestParam(name = "category") char[] category) {

    // long code = sequenceService.generationSequence("SEQ_BOOK4_NO");
    // 빈 리스트 만들기
    List<Book> list = new ArrayList<>();
    for (int i = 0; i < title.length; i++) {
        // System.out.println(title[i] + "," + price[i] + "," + writer[i] + "," +
        // category[i]);
        // book 객체만들기
        // 시퀀스를 이용해서 코드를 채움, 날짜도
        // 리스트 추가하기
        Book book = new Book();
        book.setCode(sequenceService.generationSequence("SEQ_BOOK4_NO"));
        book.setTitle(title[i]);
        book.setPrice(price[i]);
        book.setWriter(writer[i]);
        book.setCategory(category[i]);
        book.setRegdate(new Date());
        // System.out.println("book ==> " + book);
        list.add(book);
    }
    // System.out.println("list ==> " + list);
    // 배열 4개로 되어있는 결과를 => List<Book>

    long ret = bookDB.insertBatchBook(list);
    // System.out.println("ret ===> " + ret);
    if (ret == 1) {
        return "redirect:/admin/insertbatch";
    }
    return "redirect:/admin/insertbatch";
}

admin/action - 일괄수정/삭제

1. BookDB.java - interface

  • @Service

3. 일괄삭제

// 일괄삭제
public long deleteBatchBook(List<Long> code);

2. 일괄수정 - GET

  1. List<Long> code를 받는다.
    : 이렇게 받기 위해서는 jsp에서 수정할 목록을 체크할 때 그 code들을 List타입으로 만들어야 하며, long과 다르게 class가 Long이 되어야 한다.
  2. List<Book>로 반환한다.

2-1. 일괄수정 - POST

  1. List<Book> list를 받는다.
    : Book 형태의 모음이기 때문
// 수정 목록 보내기 (수업용)
public List<Book> updateBatchListWhereIn(List<Long> code);

// 일괄수정 (수업용)
public long updateBatchBook(List<Book> list);

2. BookDBImpl.java - 수행부

  • @Service

2. 일괄수정 - GET

  1. 수정 할 대상을 체크해서 code를 보내고 해당 목록만 화면에 표시하기 위한 명령
  2. code가 List<Long>형태이기 때문에 여러개가 일치해야 하는 조건이므로
    : query.addCriteria(Criteria.where("_id").in(code));
    = .in을 사용한다.
@Override
public List<Book> updateBatchListWhereIn(List<Long> code) {
    try {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").in(code));

        // DESC : 내림차순
        // ASC : 오름차순
        Sort sort = Sort.by(Direction.DESC, "_id");
        query.with(sort);

        return mongodb.find(query, Book.class);
        // System.out.println("result ===> " + result);

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

2-1. 일괄수정 - POST

  1. 수정은 query에 .in을 사용해서 수행할수 없다.
  2. 하나의 _id를 찾아서 해당 사항을 모두 수정하는 형태를 만들어서 반복문을 돌린다.
@Override
public long updateBatchBook(List<Book> list) {
    try {
        long updateCnt = 0L;
        for (Book tmp : list) {
            Query query = new Query();
            query.addCriteria(Criteria.where("_id").is(tmp.getCode()));

            Update update = new Update();
            update.set("title", tmp.getTitle());
            update.set("price", tmp.getPrice());
            update.set("writer", tmp.getWriter());
            update.set("category", tmp.getCategory());

            UpdateResult result = mongodb.updateFirst(query, update, Book.class);
            updateCnt += result.getMatchedCount();
        }
        if (updateCnt == list.size()) {
            return 1;
        }
        return 0;
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    }
}

1. AdminController.java

  • jsp에서 버튼 두개의 value값이 다름을 이용해 각각 다른 동작(일괄삭제/일괄수정)을 수행할 수 있도록 만든다.

1. 일괄삭제

  1. @RequestParam(name = "btn") String btn으로 jsp의 버튼의 value값을 받아온다.
  2. @RequestParam(name = "chk") List<Long> code으로 jsp에서 체크한 항목의 code를 List타입으로 받아온다.
  3. 받아온 btn의 value값이 일괄삭제 일때 수행 할 명령을 if문을 통해 만든다.
    : if (btn.equals("일괄삭제")) { }
  4. deleteBatchBook이 받는 값이 List타입이기 때문에 같은 타입으로 불러온 code 를 바로 넣어준다
  5. -끝-

2. 일괄수정

  1. 수정은 input 형태의 페이지를 따로 만들어서 수정 후 다시 명령을 수행하는 형식으로 동작한다.
  2. @PostMapping으로는 jsp를 불러올수 없기때문에 redirect를 사용해야한다.
  3. redirect를 사용하면 변수나 받은 값 등이 남아 있지 않고 초기화 되어버린다.
  4. 때문에 가장 중요한 변수인 code@GetMapping 하는 타이밍에 던져주기위해 세션에 저장한다.
    : httpSession.setAttribute("CHK", code);
  5. 세션에 배열형식의 값을 넣을 수 있도록 세션을 설정한다.
    : Boot20220228Application.java
@Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
	return new JdkMongoSessionConverter(Duration.ofMinutes(10));
}
  1. 이후 @GetMapping타이밍에 "CHK"라는 name을 이용해서 세션에서 code를 꺼낼 수 있다.
// 일괄수정/삭제
@PostMapping(value = "/action")
public String actionPOST(
        @RequestParam(name = "btn") String btn,
        @RequestParam(name = "chk") List<Long> code) {
    
    if (btn.equals("일괄삭제")) {
        long response = bookDB.deleteBatchBook(code);
        if (response == 1) {
            return "redirect:/admin/selectlist";
        }        
        return "redirect:/admin/selectlist";
    } 
    else if (btn.equals("일괄수정")) {
        httpSession.setAttribute("CHK", code); 
        return "redirect:/admin/updatebatch";        
    }
    return "redirect:/admin/selectlist";
}

2-1. 일괄수정 - GET

  1. 일괄수정용 jsp 페이지를 불러오는 @GetMapping페이지
  2. 세션에 저장된 code를 불러와서 사용한다.
    : 여기에서 code의 타입은 List이고, 조회하는 메소드도 List<Long> 형태로 받는다.
    : List<Long> code = (List<Long>) httpSession.getAttribute("CHK");
    2-1. 세션을 사용할때 입력한 형태와 불러오는 형태가 일치하는지의 여부를 명령어 자체에서는 파악하기 힘들기 떄문에 경고가 뜬다.
    2-2. 그 경고를 없애는 명령어를 사용한다
    : @SuppressWarnings({ "unchecked" })
    : 나는 입력한 형태와 불러오는 형태가 다 List<Long> code 임을 알고 있기 때문
  3. 이렇게 만든 List<Book> list를 model 형태로 jsp에 던진다.
    : model.addAttribute("book", list);
// 일괄수정페이지 GET
@GetMapping(value = "/updatebatch")
public String updatebatchGET(Model model) {
    // 형변환 경고(데이터가 안전하지 않다)를 없앰
    // 세션에 추가할때와 가지고올때의 타입이 정확하게 매칭한다는것을 나는 알고 있기때문
    @SuppressWarnings({ "unchecked" })
    List<Long> code = (List<Long>) httpSession.getAttribute("CHK");    
    List<Book> list = bookDB.updateBatchListWhereIn(code);
    model.addAttribute("book", list);
    return "/admin/updatebatch";
}

2-2. 일괄수정 - POST

  1. @RequestParam으로 jsp에서 받은 값들의 타입과 변수명을 정한다.
  2. @Service 파일에서 정의한 형태로 updateBatchBook을 수행하기 위해 List<Book> list = new ArrayList<>()를 만든다.
  3. list에 Book타입으로 데이터를 입력한다.
  4. bookDB.updateBatchBook(list);로 List 타입의 list를 넣어 명령을 수행한다.
@PostMapping(value = "/updatebatch")
public String updatebatchPOST(
        @RequestParam(name = "code") long[] code,
        @RequestParam(name = "title") String[] title,
        @RequestParam(name = "price") long[] price,
        @RequestParam(name = "writer") String[] writer,
        @RequestParam(name = "category") char[] category) {
    List<Book> list = new ArrayList<>();
    for (int i = 0; i < code.length; i++) {
        Book book = new Book();
        book.setCode(code[i]);
        book.setTitle(title[i]);
        book.setPrice(price[i]);
        book.setWriter(writer[i]);
        book.setCategory(category[i]);
        list.add(book);
    }
    long ret = bookDB.updateBatchBook(list);
    if (ret == 1) {
        System.out.println("수정완료");
        return "redirect:/admin/selectlist";
    }
    return "redirect:/admin/updatebatch";
}
profile
The best

0개의 댓글