Spring & Springboot/올인원 스프링 프레임워크

전자 도서관 프로젝트 - 대출 도서 반납 기능 구현

YJ_ma 2023. 12. 3. 21:08

대출 도서 반납 처리하기

도서 반납 처리는 관리자의 업무이기 때문에 관리자 화면으로 이동한 후 로그인한다.

 

도서 반납은 '대출도서' 메뉴를 이용한다. '대출도서' 메뉴는 nav.jsp에 있다.

<li><a href="<c:url value='/book/admin/registerBookForm' />">도서등록</a></li>

 

컨트롤러 기능 구현

클라이언트의 요청을 처리할 수 있는 메서드를 com.office.library.book.admin 패키지의 BookController에 선언한다.

// 도서 대출 목록
@GetMapping("/getRentalBooks")
public String getRentalBooks(Model model) {
    System.out.println("[BookController] getRentalBooks()");

    String nextPage = "admin/book/rental_books";

    List<RentalBookVo> rentalBookVos = bookService.getRentalBooks();

    model.addAttribute("rentalBookVos", rentalBookVos);

    return nextPage;
}

 

서비스 기능 구현

컨트롤러에서 호출하는 getRentalBooks()를 com.office.library.book.admin 패키지의 BookService에 선언한다.

public List<RentalBookVo> getRentalBooks(){
    System.out.println("[BookService] getRentalBooks()");

    return bookDao.selectRentalBooks();
}

 

DAO 기능 구현

데이터베이스에서 도서를 검색하는 selectRentalBooks()를 com.office.library.book.admin 패키지의 BookDao에 선언한다.

