반응형

 

도서 대여 시스템 프로젝트 진행

 

아래의 메뉴로 구성된 프로젝트를 구현한다.

관리자는 구현하지 않았으며 도서 대여의 종류만 검색 가능하게 하여 진행했다.

 

더보기

---------------- 도서 관리 프로젝트 ----------------
1. 일반 회원
2. 관리자

---------------- 일반 회원 ----------------
1. 전체 도서 조회
2. 도서 대여
3. 도서 대여 내역 조회

---------------- 일반회원 도서 대여 ----------------
# 도서 전체 내역 출력
1. 제목 검색
2. 종류 검색
3. 내용 검색

---------------- 도서 대여 내역 조회 ----------------
#전체 내역 출력
1. 대여 중인 도서

---------------- 관리자 ----------------
1. 전체 도서 조회
2. 신규 도서 등록
3. 도서 수량 변경

---------------- 신규 도서 등록 ----------------


---------------- 도서 수량 변경 ----------------
#전체 도서 내역 출력

 

 

아래의 SQL을 이용해 DB 테이블과 데이터를 생성해놓는다.

 

--------------------------------------------------------
--  파일이 생성됨
--------------------------------------------------------
--------------------------------------------------------
--  DDL for Table JAVA_BOOK
--------------------------------------------------------

  CREATE TABLE "JAVA_BOOK" 
   (	"BOOK_NO" NUMBER, 
	"NAME" VARCHAR2(100 BYTE), 
	"KIND" VARCHAR2(30 BYTE), 
	"CONTENT" VARCHAR2(2000 BYTE)
   ) ;
--------------------------------------------------------
--  DDL for Table JAVA_BOOK_HOLD
--------------------------------------------------------

  CREATE TABLE "JAVA_BOOK_HOLD" 
   (	"HOLD_NO" NUMBER, 
	"BOOK_NO" NUMBER
   ) ;
--------------------------------------------------------
--  DDL for Table JAVA_BOOK_RENT
--------------------------------------------------------

  CREATE TABLE "JAVA_BOOK_RENT" 
   (	"HOLD_NO" NUMBER, 
	"MEM_NO" NUMBER, 
	"RENT" VARCHAR2(20 BYTE)
   ) ;
