package net.bitacademy.java41.step10;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import java.util.Scanner;
/* Statememt vs. PreparedStatement
* 1) 소스 가독성:
* SQL문이 복잡할 수록 읽기 어렵다 <==> 간결하다.
*
* 2) 바이너리 데이터(이미지, 음악, 동영상 등) 입력:
* 불가(base64와 같은 문자열 형식으로 인코딩 시 가능) <==> 가능
*
* 3) 반복 수행 시 속도:
* 매번 SQL문을 DBMS 형식에 따라 변환 속도 느리다
*
<==> 한번만 변환, 그리고 실행, 속도 빠르다.
*/
public class RedApp {
protected Scanner scanner;
private Member member;
public RedApp() {
scanner = new Scanner(System.in);
}
public void execute() {
while(true) {
System.out.print("명령>");
String command = scanner.nextLine().toLowerCase();
if (command.equals("add")) {
member = null;
add();
} else if (command.equals("list")) {
member = null;
list();
} else if (command.startsWith("view")) {
//명령>view a@test.com
String[] values = command.split(" ");
view( values[1] );
} else if (command.equals("update")) {
if (member != null) {
update();
} else {
System.out.println("먼저 멤버를 조회하세요!");
}
} else if (command.equals("delete")) {
if (member != null) {
detele();
} else {
System.out.println("먼저 멤버를 조회하세요!");
}
} else if (command.equals("quit")) {
System.out.println("안녕!");
break;
} else {
System.out.println("지원하지 않는 명령어입니다.");
}
}
}
private void add(){
Member m = new Member();
System.out.print("이름 : ");
m.setName(scanner.nextLine());
System.out.print("전화번호 : ");
m.setPhone(scanner.nextLine());
System.out.print("이메일 : ");
m.setEmail(scanner.nextLine());
System.out.print("블로그 : ");
m.setBlog(scanner.nextLine());
System.out.print("나이 : ");
m.setAge( Integer.parseInt( scanner.nextLine() ) );
System.out.print("등록하시겠습니까?(y/n)");
if(scanner.nextLine().toLowerCase().equals("y")){
m.setRegDate(new Date());
Connection con = null;
//등록은 sql문을 전달만하고 DB에서 기능이 이루어지기때문에 커넥션과 스테이트먼트만 준비
PreparedStatement stmt = null;
try {
String driverClass = System.getProperty("driverClass");
//커넥션 인터페이스를 구현하는 드라이버클래스 정보 를 담는다.
Class.forName(driverClass);
//담은 클래스정보를 로딩
con = DriverManager.getConnection(
//매니저를 이용 커넥션 인터페이스를 구현한 클래스들 중에서
"jdbc:mysql://localhost/test", "test", "test");
//즉 my sql과 연결된 모든 정보들중 해당 주소와 아이디 비번 값을 가진
// 테이블에 연결
stmt = con.prepareStatement(
// sql문 보내기
"insert into MEMBERS(MNAME,PHONE,EMAIL,BLOG,AGE,REG_DATE)"
+ " values(?,?,?,?,?,now())");
// insert 로 칼럼 만들고 값에다가 ? now()는 현재 시간
stmt.setString(1, m.getName());
// 덱스 번호 순서에따라 입력받은 데이터를 얻어와서 입력
stmt.setString(2, m.getPhone());
//
stmt.setString(3, m.getEmail());
//
stmt.setString(4, m.getBlog());
stmt.setInt(5, m.getAge());
int count = stmt.executeUpdate();
//
System.out.println("등록되었습니다!");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {stmt.close();} catch(Exception e) {}
try {con.close();} catch(Exception e) {}
}
} else {
System.out.println("등록 취소하였습니다!");
}
}
private void list() {
Connection con = null; //java.sql에 정의된 인터페이스 를 선언
Statement stmt = null; //서버에 sql문을 보낼 도구
ResultSet rs = null;
//DB에 저장된 데이터를 가져오기 위한도구 위한 도구.
try {
// MySQL 서버에 연결할 도구를 준비
// - JDBC Driver 클래스 중(.jar 파일에 들어있는 클래스들 중에서)
// java.sql.Driver 인터페이스를 구현한 클래스를 먼저 로딩한다.
// - 이 클래스가 java.sql.Connection 인터페이스를 구현한 클래스를 알고 있다.
//
String driverClass = System.getProperty("driverClass"); // 시스템 클래스의 getProperty 메소드를 이용 driverclass의 정보를 얻어와
Class.forName(driverClass);
// String 타입으로 반환한다. 이것을 class.forName 메소드를 이용 해당클래스들을
//Class.forName("com.mysql.jdbc.Driver");
// 로딩한다.
// 1. 서버와 연결
con = DriverManager.getConnection(
//로딩된 클래스들중 mysql인터페이스를 구현하는 클래스정보를
"jdbc:mysql://localhost/test", "test", "test"); //해당 주소,아이디,비밀번호 가진 mysql 데이터와 연결
// 2. SQL문을 보낼 도구를 얻기
// - createStatement()를 호출하여 SQL문을 서버에 보낼 도구를 얻는다.
stmt = con.createStatement();
// 3. SQL을 서버에 보냄
// - executeQuery()는 서버에 SQL문을 보낸다.
// - 서버는 결과를 준비한다.
// - executeQuery()는 서버에서 결과를 가져올 도구를 리턴한다.
rs = stmt.executeQuery(
"select MNAME,PHONE,EMAIL from MEMBERS order by MNAME"); // order by 는 이름순으로 정렬해서
// 4. 서버의 결과를 가져와서 출력
// - next()를 호출하여 서버로부터 1 레코드의 결과를 가져온다.
while(rs.next()) {
System.out.print(rs.getString("MNAME") + ",");
//보내기위한 도구 rs에서 결과를 가져오는 메소드 next 호출
System.out.print(rs.getString("PHONE") + ",");
//읽어올 데이타가 없을경우 1을 반환 false를 반환
System.out.println(rs.getString("EMAIL"));
//문자열로 반환 화면에 출력
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {rs.close();} catch (Exception e) {}
//마찬가지로 연결도구 모두 종료.
try {stmt.close();} catch (Exception e) {}
try {con.close();} catch (Exception e) {}
}
}
private void detele() {
Connection con = null;
//연결도구
Statement stmt = null; //보낼도구
try {
String driverClass = System.getProperty("driverClass");
//역시 마찬가지로 연결을 위한 인터페이스를 구현하는 클래스를 로딩
Class.forName(driverClass);
con = DriverManager.getConnection(
//로딩된 클래스에 manager 를 사용 해당주소로 연결
"jdbc:mysql://localhost/test", "test", "test");
stmt = con.createStatement();
//보낼도구 준비
int count = stmt.executeUpdate(
// excuteUpdate 메소드를 이용 sql문을 이용 보냄.
"delete from MEMBERS"
+ " where EMAIL='" + member.getEmail() + "'");
// view 에서 이메일을 입력했을 경우 인스턴스변수 m 은 null 이 아니게되고.
// excuteUpdate 는 조건에 맞는 칼럼을 삭제하고 칼럼수를 인트로 반환
if (count > 0) {
// 0보다 큰경우는 삭제를 확인
System.out.println("삭제되었습니다!");
} else {
System.out.println("해당 이메일의 멤버를 찾을 수 없습니다!");
// 그렇지 않은 경우는 해당 메세지 출력
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {stmt.close();} catch(Exception e) {}
try {con.close();} catch(Exception e) {}
}
}
private void update() {
Member copy = member.clone();
System.out.printf("이메일(%1$s):\n", member.getEmail());
// 이메일은 키(아이디)값이기 때문에 변경을 하지 않는다.
System.out.printf("이름(%1$s):", member.getName());
String value = scanner.nextLine();
if (value.length() > 0) {
copy.setName(value);
}
System.out.printf("전화(%1$s):", member.getPhone());
value = scanner.nextLine();
if (value.length() > 0) {
copy.setPhone(value);
}
System.out.printf("블로그(%1$s):", member.getBlog());
value = scanner.nextLine();
if (value.length() > 0) {
copy.setBlog(value);
}
System.out.printf("나이(%1$d):", member.getAge());
value = scanner.nextLine();
if (value.length() > 0) {
copy.setAge( Integer.parseInt(value) );
}
System.out.print("변경하시겠습니까?(y/n)");
if(scanner.nextLine().toLowerCase().equals("y")){
Connection con = null;
PreparedStatement stmt = null;
try {
String driverClass = System.getProperty("driverClass"); //역시 해당드라이버들 로딩
Class.forName(driverClass);
//로딩
con = DriverManager.getConnection(
// 해당 주소 연결
"jdbc:mysql://localhost/test", "test", "test");
stmt = con.prepareStatement(
//sql문 전달.
"update MEMBERS set"
+ " MNAME=?,PHONE=?,BLOG=?,AGE=?,REG_DATE=now()"
// ? 지역에 setString 을 이용 인덱스번호대로 입력한다.
+ " where EMAIL=?");
stmt.setString(1, copy.getName());
stmt.setString(2, copy.getPhone());
stmt.setString(3, copy.getBlog());
stmt.setInt(4, copy.getAge());
stmt.setString(5, member.getEmail());
int count = stmt.executeUpdate();
//역시 count로 반환
if (count > 0) {
System.out.println("변경되었습니다!");
//해당 데이터 변경
} else {
System.out.println("해당 이메일의 멤버를 찾을 수 없습니다.");
//조건에 맞는 해당 데이터가 없을경우 count 값은 -1이기 때문에.
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {stmt.close();} catch(Exception e) {}
try {con.close();} catch(Exception e) {}
}
} else {
System.out.println("변경 취소하였습니다!");
}
}
private void view(String email) {
Connection con = null;
//view 도 역시 list와 같이 데이터를 불러와야하기 때문에 ResultSet을 준비 한다.
Statement stmt = null;
ResultSet rs = null;
try {
String driverClass = System.getProperty("driverClass");
//해당 인터페이스를 구현하는 클래스 정보를 담는다
Class.forName(driverClass);
//클래스 로딩
con = DriverManager.getConnection(
"jdbc:mysql://localhost/test", "test", "test");
//연결
stmt = con.createStatement();
//sql문 전달.
rs = stmt.executeQuery(
// 해당 칼럼 선택.
"select MNAME,PHONE,EMAIL,BLOG,AGE,REG_DATE"
+ " from MEMBERS"
+ " where EMAIL='" + email + "'");
// 조건은 입력받은 이메일 주소와 같은 이메일 주소데이타.
if (rs.next()) {
//새로운 멤머 객체를 만들고 set 메소드를 이용 그안에 파라미터로
member = new Member();
//읽기위한 도구 rs(ResultSet)으로 getString 메소드 호출 파라미터로
member.setName(rs.getString("MNAME"));
//칼럼이름.
member.setPhone(rs.getString("PHONE"));
member.setEmail(rs.getString("EMAIL"));
//즉 입력된 칼럼이름 안에 데이터를 문자열 타입으로 변환 Member 인스턴스에 생성한다.
member.setBlog(rs.getString("BLOG"));
member.setAge(rs.getInt("AGE"));
member.setRegDate(rs.getDate("REG_DATE"));
} else {
throw new Exception("해당 이메일의 멤버가 없습니다.");
//
}
} catch (Exception e) {
e.printStackTrace();
return;
} finally {
try {rs.close();} catch (Exception e) {}
try {stmt.close();} catch (Exception e) {}
try {con.close();} catch (Exception e) {}
}
System.out.println("이름:" + member.getName());
//셋팅된 Member 객체에서 출력.
System.out.println("전화:" + member.getPhone());
System.out.println("이메일:" + member.getEmail());
System.out.println("블로그:" + member.getBlog());
System.out.println("나이:" + member.getAge());
System.out.printf("등록일:%1$tY-%1$tm-%1$td \n", member.getRegDate());
}
public static void main(String[] args) {
RedApp app = new RedApp();
app.execute();
}
}