[미니프로젝트] 시나리오01 커피 주문프로그램
데이터베이스는 SQLite3를 이용했다.
Coffee.db 커피 데이터베이스에는 (Beverage,OrderTBL) 2가지 테이블이 있다.
OrderTBL에는 기본키 설정을 안했음...
패키지는 5가지로 나눴다.
AdminSys 는 관리자프로그램으로 음료추가,삭제,매출조회,수정(음료명,가격) 등을 할 수 있고
OrderSys 주문 시스템을 통해 오더가 들어오면 서버를 통해 주문 내역이 관리자프로그램에 뜰 수 있도록 하고자 했다.
커피오더링 프로그램의 시작이다
이 부분은 윈도우빌더로 GUI 구현할 때 주문하기버튼을 맨 처음에 띄워서 주문하기를 누르면 주문이 시작되도록 할 예정이다.
주문하기 버튼을 누르면 Beverage 테이블에 있는 음료리스트를 모두 보여주고 주문할 음료 번호와 갯수를 선택한다.
주문을 완료하면 주문내역과 주문 번호를 출력한다.
그리고 주문하시려면 주문하기<< 해당메인으로 가게할 예정이다. (GUI로 실행할때)
그리고 주문이 완료되면 클라이언트클래스를 실행해서 해당 정보를 서버로 전달한다.
어드민에서 음료관련 변경이 있거나 커피오더링시스템에서 주문이 일어나면 DB에 저장또는 업뎃이 된다.
이하 코드 공유
Start
[main]
package Start;
import java.io.IOException;
import java.sql.SQLException;
public class main {
public static void main(String[] args) throws SQLException, IOException {
new Driver().run();
}
}
[Driver]
package Start;
import java.io.IOException;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import AdmimSys.Admin;
import CoffeeOrdering.OrderSys;
public class Driver {
int choice;
void run() throws SQLException, IOException {
//실제로는 관리자 / 사용자 페이지 다르게...
Scanner scan = new Scanner(System.in);
System.out.print("관리자(1)/사용자(2)");
choice = scan.nextInt();
if(choice==1) new Admin().main();
//관리자 실행
else new OrderSys().main();
}
}
[Print]
package Start;
import java.text.DecimalFormat;
import java.util.StringTokenizer;
import java.util.Vector;
import AdmimSys.Beverage;
import CoffeeOrdering.Order;
public class Print {
public Print(){
}
public static int run(Vector<Beverage> list) {
int total=0;
for(Beverage c:list) {
total+=c.getPrice();
System.out.println(c.toString());
}
return total;
}
public static void runO(Vector<Order> list) { //매출전체조회
DecimalFormat formatter = new DecimalFormat("###,###");
int total=0;
for(Order o:list) {
System.out.println(o.toString());
total += o.getTotal();
}
System.out.println("---------------------------------------");
System.out.println("총금액: "+formatter.format(total));
}
public static void printMssg(String msg) {
StringTokenizer st = new StringTokenizer(msg," ");
while(st.hasMoreTokens())
System.out.println(st.nextToken());
}
}
Network
[Server]
package Network;
import java.net.*;
import java.util.StringTokenizer;
import java.io.*;
public class Server {
String serverIp;
ServerSocket serverSocket=null;
Socket socket;
InputStream in;
String Mssg;
public Server() {
serverIp = "127.0.0.1"; //여기에 IP넣기
}
public void getMssg() throws IOException {
serverSocket = new ServerSocket(8888);
socket = serverSocket.accept();
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
Mssg = dis.readUTF();
dis.close();
socket.close();
serverSocket.close();
printMssg(Mssg);
}
public void printMssg(String msg) {
StringTokenizer st = new StringTokenizer(msg,"/");
while(st.hasMoreTokens())
System.out.println(st.nextToken());
}
public static void main(String[] args) throws IOException {
System.out.println("주문번호 음료명\t수량");// << 이거 보여지는 탭은 따로...
while(true) {
new Server().getMssg();
}
}
} // class
[Client]
package Network;
import java.net.*;
import java.util.Scanner;
import java.util.Vector;
import CoffeeOrdering.Order;
import java.io.*;
public class Client {
Socket socket = null;
OutputStream out;
public Client() {
}
public void setOrder(Vector<Order> v) throws IOException {
String serverIp = "127.0.0.1";
socket = new Socket(serverIp, 8888);
out = socket.getOutputStream();
sendMssg(v);
socket.close();
}
void sendMssg(Vector<Order> v) throws IOException {
String str="";
Scanner scan = new Scanner(System.in);
DataOutputStream dos = new DataOutputStream(out);
for(Order o:v)
str+="["+o.getOrderid()+"] "+o.getName()+"\t"+o.getQty()+"개/";
dos.writeUTF(str);
dos.close();
}
}
DB
[CoffeeDB]
package DB;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import AdmimSys.Beverage;
import CoffeeOrdering.Order;
public class CoffeeDB {
Beverage cof;
Connection connection = null;
Statement statement;
static {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private CoffeeDB() throws SQLException {
connection = getCon();
statement= connection.createStatement();
// statement.executeUpdate("Drop TABLE Beverage");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS Beverage (id integer PRIMARY KEY AUTOINCREMENT, name TEXT, price integer)");
// statement.executeUpdate("Drop TABLE OrderTBL");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS OrderTBL (orderid integer, id integer, qty integer, saledate text)");
close(connection,statement);
}
private static CoffeeDB cofDB= null;
public static CoffeeDB getInstance() throws SQLException {
if(cofDB==null) cofDB = new CoffeeDB();
return cofDB;
}
public Connection getCon() {
try {
connection = DriverManager.getConnection("jdbc:sqlite:Coffee.db");
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
void close(Connection con,Statement stmt){
try {
stmt.close(); con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
void close(Connection con,Statement stmt,ResultSet rs){
try {
stmt.close(); con.close(); rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//쿼리실행
public int run(String sql) throws SQLException {
int result = 0;
connection = getCon();
statement= connection.createStatement();
try {
result = statement.executeUpdate(sql);
close(connection,statement);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public Vector<Beverage> selectB(String sql) throws SQLException { //조회메소드
connection = getCon();
statement= connection.createStatement();
Vector<Beverage> list = new Vector<>();
ResultSet rs = null;
try {
rs = statement.executeQuery(sql);
while(rs.next())
list.add(new Beverage(rs.getInt(1),rs.getString(2),rs.getInt(3)));
close(connection,statement,rs);
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
public Vector<Order> selectO(String sql) throws SQLException { //조회메소드
connection = getCon();
statement= connection.createStatement();
Vector<Order> list = new Vector<>();
ResultSet rs = null;
try {
rs = statement.executeQuery(sql);
while(rs.next())
list.add(new Order(rs.getInt(1),rs.getInt(2),rs.getInt(3),rs.getString(4),rs.getString(5),rs.getInt(6)));
close(connection,statement,rs);
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
[Delete]
package DB;
import java.util.Scanner;
public class Delete {
public Delete() {}
public String delete(Scanner sc) {
System.out.print("삭제하실 음료 번호를 선택하세요>>");
int num = sc.nextInt();
String str="";
System.out.print("정말 삭제하시겠습니까?(y/n)>>");
if(sc.next().equals("y")) str=deleteDrink(num);
return str;
}
public String deleteDrink(int id) {
return "Delete from Beverage where id = "+id;
}
}
[Insert]
package DB;
import java.util.Scanner;
import AdmimSys.Beverage;
import CoffeeOrdering.Order;
public class Insert {
public Insert() {}
public String add(Scanner scan) {
System.out.print("음료이름>>");
String name = scan.next().trim();
System.out.print("음료가격>>");
int price = scan.nextInt();
Beverage cof = new Beverage(name,price);
return addDrink(cof);
}
public String addDrink(Beverage cof) {
return "Insert into Beverage (name,price) values (\""+cof.getName()
+"\","+cof.getPrice()+")";
}
public static String insertOrder(Order od) {
return "Insert into OrderTBL (orderid,id,qty,saledate) values ("+od.getOrderid()+","+od.getId()+","+od.getQty()+",CURRENT_TIMESTAMP)";
}
}
[Select]
package DB;
import java.sql.SQLException;
import java.util.Vector;
import CoffeeOrdering.Order;
public class Select {
public Vector<Order> select(CoffeeDB CofDB) throws SQLException{
Vector<Order> Olist = null;
Olist = CofDB.selectO(Select.selectSale());
return Olist;
}
public static String select() { //전체조회
return "Select * from Beverage order by id";
}
public static String select(String name) { //이름조회
return "Select * from Beverage where name like \"%"+name+"\" order by id";
}
public static String selectSale() { //판매조회 (날짜별로)
return "Select orderid,Beverage.id,qty,saledate,name,Beverage.price from OrderTBL inner join Beverage on OrderTBL.id=Beverage.id order by saledate desc";
}
public static String selectSale(int i) {
return "Select orderid,Beverage.id,qty,saledate,name,Beverage.price from OrderTBL inner join Beverage on OrderTBL.id=Beverage.id where orderid ="+i;
}
}
[update]
package DB;
import java.sql.SQLException;
import java.util.Scanner;
public class Update {
public void update(Scanner sc,CoffeeDB CofDB) throws SQLException {
int opt=0;
System.out.println("1.가격수정|2.이름수정|0.이전으로");
if(opt==1) CofDB.run(updateNo1(sc)) ;
else if(opt==2) CofDB.run(updateNo2(sc)) ;
}
public String updateNo1(Scanner sc) {
System.out.print("수정할 음료번호>>");
int id = sc.nextInt();
System.out.print("수정가격>>");
int price= sc.nextInt();
return updateDrink(id,price);
}
public String updateNo2(Scanner sc) {
System.out.print("수정할 음료번호>>");
int id = sc.nextInt();
System.out.print("수정이름>>");
String name= sc.next().trim();
return updateDrink(id,name);
}
public String updateDrink(int id,int price) {
return "Update Beverage set price = "+price+" where id = "+id;
}
public String updateDrink(int id,String name) {
return "Update Beverage set name = "+name+" where id = "+id;
}
}
CoffeeOrdering
[Order]
package CoffeeOrdering;
import java.text.DecimalFormat;
public class Order {
int orderid;
int id;
int qty;
int price;
String saledate;
String name;
public Order() {}
public Order(int Oid,int id,int qty) {
orderid=Oid; this.id = id; this.qty = qty;
}
public Order(int Oid,int id,int qty,String Odate,String name, int price) {
orderid=Oid; this.id=id; this.qty=qty; saledate=Odate; this.name=name; this.price=price;
}
public int getOrderid() {
return orderid;
}
public int getId() {
return id;
}
public int getQty() {
return qty;
}
public String getName() {
return name;
}
public int getTotal() {
return qty*price;
}
@Override
public String toString() {
DecimalFormat formatter = new DecimalFormat("###,###");
return "["+orderid+"][음료번호:"+id+" 음료명:"+name+"\t 수량:"+qty+"\t 판매액:"+formatter.format(qty*price)+"원 ][판매일 : "+saledate+"]";
}
}
[OrderSys]
package CoffeeOrdering;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Scanner;
import java.util.Vector;
import AdmimSys.Beverage;
import DB.CoffeeDB;
import DB.Insert;
import DB.Select;
import Network.Client;
import Start.Print;
public class OrderSys {
private int id;
private int qty;
private int ordercnt;
Vector<Beverage> list=null;
Vector<Order> Ordlist=null;
CoffeeDB CofDB;
Scanner sc;
public OrderSys() throws SQLException {
ordercnt=1;
CofDB = CoffeeDB.getInstance();
list = CofDB.selectB(Select.select());
sc = new Scanner(System.in);
}
public void main() throws SQLException, IOException {
while(true) {
System.out.println("주문하시려면 주문하기를 선택하세요");
//"주문하기"<<버튼 누르면
run();
ordercnt++;
}
}
public void run() throws SQLException, IOException {
//종료버튼 만들어서 그거 누르면 반복문에서 빠져나가기...
input();
pay(Ordlist);
Ordlist =CofDB.selectO(Select.selectSale(ordercnt));
new Client().setOrder(Ordlist);
Print.runO(Ordlist);
System.out.println("주문번호는 "+ordercnt+"번 입니다.");
}
public Vector<Order> input() throws NumberFormatException, IOException, SQLException {
Ordlist = new Vector<>();
while(true) {
Print.run(list);
System.out.print("주문하실 음료 번호를 선택하세요>>");
id = sc.nextInt();
System.out.print("몇 개를 구입하시겠습니까?>>"); //+ 버튼 만들어서 int qty++ 되게<<<
qty = sc.nextInt();//그리고 + 누를 때마다 갯수갱신되게 보여주기
Ordlist.add(new Order(ordercnt,id,qty));
sc.nextLine();
System.out.println("계속 주문하시겠습니까?(y/n)"); //종료버튼 만들기>> 종료버튼시 choice = false;
if(sc.nextLine().equals("n")) {
break;
}
}
return Ordlist;
}
public void pay(Vector<Order> v) throws SQLException {
for(Order o:v)
CofDB.run(Insert.insertOrder(o));
}
}
AdminSys
[Admin]
package AdmimSys;
import java.sql.SQLException;
import java.util.Scanner;
import java.util.Vector;
import DB.CoffeeDB;
import DB.Delete;
import DB.Insert;
import DB.Select;
import DB.Update;
import Start.Print;
public class Admin {
Scanner scan;
private CoffeeDB CofDB;
Vector<Beverage> list;
public Admin() throws SQLException {
scan = new Scanner(System.in);
CofDB = CoffeeDB.getInstance();
}
public void main() throws SQLException {
int option = 0;
do {
list = CofDB.selectB(Select.select());
Print.run(list);
System.out.println("----------관리자페이지----------");
System.out.println("1.음료추가|2.음료삭제\n"
+"3.매출조회|4.수정\n"+"0.종료");
System.out.println("-----------------------------");
System.out.print(">>");
option = scan.nextInt();
if(option==1) CofDB.run(new Insert().add(scan));
else if(option==2) {
String str = new Delete().delete(scan);
if(str.length()!=0) CofDB.run(str);
}
else if(option==3) Print.runO(new Select().select(CofDB));
else if(option==4) new Update().update(scan, CofDB);
}while(option!=0);
}
public Vector<Beverage> search() throws SQLException {
int opt = 0;
Vector<Beverage> list = null;
do {
System.out.println("1.이름으로조회|0.종료");
opt = scan.nextInt();
if(opt==1) {
System.out.print("음료명>>");
list = CofDB.selectB(Select.select(scan.next().trim()));
}
if(opt==2) {
}
if(opt==3) list = CofDB.selectB(Select.selectSale());
} while(opt!=0);
return list;
}
//출력하기
}
[Beverage]
package AdmimSys;
import java.text.DecimalFormat;
public class Beverage {
private int id;
private String name;
private int price;
public Beverage() {
}
//id로 생성
public Beverage(int id) {
this.id = id;
}
//전체입력 생성자
public Beverage(int id,String n, int p) {
this.id = id; name = n; price = p;
}
//이름,가격,갯수 생성자
public Beverage(String n, int p) {
name = n; price = p;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
DecimalFormat formatter = new DecimalFormat("###,###");
return "[" + id + "] " + name + "\t " + formatter.format(price) +"원";
}
}
이렇게 커피 주문프로그램을 만들어보았다... 노란느낌표들은 스캐너를 닫지 않아서 생겼는데 한번 스캐너를 close하면 (System.in) 때문에 다시 열 수가 없다.
처음엔 그 이유를 몰라서 BufferedReader(System.in) 으로 바꿔서도 써보고 별별 짓들을 다 해봤는데
스캐너일 때는 No Such Element Exception, 버퍼드리더일 땐 IOException: Stream Closed 에러가 생긴다.
구글링을 하니 (system.in)을 close하지 않아서 라고 나와있어서 scan.close(); System.in.close(); 도 해보고 그래도 에러가 나고... 거의 1시간을 붙잡고 있었던것 같다.
근데 또 어떤 글을 보니 System.in <<은 한번 클로즈하면 다시 열수 없다고 그러더라... 그래서 아직까지도 팩트는 오리무중이어서 일단 스캐너를 close 하지 않고 코드를 짜보았다.
정확한 사실을 아시는 분이 있다면 댓글에 적어주시면 감사하겠습니다 :) (불쌍한 코린이에게 광명을...)