● 먼저, MySQL에서 테이블을 만들어줘야 한다.
create table user(
useridx int primary key auto_increment,
userid varchar(300) unique,
# userpw는 중복이 가능하므로 unique를 넣으면 안된다.
userpw varchar(300) not null,
username varchar(300) not null,
userage int,
userphone varchar(300),
useraddr varchar(1000)
);
create table product (
prodnum int primary key auto_increment,
prodname varchar(1000),
prodprice int,
prodamount int,
prodinfo varchar(4000),
# default 0 : 아무 값을 넣지 않으면 0이됨
likecnt int default 0
);
● 가장 먼저 나오는 페이지
package view;
import java.util.Scanner;
//index : 시작하는 페이지
public class Index {
public static void main(String[] args) {
System.out.println("22.03 개강반 최종 프로젝트 / UMS 프로그램 입니다.");
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("1. 회원가입\n2. 로그인\n3. 나가기");
int choice = sc.nextInt();
//Controller
if(choice == 3) {
System.out.println("안녕히가세요");
break;
}
switch(choice) {
case 1:
// 회원가입
// JoinView에서 생성자를 생성하고 코드를 작성한것을 메소드처럼 불러옴
// 많은 데이터들의 입출력이 일어나기 때문에 코드가 길어진다.
// 따라서 새로운 View를 띄워준다.(흐름을 이동시킨다)
new JoinView();
break;
case 2:
//로그인
new LoginView();
break;
default:
System.out.println("다시 입력하세요");
}
}
}
}
● Index에 있는 회원가입을 나타내는 코드
● new JoinView();를 불러오기 위한 생성자 생성
view / JoinView
package view;
import java.util.Scanner;
import dao.UserDAO;
import dto.UserDTO;
// 회원가입을 위해 생성
public class JoinView {
// 생성자도 메소드랑 같은 역할을 한다.
// 호출하면 내부로 와서 내부에 있는 내용 실행이 된다.
// JoinView 생성자에 코드를 작성하고 Index에서 메소드처럼 불러오기
public JoinView() {
Scanner sc = new Scanner(System.in);
//새로 가입할 "회원의 정보들" 을 데이터베이스에 저장해야 하므로
//기능을 구현해 놓은 DAO가 필요하고, 회원 관련된 데이터이므로
//UserDAO를 사용해야 한다.
UserDAO udao = new UserDAO();
System.out.print("아이디 : ");
String userid = sc.next();
// userid를 생성할때 중복검사 할 도구가 필요하다.
// 데이터와 통신할 클래스를 별도로 만드는데 DAO로 관리하면 된다.
// DAO에는 데이터베이스와 직접 통신할 DBConnection Class와 직접 소통하는 클래스로 나눌 것이다.
// UserDAO에서 만든 메소드를 이용해 사용자 중복 검사를 실시하자
if(udao.checkDup(userid)) {
System.out.print("비밀번호 : ");
String userpw = sc.next();
System.out.print("이름 : ");
String username = sc.next();
System.out.print("나이 : ");
int userage = sc.nextInt();
System.out.print("핸드폰 번호 : ");
String userphone = sc.next();
System.out.print("주소 : ");
// 새롭게 스캐너 객체를 만든이유는 nextLine()을 제대로 사용하기 위해서
sc = new Scanner(System.in);
String useraddr = sc.nextLine();
//여기까지 왔다면 회원 가입에 필요한 모든 정보를 입력받았다는
//뜻이므로, UserTable에 이 모든 데이터들을 저장해 주어야 한다.
//저장하는 기능적인 코드들은 View에서 구현하는 것이 아니고
//Userdao에 구현해 놓고 메소드를 호출하는 식으로 사용한다.
//호출시 넘겨주어야 할 데이터들이 총 6개나 되므로 UserDTO 타입의
//객체 하나로 포장해서 그 객체를 매개변수에 넘겨준다.
UserDTO user = new UserDTO(userid, userpw, username, userage, userphone, useraddr);
// UserDAO에서는 여기서 입력한 것들을 보내주기 위해서 포장한 DTO 객체를 매개변수로 넘겨준다.
// user을 UserDAO에 넘겨준다.
if(udao.join(user)) {
System.out.println("회원가입 성공!");
System.out.println(username+"님 가입을 환영합니다!");
}
else {
System.out.println("회원가입 실패 / 다시 시도해 주세요.");
}
}
else {
System.out.println("중복된 아이디가 있습니다. 다시 시도해 주세요.");
}
}
}
● 모든 클래스에 만들 필요 없이 여기에 한번에 만들고 불러오는 형식으로 사용
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DBConnection {
private static Connection conn;
public static Connection getConnection() {
// 싱글톤 패턴 : 단 하나의 객체만 만들어서 사용하도록 설계된 패턴
if(conn == null) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("드라이버 로딩 성공!");
// 다리를 짓고자 하는 목적지
String url = "jdbc:mysql://localhost:3306/web0315";
String user = "root";
String password = "1234";
conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException cnfe) {
System.out.println("드라이버 로딩 실패 : " + cnfe);
} catch(SQLException sqle) {
System.out.println("DB 연결 실패 : " + sqle);
}
}
return conn;
}
}
● JoinView를 구성하기 위한 UserDAO
▼ view - JoinView 클래스에서 아래서 나와 있는 if(udao.checkDup(userid)) { 중복검사를 돌려주는 코드
if(udao.checkDup(userid)) {
System.out.print("비밀번호 : ");
String userpw = sc.next();
System.out.print("이름 : ");
String username = sc.next();
System.out.print("나이 : ");
int userage = sc.nextInt();
System.out.print("핸드폰 번호 : ");
String userphone = sc.next();
System.out.print("주소 : ");
sc = new Scanner(System.in);
String useraddr = sc.nextLine();
● UserDAO 내부 → 중복검사(checkDup)
// 중복 검사는 'read' 그래서 SQL문에서는 'select'를 사용한다.
// 우리가 받아올 userid를 맨 끝에 세팅을 할 거니까 '?'로 써준다.
// 있으면 중복, 아니면 중복 아님
public boolean checkDup(String userid) {
String sql = "select * from user where userid=?";
try {
// 만들어논 다리를 이용(만들어 놓은 다리 위를 왔다갔다 할 택배차 만들기)
// prepareStatement 메소드에 우리가 시행하고자 할 sql문을 넘겨주면서 뽑아준다.
ps = conn.prepareStatement(sql);
ps.setString(1, userid);
// executeUpdate() :
// 시스템에 변화가 생기는 쿼리문 수행(insert, update, delete)-변화된 행의 개수 리턴
// executeQuery() : 변화 없는 쿼리문 수행(select)-검색된 결과 리턴(ResultSet)
// 여기서는 select를 사용하니까 executeQuery()를 사용
// 가지고오는 결과가 ResultSet rs인데 테이블 자체를 받아온다.
// 테이블은 데이터가 아니기 때문에 rs.next를 사용해서 데이터를
// 가져오는 형식
rs = ps.executeQuery();
// 그냥 return하면 중복되는게 있으면 true니까 !rs.next();을 해야 한다.
// 그래야 중복된게 없어야 true가 나오니까
return !rs.next();
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return false;
}
● UserDAO 내부 → 회원가입(join)
public boolean join(UserDTO user) {
// values(?,?,?,?,?,?)에서 ?는 (userid,userpw,username,userage,userphone,useraddr)
// 값들이다.
String sql = "insert into user (userid,userpw,username,userage,userphone,useraddr) "
+ "values(?,?,?,?,?,?)";
try {
// JoinView에서 매개변수로 받을 값들을 사용
ps = conn.prepareStatement(sql);
ps.setString(1, user.userid);
ps.setString(2, user.userpw);
ps.setString(3, user.username);
ps.setInt(4, user.userage);
ps.setString(5, user.userphone);
ps.setString(6, user.useraddr);
// 여기서는 insert니까 executeUpdate()
// executeUpdate()는 ResultSet rs 사용 안해도 된다.
// 1개가 있으면 true
return ps.executeUpdate() == 1;
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return false;
}
●
package dao;
import java.util.HashMap;
public class Session {
//Session.datas.put("login_id","apple");
private static HashMap<String, String> datas = new HashMap<String, String>();
//Session.put("login_id","apple");
public static void put(String key, String value) {
datas.put(key, value);
}
public static String get(String key) {
return datas.get(key);
}
}
● Index 클래스에 있는 new LoginView(); 작성
package view;
import java.util.Scanner;
import dao.UserDAO;
public class LoginView {
public LoginView() {
Scanner sc = new Scanner(System.in);
UserDAO udao = new UserDAO();
System.out.print("아이디 : ");
String userid = sc.next();
System.out.print("비밀번호 : ");
String userpw = sc.next();
if(udao.login(userid,userpw)) {
System.out.println(userid+"님 어서오세요~");
//메인창 띄우기
new MainView();
}
else {
System.out.println("로그인 실패 / 다시 시도해 주세요.");
}
}
}
● LoginView에 있는 if(udao.login(userid,userpw)) {
완성하기 위해서
// apple abcd1234
public boolean login(String userid, String userpw) {
String sql = "select * from user where userid =? and userpw=?";
try {
ps =conn.prepareStatement(sql);
ps.setString(1, userid);
ps.setString(2, userpw);
rs = ps.executeQuery();
if(rs.next()) {
Session.put("login_id", userid);
// 검색은 pk(primary key)가 가장 빠름
// 그래서 pk인 useridx를 Session에 세팅하고 싶으면 아래와 같은 방법사용
// 정수니까 +""해서 문자열로 바꾸기
Session.put("login_idx", rs.getInt("useridx") + "");
return true;
}
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return false;
}
●
package view;
import java.util.Scanner;
import dao.ProductDAO;
import dao.ProductDAO;
import dao.Session;
public class MainView {
public MainView() {
Scanner sc = new Scanner(System.in);
ProductDAO pdao = new ProductDAO();
while(true) {
//우리가 만든 프로젝트는 무조건 main()부터 시작하는 프로그램이다.
//즉 진입점이 한개이기 때문에 아래와 같은 코드를 생략 가능하다.
//*웹 상이나 다른 프로그램에서는 진입점이 여러개일 수 있으므로
//아래처럼 로그인 되어있는지를 먼저 검사해주는것이 필요하다.
if(Session.get("login_id") == null) {
System.out.println("로그인 후 이용하세요");
break;
}
System.out.println("☆★☆★☆★☆★"+Session.get("login_id")+"님 어서오세요~☆★☆★☆★☆★\n"
+ "1. 상품추가\n2. 상품수정\n3. 상품삭제\n"
+ "4. 내 상품 보기\n5. 상품 검색\n6. 내 정보 수정\n7. 로그아웃");
int choice = sc.nextInt();
if(choice == 7) {
//로그아웃
System.out.println(Session.get("login_id")+"님 안녕히가세요~");
//로그인한 정보를 담아주는 Session에서 login_id라는 KEY 와 쌍을 이루고 있는 값은
//로그아웃을 했다면 없애주어야 한다. 따라서 null로 초기화 해주어야 한다.
Session.put("login_id", null);
break;
}
switch(choice) {
case 1:
//상품추가
new AddProductView();
break;
case 2:
//상품수정
new ModifyProductView();
break;
case 3:
//상품삭제
//내 상품 목록 띄워주고 번호 입력받아서 삭제시키기
System.out.println(pdao.getList());
System.out.print("삭제할 상품 번호 : ");
int prodnum = sc.nextInt();
if(pdao.removeProduct(prodnum)) {
System.out.println(prodnum+"번 상품 삭제 성공!");
}
else {
System.out.println("알 수 없는 오류 / 다음에 다시 시도해 주세요.");
}
break;
case 4:
//내 상품 보기
System.out.println("===========내가 올린 상품 목록===========");
System.out.println(pdao.getList());
System.out.println("===================================");
break;
case 5:
//내 정보 수정
new MyInfoView();
break;
}
}
}
}
● MainView에 있는 new AddProductView();을 만들기 위해 생성
● 상품 추가
package view;
import java.util.Scanner;
import dao.ProductDAO;
import dao.Session;
import dto.ProductDTO;
public class AddProductView {
public AddProductView() {
//상품에 관련된 정보에 접근할 객체인 pdao 생성(상품 관련된 기능들이 선언되어 있다.)
ProductDAO pdao = new ProductDAO();
Scanner sc = new Scanner(System.in);
System.out.print("상품 이름 : ");
String prodname = sc.nextLine();
System.out.print("상품 가격 : ");
int prodprice = sc.nextInt();
System.out.print("상품 재고 : ");
int prodamount = sc.nextInt();
System.out.print("상품 소개 : ");
sc = new Scanner(System.in);
String prodinfo = sc.nextLine();
//지금 추가중인 상품의 상품번호는 현재 "추가되어 있는 마지막 상품의 번호"+1로 설정해 주어야 한다.
//pdao에 getLastNum()을 만들어서 리턴받고 +1 해준 것을 상품 번호로 사용한다.
ProductDTO product = new ProductDTO(pdao.getLastNum()+1, prodname, prodprice,
prodamount, prodinfo, Session.get("login_id"));//올린 사람은 현재
// 로그인 되어 있는 유저이므로 세션에서 아이디를 받아온 후 사용
//포장이 끝났다면 pdao의 메소드에 객체 넘겨주기
if(pdao.addProduct(product)) {
System.out.println(prodname+" 상품 추가 완료!");
}
else {
System.out.println("알 수 없는 오류 / 다음에 다시 시도해 주세요.");
}
}
}
● MainView 클래스에 있는 new ModifyProductView(); 만들기 위해서 생성
● 상품 수정
package view;
import java.util.Scanner;
import dao.ProductDAO;
public class ModifyProductView {
public ModifyProductView() {
ProductDAO pdao = new ProductDAO();
Scanner sc = new Scanner(System.in);
//내가 올린 상품 목록 출력
System.out.println(pdao.getList());
System.out.print("수정할 상품 번호 : ");
int prodnum = sc.nextInt();
System.out.println("1. 가격수정\n2. 재고수정\n3. 설명수정");
int choice = sc.nextInt();
System.out.print("새로운 정보 : ");
sc = new Scanner(System.in);
String newData = sc.nextLine();
//세가지 입력받은 데이터를 DAO에 넘겨주기(행, 열, 새로운 데이터)
if(pdao.modifyProduct(prodnum,choice,newData)) {
System.out.println(prodnum+"번 상품이 정상적으로 수정되었습니다.");
}
else {
System.out.println("알 수 없는 오류 / 다음에 다시 시도해 주세요.");
}
}
}
● ModifyProductView 클래스에 있는 modifyProduct 메소드를 완성하기 위해 생성
public boolean modifyProduct(int prodnum, int choice, String newData) {
String[] cols = {"prodprice", "modstock", "moddetail"};
String sql = "update product set prodnum=?, " + cols[choice -1] + "=? where userid =?";
try {
ps = conn.prepareStatement(sql);
ps.setInt(1, prodnum);
ps.setString(2, newData);
ps.setString(3, Session.get("login_id"));
return ps.executeUpdate() == 1;
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return false;
}
● MainView에 있는 new MyInfoView()를 완성하기 위해 만듬
package view;
import java.util.Scanner;
import dao.ProductDAO;
import dao.UserDAO;
public class MyInfoView {
public MyInfoView() {
Scanner sc = new Scanner(System.in);
UserDAO udao = new UserDAO();
ProductDAO pdao = new ProductDAO();
System.out.println(udao.myInfo());
System.out.println("1. 비밀번호 수정\n2. 핸드폰 번호 수정\n3. 주소 수정\n4. 수정 취소\n5. 회원탈퇴");
int choice = sc.nextInt();
if(choice == 4) {
System.out.println("메인으로 돌아갑니다.");
} else if(choice == 5) {
System.out.print("비밀번호 재입력 : ");
String userpw = sc.next();
//비밀번호 검사를 위해 udao의 checkPw() 호출
if(udao.checkPw(userpw)) {
//회원탈퇴 진행
//탈퇴 진행 시 현재 탈퇴를 하려는 회원이 올린 모든 상품들도 삭제 혹은 사용불가 처리를 해주어야 한다.
//후에 삽입될 데이터와 충돌이 발생할 수 있기 때문이다. 상품을 관리할 pdao를 통해 removeAll()을
//먼저 진행해준다. *실제 DB 환경에서도 상품 삭제가 먼저 되어야지만 회원을 탈퇴 시킬 수 있다.
pdao.removeAll();
//상품까지 깨끗하게 처리되었으므로 실제 회원 데이터 삭제 진행
if(udao.leaveId()) {
//아련하게 인사
System.out.println("그동안 이용해 주셔서 감사합니다...☆ 기다릴게요....");
}
}
//비밀번호 검사 실패
else {
System.out.println("비밀번호 오류");
}
}
//무언가 회원 정보를 수정하려고 선택했을 때
else {
System.out.print("새로운 정보 : ");
sc = new Scanner(System.in);
String newData = sc.nextLine();
boolean check = false;
// choice는 "1. 비밀번호 수정 2. 핸드폰 번호 수정 3. 주소 수정
check = udao.modifyUser(choice, newData);
if(check) {
System.out.println("정보 수정 완료!");
}
else {
System.out.println("정보 수정 실패");
}
}
}
}
● MyInfoView 클래스의 System.out.println(udao.myInfo());를
사용하기 위해 만들어 준다.
● MyInfoView 클래스의 udao.modifyUser(choice, newData);를
구현하기 위해 만들어 준다.
public String myInfo() {
String sql = "select * form user where userid =?";
try {
ps = conn.prepareStatement(sql);
ps.setString(1, Session.get("login_id"));
rs = ps.executeQuery();
while(rs.next()) {
String id = rs.getString("userid");
String pw = rs.getString("userpw");
String name = rs.getString("username");
int age = rs.getInt("userage");
String phonenum = rs.getString("userphone");
String addr = rs.getString("useraddr");
return "아이디 : " + id +"\n비번 : " + pw + "\n이름 : " + name + "\n나이 : " + age
+ "\n핸드폰 번호 : " + phonenum + "\n주소 : " + addr;
}
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return null;
}
public boolean modifyUser(int col, String newData) {
// col : 1. 비밀번호 수정 / 2.핸드폰 번호 수정 / 3. 주소수정
// ▼ SQL문이 일정하지가 않음(상황에따라 컬럼명이 바뀜)
// 1번 선택 : "update user set userpw= 'abcd1234' where userid ='apple'
// 2번 선택 : "update user set userphone= '01012341234' where userid='apple'
String[] cols ={"userpw","userphone","useraddr"};
// cols[col -1] 이렇게 하면 매개변수로 오는 번호에 -1을 해준다.
// 예를들어 비밀번호 수정하려고 1번을 넣어주면 1 - 1 = 0이 되서 cols에 있는 배열 0번자리가
// 와서 'userpw'를 사용한다.
String sql = "update user set " + cols[col -1] + "=? where userid=?";
try {
ps = conn.prepareStatement(sql);
ps.setString(1, newData);
ps.setString(2, Session.get("login_id"));
// 한개가 잘 수정이 됐다면 true
return ps.executeUpdate() == 1;
} catch (SQLException sqle) {
System.out.println("쿼리 수행 실패! : " + sqle);
}
return false;
}