MVC
① [Run 클래스] 실행시키기 위해 View를 호출한다.
② [View 클래스] 사용자가 Scanner로 전달값을 입력하면서 Controller를 호출한다.
③ [Controller 클래스] View에서 전달받은 값을 가공 처리한 후 Service로 전달 및 호출한다.
④ [Service 클래스] Connection을 생성하여 DB에 접속하고, Connection 객체와 Controller에서 전달받은
데이터를 Dao에 전달한다.
⑤ [Dao 클래스] SQL문을 실행해서 DB에 직접 접근하고, ResultSet이나 int형 변수로 결과를 받아 Service로
리턴한다.
⑥ [Service 클래스] Dao로부터 결과를 받아 트랜잭션 처리한 후 결과를 Controller로 리턴한다.
⑦ [Controller 클래스] Service로부터 반환 받은 결과에 따라 View(성공/실패 화면)를 결정한다.
⑧ [View 클래스] print문으로 결과를 출력한다.
VO
package member.model.vo;
import java.sql.Date;
public class Member {
private int userNo;
private String userId;
private String userPw;
private String userName;
private String gender;
private int age;
private String email;
private String phone;
private String address;
private String hobby;
private Date enrollDate;
public Member() {
super();
}
public Member(int userNo, String userId, String userPw, String userName, String gender
, int age, String email, String phone, String address, String hobby
, Date enrollDate) {
super();
this.userNo = userNo;
this.userId = userId;
this.userPw = userPw;
this.userName = userName;
this.gender = gender;
this.age = age;
this.email = email;
this.phone = phone;
this.address = address;
this.hobby = hobby;
this.enrollDate = enrollDate;
}
public Member(String userId, String userPw, String userName, String gender, int age
, String email, String phone, String address, String hobby) {
super();
this.userId = userId;
this.userPw = userPw;
this.userName = userName;
this.gender = gender;
this.age = age;
this.email = email;
this.phone = phone;
this.address = address;
this.hobby = hobby;
}
public Member(String userId, String userPw, String email, String phone, String address) {
super();
this.userId = userId;
this.userPw = userPw;
this.email = email;
this.phone = phone;
this.address = address;
}
public int getUserNo() {
return userNo;
}
public void setUserNo(int userNo) {
this.userNo = userNo;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPw() {
return userPw;
}
public void setUserPw(String userPw) {
this.userPw = userPw;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Date getEnrollDate() {
return enrollDate;
}
public void setEnrollDate(Date enrollDate) {
this.enrollDate = enrollDate;
}
@Override
public String toString() {
return "Member [userNo=" + userNo + ", userId=" + userId + ", userPw=" + userPw
+ ", userName=" + userName + ", gender=" + gender + ", age=" + age + ", email="
+ email + ", phone=" + phone + ", address=" + address + ", hobby=" + hobby
+ ", enrollDate=" + enrollDate + "]";
}
}
Run
package member.run;
import member.view.MemberView;
public class Run {
public static void main(String[] args) {
new MemberView().mainMenu();
}
}
View
package member.view;
import java.util.ArrayList;
import java.util.Scanner;
import member.controller.MemberController;
import member.model.vo.Member;
public class MemberView {
private Scanner sc = new Scanner(System.in);
private MemberController mc = new MemberController();
public void mainMenu() {
while(true) {
System.out.println("========회원관리 프로그램=========");
System.out.println("1. 회원 추가");
System.out.println("2. 회원 전체 조회");
System.out.println("3. 회원 아이디로 검색");
System.out.println("4. 회원 이름 검색");
System.out.println("5. 회원 정보 변경");
System.out.println("6. 회원 탈퇴");
System.out.println("0. 프로그램 종료");
System.out.println("==============================");
System.out.println("원하는 메뉴 번호를 입력하세요. ");
int menu = sc.nextInt();
sc.nextLine();
switch(menu) {
case 1: insertMember(); break;
case 2: selectAll(); break;
case 3: searchById(); break;
case 4: searchByName(); break;
case 5: updateMember(); break;
case 6: deleteMember(); break;
case 0: System.out.println("프로그램을 종료합니다."); return;
default: System.out.println("메뉴번호를 잘못 입력하였습니다.");
}
}
}
// 회원 추가용 화면
// 추가하고자 하는 회원의 정보를 입력받아 추가를 요청하는 화면
// 1. 회원 추가 화면
public void insertMember() {
System.out.println("-------회원 추가-------");
// 입력
// 회원번호(시퀀스) enrollDate(default SYSDATE) 두 컬럼에 대해서 입력받지 않는다.
System.out.println("아이디: ");
String userId = sc.nextLine();
System.out.println("비밀번호: ");
String userPw = sc.nextLine();
System.out.println("이름: ");
String userName = sc.nextLine();
System.out.println("성별: ");
String gender = sc.nextLine().toUpperCase();
System.out.println("나이: ");
int age = sc.nextInt();
sc.nextLine();
System.out.println("이메일: ");
String email = sc.nextLine();
System.out.println("휴대번호: (- 없이 숫자만 입력)");
String phone = sc.nextLine();
System.out.println("주소: ");
String address = sc.nextLine();
System.out.println("취미: ");
String hobby = sc.nextLine();
// Controller에 있는 메소드를 호출한다.
mc.insertMember(userId, userPw, userName, gender, age, email, phone, address, hobby);
}
// 2. 회원 전체 조회 화면
public void selectAll() {
System.out.println("--------회원 전체 조회--------");
// Controller에 회원 전체 조회 요청
mc.selectAll();
}
// 3. 회원 아이디로 검색하는 화면
public void searchById() {
System.out.println("-------회원 아이디로 검색-------");
System.out.println("검색할 회원의 아이디 입력: ");
String userId = sc.nextLine();
// 입력한 아이디로 Controller에 요청하기
mc.searchById(userId);
}
// 4. 회원 이름으로 검색하는 화면
public void searchByName() {
System.out.println("--------회원 이름으로 검색--------");
System.out.println("검색할 회원의 이름 입력: ");
String userName = sc.nextLine();
mc.searchByName(userName);
}
// 5. 회원 정보를 수정하는 화면
public void updateMember() {
System.out.println("---------회원 정보 변경---------");
// 변경할 회원의 아이디
System.out.println("변경할 회원의 아이디: ");
String userId = sc.nextLine();
// 변경할 정보들
System.out.println("변경할 비밀번호 입력: ");
String userPw = sc.nextLine();
System.out.println("변경할 이메일 입력: ");
String email = sc.nextLine();
System.out.println("변경할 휴대번호 입력: ");
String phone = sc.nextLine();
System.out.println("변경할 주소 입력: ");
String address = sc.nextLine();
// 회원 정보 수정 요청
mc.updateMember(userId, userPw, email, phone, address);
}
// 6. 회원 탈퇴하는 화면
public void deleteMember() {
System.out.println("---------회원 탈퇴---------");
System.out.println("회원 탈퇴할 아이디: ");
String userId = sc.nextLine();
mc.deleteMember(userId);
}
//---------------------------------------------------
// 서비스 요청 시 사용자가 보게될 응답 화면
// 서비스 요청 성공 시 응답 화면
public void displaySuccess(String message) {
System.out.println("서비스 요청 성공: " + message);
}
// 서비스 요청 실패시 응답 화면
public void displayFail(String message) {
System.out.println("서비스 요청 실패: " + message);
}
// 전체 조회 결과가 없을 때 응답 화면
public void displayNoData(String message) {
System.out.println(message);
}
// 전체 조회 결과가 있을 때 응답 화면
public void displayList(ArrayList<Member> list) {
System.out.println("조회된 결과는 " + list.size() + "건입니다.");
for(Member m : list) {
System.out.println(m);
}
}
// 조회결과가 하나일 때
public void displayOne(Member m) {
System.out.println("조회된 결과는 다음과 같습니다.");
System.out.println(m);
}
}
Controller
package member.controller;
import java.util.ArrayList;
import member.model.dao.MemberDao;
import member.model.service.MemberService;
import member.model.vo.Member;
import member.view.MemberView;
public class MemberController {
public void insertMember(String userId, String userPw, String userName, String gender
, int age, String email, String phone, String address
, String hobby) {
Member m = new Member(userId, userPw, userName, gender, age, email, phone, address
, hobby);
int result = new MemberService().insertMember(m);
if(result > 0) {
new MemberView().displaySuccess("회원 추가 성공");
} else {
new MemberView().displayFail("회원 추가 실패");
}
}
// 사용자의 회원 전체 조회 요청을 처리해주는 메소드
public void selectAll() {
// 결과값을 담을 변수
// SELECT - ResultSet -> ArrayList<Member>
ArrayList<Member> list = new MemberService().selectAll();
// DAO에서 작업을 끝마친 결과를 전달받아 해당 결과를 토대로 어떤 화면을 보여줄 지 정하여
// view에 전달한다.
// 조회결과가 있는지 없는지 판단 후 사용자가 보게될 화면을 지정한다.
if(list.isEmpty()) { // list가 비어있어 true인 경우
new MemberView().displayNoData("전체 조회 결과가 없습니다.");
} else { // list 조회된 경우 list에 Member가 담겨있음
new MemberView().displayList(list);
// toString()을 오버라이딩하여 목록이 죽 나온다.
// 만약 toString()이 오버라이딩되지 않으면 주소값만 출력된다.
}
}
// 사용자가 입력한 아이디로 검색 요청을 처리해주는 메소드
public void searchById(String userId) {
Member m = new MemberService().searchById(userId);
if(m == null) {
new MemberView().displayNoData(userId+"에 해당하는 조회 결과가 없습니다.");
} else {
new MemberView().displayOne(m);
}
}
// 사용자가 입력한 이름으로 검색 요청을 처리해주는 메소드
public void searchByName(String userName) {
ArrayList<Member> list = new MemberService().searchByName(userName);
if(list == null) {
new MemberView().displayNoData(userName + "에 해당하는 조회 결과가 없습니다.");
} else {
new MemberView().displayList(list);
}
}
// 사용자가 입력한 정보들을 변경 요청을 처리해주는 메소드
public void updateMember(String userId, String userPw, String email, String phone
, String address) {
int result = new MemberService().updateMember(userId, userPw, email, phone, address);
if(result > 0) {
new MemberView().displaySuccess("삽입에 성공했습니다.");
} else {
new MemberView().displayFail("삽입에 실패했습니다.");
}
}
// 사용자가 입력한 정보들을 삭제 요청 처리해주는 메소드
public void deleteMember(String userId) {
int result = new MemberService().deleteMember(userId);
if(result > 0) {
new MemberView().displaySuccess("회원 정보가 삭제되었습니다.");
} else {
new MemberView().displayFail("회원 정보 삭제에 실패했습니다.");
}
}
}
Template
: JDBC 과정 중 반복적으로 쓰이는 구문들이 각각의 메소드로 정의해둘 공간으로, 재사용을 목적으로 한다.
- 이 클래스에서의 모든 메소드들은 다 static 메소드로 만든다.
- 싱글톤 패턴: 메모리 영역에 단 한 번만 올라간 것을 재사용하는 개념이다.
package member.common;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcTemplate {
// DB와 접속된 Connection 객체를 생성해서 반환해주는 메소드
public static Connection getConnection() {
// Connection 객체 변수 생성
Connection conn = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC"
, "JDBC");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
// 전달받은 JDBC용 객체를 반납시켜주는 메소드(각 객체 별로 만든다)
// Connection 객체 반납 메소드
public static void close(Connection conn) {
try {
// conn이 null이면 nullPointerException이 발생하기 때문에 조건으로 확인해야 된다.
if(conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// Statement 객체 반납 메소드
// PreparedStatement 객체가 Statement 객체의 자식이기 때문에 다형성이 적용되어
// 매개변수로 전달이 가능하다.
public static void close(Statement stmt) {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// ResultSet 객체 반납 메소드
public static void close(ResultSet rset) {
try {
if(rset != null && !rset.isClosed()) {
rset.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// 전달받은 Connection 객체를 이용해서 트랜잭션 처리를 해주는 메소드
public static void commit(Connection conn) {
try {
if(conn != null && !conn.isClosed()) {
conn.commit();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// rollback 메소드
public static void rollback(Connection conn) {
try {
if(conn != null && !conn.isClosed()) {
conn.rollback();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Service
: 기존 DAO의 역할을 분담하는 역할을 한다.
- Controller에서 Connection 객체를 생성하여 Service를 호출한 후 Service를 거쳐 DAO로 넘어간다.
- DAO 호출 시에 Connection 객체와 기존에 넘기려는 매개변수도 함께 넘겨준다.
- DAO에서 처리가 끝나면 Service에서 해당 결과의 트랜잭션 처리를 한다.
→ Service를 추가함에 따라 DAO는 SQL문만을 처리하게 된다.
package com.kh.model.service;
import java.sql.Connection;
import java.util.ArrayList;
import com.kh.common.JDBCTemplate;
import com.kh.model.dao.MemberDao;
import com.kh.model.vo.Member;
public class MemberService {
public int insertMember(Member m) {
// Connection 객체 만들어주기
Connection conn = JDBCTemplate.getConnection();
// DAO를 호출하는 데 Controller에게 전달받은 요청값과 커넥션을 같이 넘긴다.
int result = new MemberDao().insertMember(conn, m);
// 결과에 따른 트랜잭션 처리해주기
if(result > 0) {
JDBCTemplate.commit(conn);
} else {
JDBCTemplate.rollback(conn);
}
// Connection 객체 반납하기
JDBCTemplate.close(conn);
return result;
}
// 전체 조회하기 위한 DB 접속
public ArrayList<Member> selectAll() {
Connection conn = JDBCTemplate.getConnection();
ArrayList<Member> list = new MemberDao().selectAll(conn);
// 조회 구문은 트랜잭션 처리를 할 필요가 없다.
// Connection 객체 반납하기
JDBCTemplate.close(conn);
return list;
}
public Member searchById(String userId) {
Connection conn = JDBCTemplate.getConnection();
Member m = new MemberDao().searchById(conn, userId);
// 조회 구문에서는 트랜잭션 처리X
JDBCTemplate.close(conn);
return m;
}
public ArrayList<Member> searchByName(String userName) {
Connection conn = JDBCTemplate.getConnection();
ArrayList<Member> list = new MemberDao().searchByName(conn, userName);
JDBCTemplate.close(conn);
return list;
}
public int updateMember(String userId, String userPw, String email, String phone, String address) {
Connection conn = JDBCTemplate.getConnection();
int result = new MemberDao().updateMember(conn, userId, userPw, email, phone, address);
if(result > 0) {
JDBCTemplate.commit(conn);
} else {
JDBCTemplate.rollback(conn);
}
JDBCTemplate.close(conn);
return result;
}
public int deleteMember(String userId) {
Connection conn = JDBCTemplate.getConnection();
int result = new MemberDao().deleteMember(conn, userId);
if(result > 0) {
JDBCTemplate.commit(conn);
} else {
JDBCTemplate.rollback(conn);
}
JDBCTemplate.close(conn);
return result;
}
}
DAO
package member.model.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import member.model.vo.Member;
public class MemberDao {
public int insertMember(Connection conn, Member m) {
int result = 0;
PreparedStatement pstmt = null;
String sql = "INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, ?, ?, ?, ?, ?, ?, ?
, ?, ?, DEFAULT)";
try {
pstmt = conn.prepareStatement(sql);
// 미완성된 SQL문 완성시켜주기
pstmt.setString(1, m.getUserId());
pstmt.setString(2, m.getUserPw());
pstmt.setString(3, m.getUserName());
pstmt.setString(4, m.getGender());
pstmt.setInt(5, m.getAge());
pstmt.setString(6, m.getEmail());
pstmt.setString(7, m.getPhone());
pstmt.setString(8, m.getAddress());
pstmt.setString(9, m.getHobby());
result = pstmt.executeUpdate();
if(result > 0) {
conn.commit();
} else {
conn.rollback();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public ArrayList<Member> selectAll(){
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
ArrayList<Member> list = new ArrayList<>();
// 실행할 SQL문
String sql = "SELECT * FROM MEMBER";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC"
, "JDBC");
stmt = conn.createStatement();
rset = stmt.executeQuery(sql);
while(rset.next()) {
m.setUserNo(rset.getInt("USERNO"));
m.setUserId(rset.getString("USERID"));
m.setUserPw(rset.getString("USERPW"));
m.setUserName(rset.getString("USERNAME"));
m.setGender(rset.getString("GENDER"));
m.setAge(rset.getInt("AGE"));
m.setEmail(rset.getString("EMAIL"));
m.setPhone(rset.getString("PHONE"));
m.setAddress(rset.getString("ADDRESS"));
m.setHobby(rset.getString("HOBBY"));
m.setEnrollDate(rset.getDate("ENROLLDATE"));
list.add(m);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
rset.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
// 사용자에게 입력받은 아이디로 해당 회원이 있는지 정보 검색 처리하는 메소드
public Member searchById(String userId) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rset = null;
Member m = null;
String sql = "SELECT * FROM MEMBER WHERE USERID = ?";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC"
, "JDBC");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userId);
rset = pstmt.executeQuery();
if(rset.next()) {
m = new Member(rset.getInt("USERNO")
, rset.getString("USERID")
, rset.getString("USERPW")
, rset.getString("USERNAME")
, rset.getString("GENDER")
, rset.getInt("AGE")
, rset.getString("EMAIL")
, rset.getString("PHONE")
, rset.getString("ADDRESS")
, rset.getString("HOBBY")
, rset.getDate("ENROLLDATE"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
rset.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return m;
}
public ArrayList<Member> searchByName(String userName) {
Connection conn = null;
PreparedStatement pstmt= null;
ResultSet rset = null;
ArrayList<Member> list = new ArrayList<>();
String sql = "SELECT * FROM MEMBER WHERE USERNAME LIKE ?";
pstmt.setString(1, "%" + userName + "%");
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC"
, "JDBC");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userName);
rset = pstmt.executeQuery();
while(rset.next()) {
list.add(new Member(rset.getInt("USERNO")
, rset.getString("USERID")
, rset.getString("USERPW")
, rset.getString("USERNAME")
, rset.getString("GENDER")
, rset.getInt("AGE")
, rset.getString("EMAIL")
, rset.getString("PHONE")
, rset.getString("ADDRESS")
, rset.getString("HOBBY")
, rset.getDate("ENROLLDATE")));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
rset.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
public int updateMember(Member m) {
Connection conn = null;
PreparedStatement pstmt = null;
int result = 0;
String sql="UPDATE MEMBER"
+ " SET"
+ " USERPW=?"
+ ", EMAIL=?"
+ ", PHONE=?"
+ ", ADDRESS=?"
+ "WHERE USERID=?";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe",
"JDBC","JDBC");
pstmt=conn.prepareStatement(sql);
pstmt.setString(1,m.getUserPw());
pstmt.setString(2,m.getEmail());
pstmt.setString(3, m.getPhone());
pstmt.setString(4, m.getAddress());
pstmt.setString(5, m.getUserId());
result=pstmt.executeUpdate();
if(result>0) {
conn.commit();
}else {
conn.rollback();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public int deleteMember(String userId) {
Connection conn = null;
PreparedStatement pstmt = null;
int result = 0;
String sql = "DELETE FROM MEMBER WHERE USERID = ?";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC"
, "JDBC");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userId);
result = pstmt.executeUpdate();
if(result > 0) {
conn.commit();
} else {
conn.rollback();
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
}
DB
CREATE TABLE MEMBER(
USERNO NUMBER PRIMARY KEY,
USERID VARCHAR2(20) UNIQUE NOT NULL,
USERPW VARCHAR2(20) NOT NULL,
USERNAME VARCHAR2(20) NOT NULL,
GENDER CHAR(1) CHECK (GENDER IN('M', 'F')), -- M 또는 F만 들어올 수 있게 제약
AGE NUMBER,
EMAIL VARCHAR2(30),
PHONE CHAR(11),
ADDRESS VARCHAR2(100),
HOBBY VARCHAR2(50),
ENROLLDATE DATE DEFAULT SYSDATE NOT NULL
);