본문 바로가기
Java/JDBC

JDBC) MVC pattern (회원관리 프로젝트, 회원가입 처리)

by 박채니 2022. 5. 4.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


MVC pattern

* run → 실행 메소드가 있는 실행 클래스

* view → 사용자가 보게 될 메뉴 제공

* controller → 사용자가 메뉴 선택하면 controller에서 요청을 받아 시작 (dao에게 req)

* dao(Data Access Object) → DB에 접근하기 위한 클래스

* VO (value Object) → DB의 테이블과 대응하여 데이터를 담은 클래스 (filed ↔ column)

 


회원관리 프로젝트

MVC pattern에 따라 패키지 및 클래스들을 생성하였습니다.

 

Member Class (VO Class)

- Value Object

- Datebase 테이블과 대응

- field는 테이블의 컬럼과 대응

- VO 객체 하나가 테이블의 레코드와 대응

public class Member {
	/*
	 * ID       NOT NULL VARCHAR2(20)  
	 * NAME     NOT NULL VARCHAR2(100) 
	 * GENDER            CHAR(1)       
	 * BIRTHDAY          DATE          
	 * EMAIL    NOT NULL VARCHAR2(500) 
	 * POINT             NUMBER        
	 * REG_DATE          TIMESTAMP(6)  
	 */
	
	private String id;
	private String name;
	private String gender;	// char도 String으로 처리! 나중에 복잡해짐
	private Date birthday;	// java.sql.Date
	private String email;
	private int point;
	private Timestamp regDate;	// java.sql.timestamp
	
	public Member() {
		super();
	}

	public Member(String id, String name, String gender, Date birthday, String email, int point, Timestamp regDate) {
		super();
		this.id = id;
		this.name = name;
		this.gender = gender;
		this.birthday = birthday;
		this.email = email;
		this.point = point;
		this.regDate = regDate;
	}

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}

	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}

	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}

	public Timestamp getRegDate() {
		return regDate;
	}
	public void setRegDate(Timestamp regDate) {
		this.regDate = regDate;
	}

	@Override
	public String toString() {
		return "Member [id=" + id + ", name=" + name + ", gender=" + gender + ", birthday=" + birthday + ", email="
				+ email + ", point=" + point + ", regDate=" + regDate + "]";
	}
}

java.sql.Date와 DB에서의 date 모두 각각 사용하면 년/월/일 시:분:초까지 표현할 수 있지만,

JDBC로 통신하는 와중에 시:분:초의 정보는 사라집니다.

 

따라서 JDBC에서의 Date는 년/월/일까지만 표현 가능하며, 시:분:초까지 표현하고 싶다면 Timestamp를 사용해야 합니다.

 

MemberRun (RUN)

package member.run;

import member.view.MemberMenu;

public class MemberRun {
	public static void main(String[] args) {
		new MemberMenu().mainMenu();
		
		System.out.println("==== 이용해주셔서 감사합니다. ====");
	}
}

 

MemberMenu (VIEW)

- 사용자에게 메뉴 노출

- 사용자 입력 값 처리

- 메뉴 선택 시 controller의 메소드 호출(요청)

회원가입

package member.view;

import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

import member.controller.MemberController;
import member.model.vo.Member;

public class MemberMenu {
	private Scanner sc = new Scanner(System.in);
	private MemberController memberController = new MemberController();
	private SimpleDateFormat dateFormatRegDate = new SimpleDateFormat("yyyyMMdd");
	
	public void mainMenu() {
		String menu = "\n******** 회원 정보 관리 ********\n"
				+ "1. 전체 조회\n"
				+ "2. 아이디 조회\n"
				+ "3. 이름 검색 \n"
				+ "4. 회원가입\n"
				+ "5. 회원 정보 변경\n"
				+ "6. 회원 탈퇴\n"
				+ "0. 프로그램 종료\n"
				+ "*****************************\n"
				+ "선택 : ";
	
		while(true) {
			System.out.print(menu);
			String choice = sc.next();
			
			Member member = null;
			int result = 0;
			
			switch(choice) {
			case "1" : break;
			case "2" : break;
			case "3" : break;
			case "4" : 
				member = inputMember();
				result = memberController.inputMember(member);
				System.out.println(result > 0 ? "> 회원가입 성공!" : "> 회원가입 실패!");
				break;
			case "5" : break;
			case "6" : break;
			case "0" : return;
			default : System.out.println("잘못 입력하셨습니다.");
			}
		}
	}
	
