JDBC

JDBC_2강

삼색이삼랑해 2022. 10. 9. 23:03

  데이터 관리 프로그램

문자열, 정수, 날짜 데이터를 관리하는 프로그램 짜보기

 

메뉴)

  • 데이터 입력
  • 데이터 출력
  • 데이터 검색
  • 데이터 수정
  • 데이터 삭제
  • 종료

=> MVC 패턴 + DB 연동 => DB를 연결하여 데이터를 주고 받기 때문에 DTO 작성 시에는 연관된 DB 테이블을 고려하여 작성해야 한다. 따라서 컬럼의 이름과 동일하게 변수를 만들고(소문자로만 작성) 날짜형(date)는 문자열로 취급해 만들어준다.

 

프로그램의 흐름)

main 메소드에서 시작 -> controller 메소드 실행(전체 흐름 처리)

-> 입출력은 view 패키지의 클래스에서 처리

-> 각 기능에 대한 처리는 service 패키지에서 처리

-> 전체 프로그램의 흐름 제어는 controller에서 처리 ex) view -> controller -> service -> dao -> DB

 

Lombok)

Lombok : Lombok은 클래스의 Setter, Getter, 생성자 등의 코드를 자동으로 생성해주는 라이브러리로, DTO(정보 객체) 작성에 도움을 준다. 이를 사용하기 위해서는 먼저 Lombok 플로그인이 개발도구에 설치되어 있어야 하며(IntelliJ는 자동 설치) lombok.jar 파일을 프로젝트에 포함시켜줘야 한다.

 

Lombok 관련 에러 처리 : File > Settings... -> Buildm Execution, Deployment > Compiler > Annotation Processor ->

Enable annotation processing 체크 (체크되어 있으면 해제하고 다시 apply)

  프로그램

1. DB SQL Script

-- 테이블 삭제 쿼리
DROP TABLE IF EXISTS datatbl;

-- 테이블 생성 쿼리
CREATE TABLE IF NOT EXISTS datatbl (
	m_code INT AUTO_INCREMENT PRIMARY KEY,
    m_str VARCHAR(20) NOT NULL,
    m_int INT NOT NULL,
    m_date DATE NOT NULL
);

-- 확인용
SELECT * FROM datatbl;
SELECT * FROM datatbl WHERE m_code = 1;

-- Java 내에서 쿼리문을 작성하는 방법
UPDATE datatbl
SET m_str = ?, m_int = ?, m_date = ?
-- 'SET m_str = ?'일 경우 m_str만 수정하겠다는 의미
WHERE m_code = ?
;

DELETE FROM datatbl;
COMMIT;

 

2. DataDto

package com.dto;

import lombok.Getter;
import lombok.Setter;

@Getter // Getter 메소드 자동 생성
@Setter // Setter 메소드 자동 생성
public class DataDto { // vo로도 작성 => Value Object
    private int m_code;
    private String m_str;
    private int m_int;
    private String m_date;

    @Override
    public String toString() {
        String str = "CODE : " + m_code + "\n"
                + "STR : " + m_str + "\n"
                + "INT : " + m_int + "\n"
                + "DATE : " + m_date;
        return str;
    } // 데이터의 출력 형식을 지정
}

 

3. DataController

- 메뉴 출력

public void run() {
    int menu = -1;

    // 종료 명령이 있을 때까지 반복
    while (true) {
        // 타이틀 출력, 메뉴 출력, 메뉴 번호 입력 => view
        menu = dView.showFirst();

        // 종료 처리
        if (menu == 0) {
            // 종료 메시지 출력 => view
            dView.printMsg("Finish!");
            break;
        }

        // 나머지 메뉴 처리
        switch (menu) {
            case 1:
                inputData();
                break;
            case 2:
                outputData();
                break;
            case 3:
                searchData();
                break;
            case 4: // 데이터 수정 = 검색 + 입력 + 수정
                updateData();
                break;
            case 5: // 데이터 삭제 = 검색 + 삭제
            deleteData();
                break;
            default:
                dView.printMsg("Input Error!(0-5)");
        }
    } // while end
} // run end

 