REM INSERTING into JAVA_BOOK
SET DEFINE OFF;
Insert into JAVA_BOOK (BOOK_NO,NAME,KIND,CONTENT) values (1,'올웨더 투자법','경제','꼭지에 사고 바닥일 때 털고 나오는, 언제나 돈과 어긋나는 사람들을 위한 투자 교과서. 투자의 성패는 예측에 좌우되는 것이 아니다. 시장에 따라 돈이 되는 종목은 따로 있다. 우산 장수와 나막신 장수 두 아들을 둔 어머니처럼 비가 오는 날엔 우산을 팔고 맑은 날에는 나막신을 팔면, 언제나 웃을 수 있다. 투자도 마찬가지. 시장 변화에 종목을 바꿔 대응하면 언제든 ‘수익’을 낼 수 있다!');
Insert into JAVA_BOOK (BOOK_NO,NAME,KIND,CONTENT) values (2,'돈의 속성 ','경제','돈의 속성』은 3년 전 어느 극장 하나를 빌려 대중에게 강의했던 내용을 기반으로 집필됐다. 강연은 방송을 통해 전파되며 유튜브와 셀럽들에 의해 공유와 전파를 거듭했다. 그리고 이내 1,100만 명에게 전달되기에 이르렀다. 하지만 여러 사람을 통해 생산 및 재생산되는 과정에서 어떤 의미는 그 뜻이 정확히 전달되지 않았거나 의미가 왜곡되는 일이 있었다');
Insert into JAVA_BOOK (BOOK_NO,NAME,KIND,CONTENT) values (3,'클래식 음악 수업','예술','클래식 음악에 한결 더 가까이
알고 들으면 더 감동적인 클래식 음악의 세계

음악은 언어와도 같습니다. 클래식 음악은 낯선 외국어입니다. ');
Insert into JAVA_BOOK (BOOK_NO,NAME,KIND,CONTENT) values (4,'모든 순간의 클래식','예술','두려움과 불안, 반복되는 일상에서 느끼는 무기력, 누군가를 향한 그리움, 실패 후 느끼는 좌절…… 인생은 똑같이 흘러가는 듯 보이지만 실상 우리는 매일 완전히, 혹은 미묘하게 다른 감정의 순간들을 마주하며 살아간다. 그 순간 우리는 마치 무언가에 홀린 듯 어떤 선율을 떠올리거나 읊조린다. 선율은 추억이 담긴 음악일 수도, 젊었던 나를 위로한 멜로디일 수도, 그저 별 이유 없이 떠오른 음악일 수도 있다. 분명한 사실은 그 선율이 과거의 어느 날 당신을 위로했고, 여전히 당신의 마음을 어루만지고 있으며, 앞으로도 당신을 헤아리고 보듬어줄 거라는 것이다.');
REM INSERTING into JAVA_BOOK_HOLD
SET DEFINE OFF;
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (1,1);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (2,1);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (3,2);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (4,2);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (5,3);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (6,3);
Insert into JAVA_BOOK_HOLD (HOLD_NO,BOOK_NO) values (7,4);
REM INSERTING into JAVA_BOOK_RENT
SET DEFINE OFF;
Insert into JAVA_BOOK_RENT (HOLD_NO,MEM_NO,RENT) values (1,1,'Y');
Insert into JAVA_BOOK_RENT (HOLD_NO,MEM_NO,RENT) values (2,1,'N');
Insert into JAVA_BOOK_RENT (HOLD_NO,MEM_NO,RENT) values (2,2,'Y');
Insert into JAVA_BOOK_RENT (HOLD_NO,MEM_NO,RENT) values (3,1,'N');
--------------------------------------------------------
--  DDL for Index JAVA_BOOK_PK
--------------------------------------------------------

  CREATE UNIQUE INDEX "JAVA_BOOK_PK" ON "JAVA_BOOK" ("BOOK_NO") 
  ;
--------------------------------------------------------
--  DDL for Index JAVA_BOOK_HOLD_PK
--------------------------------------------------------

  CREATE UNIQUE INDEX "JAVA_BOOK_HOLD_PK" ON "JAVA_BOOK_HOLD" ("HOLD_NO") 
  ;
--------------------------------------------------------
--  Constraints for Table JAVA_BOOK
--------------------------------------------------------

  ALTER TABLE "JAVA_BOOK" ADD CONSTRAINT "JAVA_BOOK_PK" PRIMARY KEY ("BOOK_NO") ENABLE;
  ALTER TABLE "JAVA_BOOK" MODIFY ("BOOK_NO" NOT NULL ENABLE);
--------------------------------------------------------
--  Constraints for Table JAVA_BOOK_HOLD
--------------------------------------------------------

  ALTER TABLE "JAVA_BOOK_HOLD" MODIFY ("BOOK_NO" NOT NULL ENABLE);
  ALTER TABLE "JAVA_BOOK_HOLD" ADD CONSTRAINT "JAVA_BOOK_HOLD_PK" PRIMARY KEY ("HOLD_NO") ENABLE;
  ALTER TABLE "JAVA_BOOK_HOLD" MODIFY ("HOLD_NO" NOT NULL ENABLE);
--------------------------------------------------------
--  Constraints for Table JAVA_BOOK_RENT
--------------------------------------------------------

  ALTER TABLE "JAVA_BOOK_RENT" MODIFY ("HOLD_NO" NOT NULL ENABLE);

 

 

최종적인 프로젝트 파일은 바로 하단에 접기로 기입해놓았다.

 

package controller;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import service.BookService;
import util.ScanUtil;
import util.View;
import view.Print;
import vo.BookVo;

public class MainController extends Print{
	// sessionStorage은 하나 밖에 존재하지 않음
	static public Map<String, Object> sessionStorage = new HashMap<>();
	BookService bookService = BookService.getInstance();
	
	public static void main(String[] args) {
		new MainController().start();
	}
	
	private void start() {
		View view = View.MAIN;
		while (true) {
			switch (view) {
			case MAIN:
				view = home();
				break;
			case MEMBER:
				view = member();
				break;
			case ADMIN:
				view = admin();
				break;
			case MEM_BOOK_LIST:
				view = bookList();
				break;
			case BOOK_RENT:
				view = bookRent();
				break;
			case BOOK_RENT_LIST:
				view = bookRentList();
				break;
			case ADMIN_BOOK_LIST:
				view = adminBookList();
				break;
			case BOOK_ADD:
				view = bookAdd();
				break;
			case BOOK_HOLD_ADD:
				view = bookHoldAdd();
				break;
			default:
				break;
			}
		}
	}
	
	// 도서 수량 변경
	private View bookHoldAdd() {
		System.out.println("도서 수량 변경");
		System.out.println("#전체 도서 내역 출력");
		return null;
	}

	// 신규 도서 등록
	private View bookAdd() {
		System.out.println("신규 도서 등록");
		return View.MAIN;
	}

	// 전체 도서 조회(관리자)
	private View adminBookList() {
		System.out.println("전체 도서 조회");
		return View.MAIN;
	}
	
	// 관리자
	private View admin() {
		printAdmin();
		int sel = ScanUtil.menu();
		switch (sel) {
		case 1:
			return View.ADMIN_BOOK_LIST;
		case 2:
			return View.BOOK_ADD;
		case 3:
			return View.BOOK_HOLD_ADD;
		default:
			return View.MAIN;
		}
	}

	// 도서 대여 내역 조회
	private View bookRentList() {
		// 전체 대여 내역 출력
		int mem_no = (int)sessionStorage.get("mem_no");
		
		List<Map<String, Object>> rentList = bookService.bookRentList(mem_no);
		// 출력
		System.out.println("책 이름\t내용\t종류\t대여여부");
		for (Map<String, Object> map : rentList) {
			String name = (String)map.get("NAME");
			String content = (String)map.get("CONTENT");
			String kind = (String)map.get("KIND");
			String rent = (String)map.get("RENT");
			System.out.println(name + "\t" + content + "\t" + kind + "\t" + rent);
		}
		
		printMemberRentalList();
		int sel = ScanUtil.menu();
		if(sel == 1) {
			// 대여 중인 도서 출력
			List<Map<String, Object>> rentListY = bookService.bookRentListY(mem_no);
			for (Map<String, Object> map : rentListY) {
				String name = (String)map.get("NAME");
				String content = (String)map.get("CONTENT");
				String kind = (String)map.get("KIND");
				String rent = (String)map.get("RENT");
				System.out.println(name + "\t" + content + "\t" + kind + "\t" + rent);
			}
		}
		return View.MEMBER;
	}

	// 도서 대여
	private View bookRent() {
		List<Map<String, Object>> list = bookService.bookRentPossible();
		for (Map<String, Object> map : list) {
			BigDecimal hold_no = (BigDecimal)map.get("HOLD_NO");
			String name = (String)map.get("NAME");
			String kind = (String)map.get("KIND");
			String content = (String)map.get("CONTENT");
			
			System.out.println(hold_no.intValue() + "\t" + name + "\t" + kind + "\t" + content);
		}
		printMemberRental();
		int sel = ScanUtil.menu();
		if(sel == 2) {
			String kind = ScanUtil.nextLine("종류 >> ");
			List<Map<String, Object>> kindList
				= bookService.bookRentPossibleList(kind, sel);
			for (Map<String, Object> map : kindList) {
				BigDecimal hold_no = (BigDecimal)map.get("HOLD_NO");
				String name = (String)map.get("NAME");
				String kind2 = (String)map.get("KIND");
				String content = (String)map.get("CONTENT");
				
				System.out.println(hold_no.intValue() + "\t" + name + "\t" + kind2 + "\t" + content);
			}
			
			
		}
		if(sel == 3) {
			String content = ScanUtil.nextLine("내용 >> ");
		}
		return View.MAIN;
	}

	// 전체 도서 조회
	private View bookList() {
		List<BookVo> bookList = bookService.bookList();
		for (BookVo bookVo : bookList) {
			System.out.println(bookVo);
		}
		return View.MEMBER;
	}

	// 일반 회원
	private View member() {
		printMember();
		int sel = ScanUtil.menu();
		switch (sel) {
		case 1:
			return View.MEM_BOOK_LIST;
		case 2:
			return View.BOOK_RENT;
		case 3:
			return View.BOOK_RENT_LIST;
		default:
			return View.MAIN;
		}
	}

	// 홈
	private View home() {
		sessionStorage.put("mem_no", 1); // 로그인 생략
		
		printHome();
		int sel = ScanUtil.menu();
		switch (sel) {
		case 1:
			return View.MEMBER;
		case 2:
			return View.ADMIN;
		default:
			return View.MAIN;
		}
	}
}

 

package dao;

import java.util.List;
import java.util.Map;

import util.JDBCUtil;
import vo.BookVo;

public class BookDao {
	private static BookDao instance = null;

	private BookDao() {
	}

	public static BookDao getInstance() {
		if (instance == null) {
			instance = new BookDao();
		}
		return instance;
	}
	
	JDBCUtil jdbc = JDBCUtil.getInstance();
	
	public List<BookVo> bookList() {
		String sql = "select book_no, name, kind, "
					+"substr(content, 0, 10) content\r\n" + 
					 "from java_book";
		
		return jdbc.selectList(sql, BookVo.class);
	}
	
	public List<Map<String, Object>> bookRentList(int mem_no) {
		String sql = "select b.name, b.kind,\r\n" + 
				"substr(b.content, 0, 10) content, br.rent\r\n" + 
				"from java_book_rent br, java_book b, java_book_hold bh\r\n" + 
				"where bh.hold_no = br.hold_no\r\n" + 
				"and bh.book_no = b.book_no\r\n" + 
				"and mem_no = " + mem_no;
		
		return jdbc.selectList(sql);
	}
	
	public List<Map<String,Object>> bookRentListY(int mem_no) {
		String sql = "select b.name, b.kind,\r\n" + 
				"substr(b.content, 0, 10) content, br.rent\r\n" + 
				"from java_book_rent br, java_book b, java_book_hold bh\r\n" + 
				"where bh.hold_no = br.hold_no\r\n" + 
				"and bh.book_no = b.book_no\r\n" + 
				"and mem_no = " + mem_no + 
				"and br.rent = 'Y'";
		
		return jdbc.selectList(sql);
	}
	
	public List<Map<String, Object>> bookRentPossible() {
		String sql = "with data as(\r\n" + 
				"select *\r\n" + 
				"from java_book_hold h\r\n" + 
				"where not h.hold_no in (select hold_no \r\n" + 
				"                 from java_book_rent\r\n" + 
				"                 where rent = 'Y')\r\n" + 
				")\r\n" + 
				"select d.hold_no, b.name, b.kind,\r\n" + 
				"substr(b.content, 0, 10) content\r\n" + 
				"from data d, java_book b\r\n" + 
				"where d.book_no = b.book_no\r\n" + 
				"order by b.book_no";
		
		return jdbc.selectList(sql);
	}

	public List<Map<String, Object>> bookRentPossibleList(String kind, int sel) {
		String sql = "with data as(\r\n" + 
				"select *\r\n" + 
				"from java_book_hold h\r\n" + 
				"where not h.hold_no in (select hold_no \r\n" + 
				"                 from java_book_rent\r\n" + 
				"                 where rent = 'Y')\r\n" + 
				")\r\n" + 
				"select d.hold_no, b.name, b.kind,\r\n" + 
				"substr(b.content, 0, 10) content\r\n" + 
				"from data d, java_book b\r\n" + 
				"where d.book_no = b.book_no\r\n" +
//				"and kind like '%'||?||'%'\r\n" + 
				"and kind like '%" + kind + "%'\r\n" + 
				"order by b.book_no";
		return jdbc.selectList(sql);
	}
}

 

package service;

import java.util.List;
import java.util.Map;

import dao.BookDao;
import vo.BookVo;

public class BookService {
	private static BookService instance = null;

	private BookService() {
	}

	public static BookService getInstance() {
		if (instance == null) {
			instance = new BookService();
		}
		return instance;
	}
	
	BookDao dao = BookDao.getInstance();
	
	public List<BookVo> bookList() {
		return dao.bookList();
	}
	
	public List<Map<String, Object>> bookRentList(int mem_no) {
		return dao.bookRentList(mem_no);
	}
	
	public List<Map<String,Object>> bookRentListY(int mem_no) {
		return dao.bookRentListY(mem_no);
	}
	
	public List<Map<String, Object>> bookRentPossible() {
		return dao.bookRentPossible();
	}

	public List<Map<String, Object>> bookRentPossibleList(String kind, int sel) {
		return dao.bookRentPossibleList(kind, sel);
	}
}

 

package vo;

public class BookVo {
	 private int book_no;
	 private String name;
	 private String kind;
	 private String content;
	 
	public int getBook_no() {
		return book_no;
	}
	public void setBook_no(int book_no) {
		this.book_no = book_no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getKind() {
		return kind;
	}
	public void setKind(String kind) {
		this.kind = kind;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	
	@Override
	public String toString() {
		return "BookVo [book_no=" + book_no + ", name=" + name + ", kind=" + kind + ", content=" + content + "]";
	}
}

 

package view;

public class Print {
	public void printVar() {
		System.out.println("============================");
	}
	
	public void printLn(int num) {
		for(int i=0; i<num; i++) System.out.println();
	}
	
	public void printHome() {
		printVar();
		System.out.println("----------- 도서 관리 프로젝트 -----------");
		System.out.println("1. 일반 회원");
		System.out.println("2. 관리자");
		printLn(4);
		printVar();
	}
	
	public void printMember() {
		printVar();
		System.out.println("----------- 일반 회원 -----------");
		System.out.println("1. 전체 도서 조회");
		System.out.println("2. 도서 대여");
		System.out.println("3. 도서 대여 내역 조회");
		printLn(3);
		printVar();
	}
	
	public void printMemberRental() {
		printVar();
		System.out.println("------ 일반회원 도서 대여 ------");
		System.out.println("1. 제목 검색");
		System.out.println("2. 종류 검색");
		System.out.println("3. 내용 검색");
		printLn(3);
		printVar();
	}
	
	public void printMemberRentalList() {
		printVar();
		System.out.println("------ 도서 대여 내역 조회 ------");
		System.out.println("1. 대여 중인 도서");
		System.out.println("2. 홈");
		printLn(3);
		printVar();
	}
	
	public void printAdmin() {
		printVar();
		System.out.println("------ 관리자 ------");
		System.out.println("1. 전체 도서 조회");
		System.out.println("2. 신규 도서 등록");
		System.out.println("3. 도서 수량 변경");
		printLn(3);
		printVar();
	}
}

 

package util;

public enum View {
	MAIN,					// 기본화면
	ADMIN,					// 관리자
	MEMBER,					// 일반 회원
	
	MEM_BOOK_LIST,			// 일반회원 전체 조회
	BOOK_RENT,				// 도서 대여
	BOOK_RENT_LIST,			// 도서 대여 내역
	
	ADMIN_BOOK_LIST,		// 관리자 전체 도서 조회
	BOOK_ADD,				// 신규 도서 등록
	BOOK_HOLD_ADD			// 도서 수량 변경
}

 

package util;

import java.util.Scanner;

public class ScanUtil   {
	// 스캐너를 손쉽게 사용할 수 있는 static 메서드를 가지고있음
	static Scanner sc = new Scanner(System.in);
	
	public static int menu() {
		return nextInt("메뉴 선택 : ");
	}
	
	
	public static String nextLine(String print) {
		System.out.print(print);
		return nextLine();
	}
	
	private static String nextLine() {
		return sc.nextLine();
	}
	
	public static int nextInt(String print) {
		System.out.print(print);
		return nextInt();
	}
	
	private static int nextInt() {
		while(true) {
			try {
				int result = Integer.parseInt(sc.nextLine());
				return result;
			}catch (NumberFormatException e) {
				System.out.println("잘못 입력!!");
			}
		}
	}
}

 

 

 

 

TIP (Database)

 

  • whith as 문

: 복잡한 부분의 쿼리를 분리해서 사용할 수 있는 문. 서브 쿼리를 옮겨 괄호 안에 넣어두면 된다.

 

with 테이블이름 as (

서브쿼리;

)

 

-- with as문 : 복잡한 부분의 쿼리를 분리해서 사용할 수 있는 문. 서브 쿼리를 옮겨 괄호 안에 넣어두면 된다.
with data as(
select *
from java_book_hold h
where not h.hold_no in (select hold_no 
                 from java_book_rent
                 where rent = 'Y')
)
select d.hold_no, b.name, b.kind, substr(b.content, 0, 10) content
from data d, java_book b
where d.book_no = b.book_no
and kind like '%'||'경제'||'%'
order by b.book_no;

 

 

 

  • VO 생성

SQL Developer 에 하단의 코드를 작성하여 복붙하면 좀 더 쉽게 vo를 생성할 수 있다.

 

SELECT 
    ' private '||
   DECODE( DATA_TYPE , 'NUMBER', 'int ', 'String ' )||
    LOWER(COLUMN_NAME)||';'
FROM COLS
WHERE TABLE_NAME = '테이블이름' -- 대문자로 입력하지 않을시 오류뜸
ORDER BY COLUMN_ID;

 

 

반응형