	/**
	 * 4. 회원가입
	 * 사용자 입력 값을 받아 member 객체 반환
	 */
	public Member inputMember() {
		System.out.print("> 아이디를 입력하세요 : ");
		String id = sc.next();
		System.out.print("> 이름을 입력하세요 : ");
		String name = sc.next();
		System.out.print("> 성별을 입력하세요(M/F) : ");
		String gender = String.valueOf(sc.next().toUpperCase().charAt(0));
		System.out.print("> 생일을 입력하세요(19990909) : ");
		String temp = sc.next();
		Date birthday = null;
		// 문자열 -> java.util.Date -> java.sql.Date
		try {
			birthday = new Date(dateFormatRegDate.parse(temp).getTime());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.print("> 이메일 주소를 입력하세요 : ");
		String email = sc.next();
		
		return new Member(id, name, gender, birthday, email, 0, null);
	}
}

* 성별 또한 char형으로 받으면 DB 자료형과 맞지 않으므로, char형을 String으로 변환하는 작업을 거쳤습니다.

 

* Date는 문자열로 받아 SimpleDateFormat을 통해 Date형으로 변환하였지만, SimpleDateFormat은 java.util.Date타입을 리턴해주므로, 다시 java.sql.Date 타입으로 변환해주는 작업을 더하였습니다.

 

회원이 4번을 선택하면 inputMember() 메소드가 실행되며,

리턴 받은 Member 객체를 MemberController 클래스의 inputMember()메소드로 넘겨줍니다.

 

MemberController (Controller)

package member.controller;

import member.model.dao.MemberDao;
import member.model.vo.Member;

public class MemberController {
	
	private MemberDao memberDao = new MemberDao();
	
	// 4. 회원가입
	public int inputMember(Member member) {
		int result = memberDao.insertMember(member);
		return result;
	}
}

MemberMenu클래스에서 넘겨 받은 Member 객체를 다시 MemberDao 클래스의 insertMember()로 넘겨줍니다.

 

 

MemberDao (DAO)

- Database Access Object

- 전달 받은 데이터를 바탕으로 database에 질의(DML/DQL) 하는 객체

package member.model.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import member.model.vo.Member;

public class MemberDao {
	final String driverClass = "oracle.jdbc.OracleDriver";
	final String url = "jdbc:oracle:thin:@localhost:1521:xe";	//db접속프로토콜@ip:포트:db명(sid)
	final String user = "student";
	final String password = "student";
	
	// 4. 회원가입
	public int insertMember(Member member) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = "insert into member values (?, ?, ?, ?, ?, default, default)";
		
		try {
			// 1. jdbc driver class 등록
			Class.forName(driverClass);

			// 2. Connection 객체 생성 & autoCommit false로 설정 (기본값 true)
			conn = DriverManager.getConnection(url, user, password);
			conn.setAutoCommit(false);
			
			// 3. PreparedStatement 객체 생성 & 미완성 쿼리 값 대입
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member.getId());
			pstmt.setString(2, member.getName());
			pstmt.setString(3, member.getGender());
			pstmt.setDate(4, member.getBirthday());
			pstmt.setString(5, member.getEmail());
			
			// 4. executeUpdate 실행 & 정수형(처리된 행 수) 리턴 값
			result = pstmt.executeUpdate();
			
			// 5. 트랜잭션 처리 
			conn.commit();
		} catch (ClassNotFoundException | SQLException e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			// 6. 자원반납
			try {
				pstmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}
}

* if(result > 0) commit; 해줘도 되지만, 그 전까지 문제가 없었다면 commit처리가 잘 되므로 생략해도 됨!

(안전한 코딩을 하려면 if절 추가해주기)

 

* 자원 반납 시 catch절에 Exception 예외를 모두 받아 모든 예외가 발생할 때를 대비해줌

 

넘겨 받은 Member 객체를 가지고 DB에 DML작업을 해주어 insert 처리를 해주었고,

처리된 행의 수를 받아 return 해주어 MemberController 클래스의 insertMember()로 넘겨주고, 다시 그 값을 받아서 MemberMenu로 넘겨주어 해당 값을 가지고 회원가입 처리가 되었는 지 안 되었는 지에 대한 여부를 사용자에게 리턴 해주었습니다.

 

 

@회원가입해보기

******** 회원 정보 관리 ********
1. 전체 조회
2. 아이디 조회
3. 이름 검색 
4. 회원가입
5. 회원 정보 변경
6. 회원 탈퇴
0. 프로그램 종료
*****************************
선택 : 4
> 아이디를 입력하세요 : chany
> 이름을 입력하세요 : 박채니
> 성별을 입력하세요(M/F) : F
> 생일을 입력하세요(19990909) : 19990119
> 이메일 주소를 입력하세요 : chany@abc.com
> 회원가입 성공!

 

select * from member;

 

 

나머지 기능들은 아래 링크 참고!
https://chanychu.tistory.com/212

 

[실습문제] 회원정보 수정/삭제/검색 완성시키기

안녕하세요, 코린이의 코딩 학습기 채니 입니다. 개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다. 전체 회원 조회  0 ~ n건이 조회될 때, 실제 조회 결과가 0건이면 빈 

chanychu.tistory.com