public List<RentalBookVo> selectRentalBooks(){
    System.out.println("[BookDao] selectRentalBooks()");

    String sql = "SELECT * FROM tbl_rental_book rb "
            + "JOIN tbl_book b "
            + "ON rb.b_no = b.b_no "
            + "JOIN tbl_user_member um "
            + "ON rb.u_m_no = um.u_m_no "
            + "WHERE rb.rb_end_date = '1000-01-01' "
            + "ORDER BY um.u_m_id ASC, rb.rb_reg_date DESC";

    List<RentalBookVo> rentalBookVos = new ArrayList<RentalBookVo>();

    try {
        rentalBookVos = jdbcTemplate.query(sql, new RowMapper<RentalBookVo>() {
            @Override
            public RentalBookVo mapRow(ResultSet rs, int rowNum) throws SQLException {
                RentalBookVo rentalBookVo = new RentalBookVo();

                rentalBookVo.setRb_no(rs.getInt("rb_no"));
                rentalBookVo.setB_no(rs.getInt("b_no"));
                rentalBookVo.setU_m_no(rs.getInt("u_m_no"));
                rentalBookVo.setRb_start_date(rs.getString("rb_start_date"));
                rentalBookVo.setRb_end_date(rs.getString("rb_end_date"));
                rentalBookVo.setRb_reg_date(rs.getString("rb_reg_date"));
                rentalBookVo.setRb_mod_date(rs.getString("rb_mod_date"));

                rentalBookVo.setB_thumbnail(rs.getString("b_thumbnail"));
                rentalBookVo.setB_name(rs.getString("b_name"));
                rentalBookVo.setB_author(rs.getString("b_author"));
                rentalBookVo.setB_publisher(rs.getString("b_publisher"));
                rentalBookVo.setB_publish_year(rs.getString("b_publish_year"));
                rentalBookVo.setB_isbn(rs.getString("b_isbn"));
                rentalBookVo.setB_call_number(rs.getString("b_call_number"));
                rentalBookVo.setB_rantal_able(rs.getInt("b_rantal_able"));
                rentalBookVo.setB_reg_date(rs.getString("b_reg_date"));

                rentalBookVo.setU_m_id(rs.getString("u_m_id"));
                rentalBookVo.setU_m_pw(rs.getString("u_m_pw"));
                rentalBookVo.setU_m_name(rs.getString("u_m_name"));
                rentalBookVo.setU_m_gender(rs.getString("u_m_gender"));
                rentalBookVo.setU_m_mail(rs.getString("u_m_mail"));
                rentalBookVo.setU_m_phone(rs.getString("u_m_phone"));
                rentalBookVo.setU_m_reg_date(rs.getString("u_m_reg_date"));
                rentalBookVo.setU_m_mod_date(rs.getString("u_m_mod_date"));

                return rentalBookVo;
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
    return rentalBookVos;
}

 

tbl_rental_book, tbl_book, tbl_user_member 테이블을 조인해서 대출 정보를 조회한다.

프로젝트를 실행하고 관리자로 로그인하여 '대출도서'를 클릭한다.

'대출도서' 화면

 

대출 중인 도서를 반납하기 위해서는 <반납> 버튼을 이용한다. <반납> 버튼은 rental_books.jsp에 있다.

<td>
    <c:url value='/book/admin/returnBookConfirm' var='return_url'>
        <c:param name='b_no' value='${item.b_no}'/>
        <c:param name='rb_no' value='${item.rb_no}'/>
    </c:url>
    <a href="${return_url}">반납</a>
</td>

 

<반납> 버튼을 클릭하면 /book/admin/returnBookConfirm 요청이 발생한다.

이때 매개변수로 도서와 대출번호를 구분할 수 있는 b_no, rb_no를 같이 서버에 전달한다. 

 

컨트롤러 기능 구현

클라이언트의 요청을 처리하는 bookDetail()을 BookController에 이어서 선언한다.

// 도서 반납 확인
@GetMapping("/returnBookConfirm")
public String returnBookConfirm(@RequestParam("b_no") int b_no,
        @RequestParam("rb_no") int rb_no) {
    System.out.println("[BookController] returnBookConfirm()");

    String nextPage = "admin/book/return_book_ok";

    int result = bookService.returnBookConfirm(b_no, rb_no);

    if (result <= 0)
        nextPage = "admin/book/return_book_ng";

    return nextPage;
}

 

서비스 기능 구현

컨트롤러에서 호출하는 returnBookConfirm()을 서비스(BookService)에 선언한다.

public int returnBookConfirm(int b_no, int rb_no) {
    System.out.println("[BookService] getRentalBooks()");

    int result = bookDao.updateRentalBook(rb_no);

    if (result > 0)
        result = bookDao.updateBook(b_no);

    return result;
}

 

DAO 기능 구현

updateRentalBook()과 updateBook()을 BookDao에 선언한다.

public int updateRentalBook(int rb_no) {
    System.out.println("[BookDao] updateRentalBook()");

    String sql = "UPDATE tbl_rental_book "
            + "SET rb_end_date = NOW() "
            + "WHERE rb_no = ?";

    int result = -1;

    try {
        result = jdbcTemplate.update(sql, rb_no);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

public int updateBook(int b_no) {
    System.out.println("[BookDao] updateRentalBook()");

    String sql = "UPDATE tbl_book "
            + "SET b_rantal_able = 1 "
            + "WHERE b_no = ?";

    int result = -1;

    try {
        result = jdbcTemplate.update(sql, b_no);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

 

 

전체 대출 이력 조회하기

user1이 대출한 도서 2권중 1권을 반납했다. 따라서 user1이 현재 대출중인 도서는 1권이다. 이를 확인하기 위해 사용자 화면에서 user1로 로그인한 후 '나의책장'으로 이동하여 확인해본다.

 

이번에는 사용자가 <전체 대출 이력>을 클릭하여 모든 대출 이력(대출 중, 반납완료)을 조회하는 기능을 구현한다. 

<전체 대출 이력> 버튼은 bookshelf.jsp에 있다.

<a href="<c:url value='/book/user/listupRentalBookHistory'/>">전체 대출 이력</a>

 

<전체 대출 이력> 버튼을 클릭하면 /book/user/listupRentalBookHistory 요청이 발생한다. 계속해서 컨트롤러, 서비스, DAO를 구현해본다.

 

컨트롤러 기능 구현

// 도서 대출 이력
@GetMapping("/listupRentalBookHistory")
public String listupRentalBookHistory(HttpSession session, Model model) {
    System.out.println("[UserBookController] listupRentalBookHistory()");

    String nextPage = "user/book/rental_book_history";

    UserMemberVo loginedUserMemberVo = (UserMemberVo) session.getAttribute("loginedUserMemberVo");

    List<RentalBookVo> rentalBookVos = bookService.listupRentalBookHistory(loginedUserMemberVo.getU_m_no());

    model.addAttribute("rentalBookVos", rentalBookVos);

    return nextPage;
}

 

서비스 기능 구현

public List<RentalBookVo> listupRentalBookHistory(int u_m_no){
    System.out.println("[BookService] listupRentalBookHistory()");

    return bookDao.selectRentalBookHistory(u_m_no);
}

 

DAO 기능 구현

public List<RentalBookVo> selectRentalBookHistory(int u_m_no){
    System.out.println("[BookDao] selectRentalBookHistory()");

    String sql = "SELECT * FROM tbl_rental_book rb "
            + "JOIN tbl_book b "
            + "ON rb.b_no = b.b_no "
            + "JOIN tbl_user_member um "
            + "ON rb.u_m_no = um.u_m_no "
            + "WHERE rb.u_m_no = ? "
            + "ORDER BY rb.rb_reg_date DESC";

    List<RentalBookVo> rentalBookVos = new ArrayList<RentalBookVo>();

    try {
        rentalBookVos = jdbcTemplate.query(sql, new RowMapper<RentalBookVo>() {
            @Override
            public RentalBookVo mapRow(ResultSet rs, int rowNum) throws SQLException {
                RentalBookVo rentalBookVo = new RentalBookVo();

                rentalBookVo.setRb_no(rs.getInt("rb_no"));
                rentalBookVo.setB_no(rs.getInt("b_no"));
                rentalBookVo.setU_m_no(rs.getInt("u_m_no"));
                rentalBookVo.setRb_start_date(rs.getString("rb_start_date"));
                rentalBookVo.setRb_end_date(rs.getString("rb_end_date"));
                rentalBookVo.setRb_reg_date(rs.getString("rb_reg_date"));
                rentalBookVo.setRb_mod_date(rs.getString("rb_mod_date"));

                rentalBookVo.setB_thumbnail(rs.getString("b_thumbnail"));
                rentalBookVo.setB_name(rs.getString("b_name"));
                rentalBookVo.setB_author(rs.getString("b_author"));
                rentalBookVo.setB_publisher(rs.getString("b_publisher"));
                rentalBookVo.setB_publish_year(rs.getString("b_publish_year"));
                rentalBookVo.setB_isbn(rs.getString("b_isbn"));
                rentalBookVo.setB_call_number(rs.getString("b_call_number"));
                rentalBookVo.setB_rantal_able(rs.getInt("b_rantal_able"));
                rentalBookVo.setB_reg_date(rs.getString("b_reg_date"));

                rentalBookVo.setU_m_id(rs.getString("u_m_id"));
                rentalBookVo.setU_m_pw(rs.getString("u_m_pw"));
                rentalBookVo.setU_m_name(rs.getString("u_m_name"));
                rentalBookVo.setU_m_gender(rs.getString("u_m_gender"));
                rentalBookVo.setU_m_mail(rs.getString("u_m_mail"));
                rentalBookVo.setU_m_phone(rs.getString("u_m_phone"));
                rentalBookVo.setU_m_reg_date(rs.getString("u_m_reg_date"));
                rentalBookVo.setU_m_mod_date(rs.getString("u_m_mod_date"));

                return rentalBookVo;
            }
        }, u_m_no);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return rentalBookVos;
}

 

이제 프로젝트를 실행하여 '나의책장'에서 <전체 대출 이력> 버튼을 클릭한다. 반납된 도서와 현재 대출중인 도서가 모두 출력되는 것을 확인할 수 있다.

 

전체 도서 이력 역시 로그인 후 사용 가능하기 때문에 다음과 같이 인터셉터에 추가해야한다.

<mapping path="/book/user/listupRentalBookHistory"/>