- 각 메뉴에 대한 처리 메소드

// 입력
private void inputData() {
    // 3가지 데이터를 입력받음(str, int, date)
    DataDto data = new DataDto(); // 데이터 입력 공간

    // view에서 입력 처리
    dView.inputData(data);
    
    // DB에 저장 => service로 전달(성공/실패에 대한 메시지를 줌)
    String msg = dServ.insertData(data);
    
    // 메시지 출력 => view
    dView.printMsg(msg);
} // input end

// 출력
private void outputData() {
    // service에게 전체 목록을 가져오도록 위임
    List<DataDto> dList = dServ.getList();

    // 목록을 view가 출력하도록 넘김
    dView.outputList(dList);
} // output end

// 검색
private void searchData() {
    // 검색 값을 입력받음 => view
    // 현재 테이블의 기본키를 검색에 활용 => 정수(int)
    int code = dView.searchCode("Data Search");
    // 연속적인 입력을 받는 변수에는 초기화가 필요 없음
    
    // 검색 값을 service로 전달해 해당 데이터를 가져옴 => service
    DataDto data = dServ.getData(code);
    
    // 해당 데이터를 화면에 출력 => view
    dView.outData(data);
} // search end

// 수정
private void updateData() {
    // 검색
    int code = dView.searchCode("Update Data");
    DataDto data = dServ.getData(code);
    dView.outData(data);

    // data가 null이 아닌 경우( = 데이터가 있는 경우)
    if (data != null) {
    // 수정할 값 입력 => view
        dView.updateInput(data);

        // DB를 수정하기 위해 service로 전달하고 결과 메시지를 받음 => service
        String msg = dServ.updateData(data);
        
        // 결과 메시지를 출력 => view
        dView.printMsg(msg);
    }
} // update end

// 삭제
private void deleteData() {
    // 삭제 코드 검색
    int code = dView.searchCode("Delete Data");
    DataDto data = dServ.getData(code);
    dView.outData(data);

    if (data != null) {
        String yn = dView.isDelete();
        
        if (yn.equals("y")) {
            // service로 code를 넘겨 삭제 처리하고 결과 메시지를 받음
            String msg = dServ.deleteData(code);
            dView.printMsg(msg);
        }
    }
} // delete end

 

3. DataView

- Menu 출력

public int showFirst() {
    int menu = -1;
    
    // 타이틀 출력
    ioc.twoPrint("");
    ioc.twoPrint("< Data Management Program >");
    ioc.twoPrint("---------------------------");
    // 메뉴 출력
    ioc.twoPrint("menu)");
    ioc.twoPrint("1. Data Input");
    ioc.twoPrint("2. Data Output");
    ioc.twoPrint("3. Data Search");
    ioc.twoPrint("4. Data Update");
    ioc.twoPrint("5. Data Delete");
    ioc.twoPrint("0. Quit");
    
    // 메뉴 번호 입력
    menu = ioc.inNum("SELECT >> ");
    
    // 입력받은 메뉴 번호를 controller에 전달
    return menu;
}

 

- 각 메뉴에 대한 메시지 출력용 메소드

// 입력 텍스트 출력
public void inputData(DataDto data) {
    // 기능 타이틀 출력
    subTitle("Data Input");
    
    // 데이터 입력
    data.setM_str(ioc.inStr("STR : "));
    data.setM_int(ioc.inNum("INT : "));
    data.setM_date(ioc.inStr("DATE(yyyy-mm-dd) : "));
} // input end

// 출력 텍스트 출력
public void outputList(List<DataDto> dList) {
    // 서브 타이틀 출력
    subTitle("Data Output");

    // 목록 내의 데이터 유무 확인
    if (dList == null) {
        printMsg("No Data.");
        return; // 메소드 종료
     }

    for (DataDto data : dList) {
        ioc.twoPrint(data.toString());
        ioc.twoPrint("-------------");
    }
} // output end

// 데이터 검색 후 존재 유무 판단
public int searchCode(String str) {
    int code = 0;

    // 서브 타이틀 출력
    subTitle(str);

    code = ioc.inNum("CODE : ");
    
    return code;
} // end => Search/Update/Delete

// 데이터 유무 결과값 반환
public void outData(DataDto data) {
    subTitle("Select Data");

    if (data == null) {
        printMsg("No Data.");
        return;
    }
    
    ioc.twoPrint(data.toString());
    ioc.twoPrint("-------------");
} // end => Search/Update/Delete

// 수정 텍스트 출력
public void updateInput(DataDto data) {
    subTitle("Update Data");

    // 변경할 값만 받아서 저장
    String str = null;
    int num = 0;
    
    str = ioc.inStr("STR : ");
    if (!str.equals("")) { // 변경할 값을 입력한 경우
        data.setM_str(str);
    }

    num = ioc.inNum("NUM : ");
    if (num != -1) {
        data.setM_int(num);
    }

    str = ioc.inStr("DATE(yyyy-mm-dd) : ");
    if (!str.equals("")) {
        data.setM_date(str);
    }
} // updateInput end

// 삭제 텍스트 출력
public String isDelete() {
    String yn = ioc.inStr("Delete OK?(y/n)");
    return yn;
} // delete end

 

4. DataService

// 입력 데이터 DB 반영 판별
public String insertData(DataDto data) {
    String msg = null;

    // Dao를 사용하여 저장
    int res = dDao.insertData(data);

    if (res == 0) {
        msg = "Insert Failed.";
    } else {
        msg = "Insert Success.";
    }

    return msg;
}

// DB로부터 데이터를 받아 목록 저장
public List<DataDto> getList() {
    // Dao에게 DB로부터 데이터를 검색하여 목록을 가져오게 함
    List<DataDto> gList = dDao.selectList();
    
    // 받은 목록을 controller에 전달
    return gList;
}

// 검색한 값을 DB 작업을 통해 받아와 목록 저장
public DataDto getData(int code) {
    DataDto data = null;

    // 전달받은 검색값을 사용해 DB select 작업을 수행 => Dao
    data = dDao.selectData(code);

    // 검색 결과 데이터를 controller에 전달
    return data;
}

// 받은 데이터가 DB에 업데이트 됐는지 판별
public String updateData(DataDto data) {
    String msg = null;

    // dao에서 DB 수정 처리
    int res = dDao.updateData(data);

    if (res > 0) {
        msg = "Update Success.";
    } else {
        msg = "Update Failed.";
    }

    return msg;
}

// 받은 데이터가 DB에 삭제됐는지 판별
public String deleteData(int code) {
    String msg = null;

    int res = dDao.deleteData(code);

    if (res > 0) {
        msg = "Delete Success.";
    } else {
        msg = "Delete Failed.";
    }

    return msg;
}

 

5. DataDto

- DB 연동에 필요한 정보

private String drv = "com.mysql.cd.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/datadb";
private String user = "dev01";
private String pass = "12341234";

// DB 연동 관련 객체
private Connection conn;
private PreparedStatement pstmt;
private ResultSet rs;

 

- 생성자 및 메모리 해제 메소드

// 드라이버 로드 => 생성자로 처리
public DataDao() {
    try {
        Class.forName(drv);
    } catch (ClassNotFoundException e) {
        //
    }
} // 생성자 end

// 메모리 해제 메소드(각 DB 처리 메소드의 finally 부분에서 사용)
private void close() {
    try {
        if (rs != null) rs.close();
        if (pstmt != null) pstmt.close();
        if (conn != null) conn.close();
    } catch (SQLException e) {

    }
} // close end

 

- 각 용도에 맞는 Dao 메소드

// 입력용
public int insertData(DataDto data) {
    int result = 0; // 0이면 삽입 실패, 0이 아니면 성공
    String query = "INSERT INTO datatbl VALUES (null,?,?,?)";

    try {
        conn = DriverManager.getConnection(url, user, pass);
        pstmt = conn.prepareStatement(query);

        // 쿼리문의 '?' 부분 순서대로 채우기
        pstmt.setString(1, data.getM_str());
        pstmt.setInt(2, data.getM_int());
        pstmt.setDate(3, Date.valueOf(data.getM_date()));
        
        // 쿼리문 실행 및 실행 결과 받기
        result = pstmt.executeUpdate();
        } catch (SQLException e) {
            result = 0; // 삽입 실패
        }

    return result;
} // insertData end

// 출력용
public List<DataDto> selectList() {
    List<DataDto> dList = null;
    String query = "SELECT * FROM datatbl";

    try {
        conn = DriverManager.getConnection(url, user, pass);
        pstmt = conn.prepareStatement(query);
        rs = pstmt.executeQuery();

        // 처리할(가져올) 행이 없으면 rs.next()는 false를 반환 => while문 중단
        while (rs.next()) {
            if (dList == null) {
                dList = new ArrayList<>();
            }

            // DTO를 목록 추가
            DataDto data = new DataDto();
            data.setM_code(rs.getInt(1));
            data.setM_str(rs.getString(2));
            data.setM_int(rs.getInt(3));
            data.setM_date(rs.getString(4)); // 직접 컬럼명 작성도 가능
            
            dList.add(data);
        }
    } catch (SQLException e) {
        dList = null;
    }

    // service로 목록 전달(데이터가 없을 경우 null 전달)
    return dList;
} // selectList end

// 검색용
public DataDto selectData(int code) {
    DataDto data = null;
    String query = "SELECT * FROM datatbl WHERE m_code = ?";
    
    try {
        conn = DriverManager.getConnection(url, user, pass);

        pstmt = conn.prepareStatement(query);
        pstmt.setInt(1, code);
        rs = pstmt.executeQuery();
        
        if (rs.next()) {
            data = new DataDto();
            data.setM_code(rs.getInt(1)); // 입력한 코드나 데이터에서 가져온 코드나 모두 같은 값임
            data.setM_str(rs.getString(2));
            data.setM_int(rs.getInt(3));
            data.setM_date(rs.getString(4));
        }
    } catch (SQLException e) {
        // e.printStackTrace();
    } finally {
        close();
    }

    return data;
} // selectData end

// 수정용
public int updateData(DataDto data) {
    int result = 0;
    String query = "UPDATE datatbl "
         + "SET m_str = ?, m_int = ?, m_date = ? "
         + "WHERE m_code = ?";

    try {
        conn = DriverManager.getConnection(url, user, pass);
        pstmt = conn.prepareStatement(query);
        pstmt.setString(1, data.getM_str());
        pstmt.setInt(2, data.getM_int());
        pstmt.setDate(3, Date.valueOf(data.getM_date()));
        pstmt.setInt(4, data.getM_code());
        
        result = pstmt.executeUpdate();
    } catch (SQLException e) {
        // e.printStackTrace();
        result = 0;
    } finally {
        close();
    }

    return result;
} // update end

// 삭제용
public int deleteData(int code) {
    int result = 0;
    String query = "DELETE FORM datatbl WHERE m_code = ?";

    try {
        conn = DriverManager.getConnection(url, user, pass);
        pstmt = conn.prepareStatement(query);
        pstmt.setInt(1, code);
        
        result = pstmt.executeUpdate();
    } catch (SQLException e) {
        // e.printStackTrace();
        result = 0;
    } finally {
        close();
    }

    return result;
} // delete end