온풀투데이

[JDBC] 성적 처리 프로그램 : DAO, DTO, Process 클래스 / Statement 인터페이스 활용 본문

TIL

[JDBC] 성적 처리 프로그램 : DAO, DTO, Process 클래스 / Statement 인터페이스 활용

온풀 2022. 4. 3. 23:52

문제

○ 성적 처리 → 데이터베이스 연동(데이터베이스 연결 및 액션 처리)
                ScoreDTO 클래스 활용(속성만 존재하는 클래스, getter / setter 구성)
                ScoreDAO 클래스 활용(데이터베이스 액션 처리)
                Process 클래스 활용(업무 단위 기능 구성)
                DBConn 클래스 활용(데이터베이스 연결 전담 전용 객체 처리)
                
여러 명의 이름, 국어점수, 영어점수, 수학점수를 입력받아
총점, 평균, 석차 등을 계산하여 출력하는 프로그램을 구현한다.
※ 서브 메뉴 구성 → Process 클래스 활용

실행 예)

====[ 성적 처리 ]====
1. 성적 입력
2. 성적 전체 출력
3. 이름 검색 출력
4. 성적 수정
5. 성적 삭제
=====================
>> 선택(1~5, -1종료) : 1

7번 학생 성적 입력(이름 국어 영어 수학) : 이시우 50 60 70
성적 입력이 완료되었습니다.

8번 학생 성적 입력(이름 국어 영어 수학) : 이지연 80 80 80
성적 입력이 완료되었습니다.

9번 학생 성적 입력(이름 국어 영어 수학) : .

====[ 성적 처리 ]====
1. 성적 입력
2. 성적 전체 출력
3. 이름 검색 출력
4. 성적 수정
5. 성적 삭제
=====================
>> 선택(1~5, -1종료) : 2

전체 인원 : 8명
번호   이름   국어   영어   수학   총점   평균   석차
 1
 2
 3
 4
 5                       ...
 6
 7
 8
 
====[ 성적 처리 ]====
1. 성적 입력
2. 성적 전체 출력
3. 이름 검색 출력
4. 성적 수정
5. 성적 삭제
=====================
>> 선택(1~5, -1종료) : -1

프로그램이 종료되었습니다.

DBConn.java

package com.util;

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

public class DBConn
{
    private static Connection dbConn;

    public static Connection getConnection() throws ClassNotFoundException, SQLException
    {
        if (dbConn == null)
        {
            String url = "jdbc:oracle:thin:@localhost:1521:xe";
            String user = "scott";
            String pwd = "tiger";

            Class.forName("oracle.jdbc.driver.OracleDriver");

            dbConn = DriverManager.getConnection(url, user, pwd);
        } 

        return dbConn;
    }

    public static Connection getConnection(String url, String user, String pwd) throws ClassNotFoundException, SQLException
    {
        if (dbConn == null)
        {
            Class.forName("oracle.jdbc.driver.OracleDriver");

            dbConn = DriverManager.getConnection(url, user, pwd);
        }

        return dbConn;
    }

    public static void close() throws SQLException
    {
        if (dbConn != null)
        {
            if (!dbConn.isClosed())
            {
                dbConn.close();
            }
        }

        dbConn = null;
    }
}

ScoreDTO.java

package com.test;

public class ScoreDTO
{
    // 주요 속성 구성
    private String sid, name;
    private int kor, eng, mat;
    private int tot, rank;
    private double avg;

    // getter / setter 구성
    public String getSid()
    {
        return sid;
    }
    public void setSid(String sid)
    {
        this.sid = sid;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public int getKor()
    {
        return kor;
    }
    public void setKor(int kor)
    {
        this.kor = kor;
    }
    public int getEng()
    {
        return eng;
    }
    public void setEng(int eng)
    {
        this.eng = eng;
    }
    public int getMat()
    {
        return mat;
    }
    public void setMat(int mat)
    {
        this.mat = mat;
    }
    public int getTot()
    {
        return tot;
    }
    public void setTot(int tot)
    {
        this.tot = tot;
    }
    public int getRank()
    {
        return rank;
    }
    public void setRank(int rank)
    {
        this.rank = rank;
    }
    public double getAvg()
    {
        return avg;
    }
    public void setAvg(double avg)
    {
        this.avg = avg;
    }
}

ScoreDAO.java

package com.test;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import com.util.DBConn;

public class ScoreDAO
{
    // 주요 속성 구성
    private Connection conn;


    // 데이터베이스 연결 담당 메소드
    public Connection connection() throws ClassNotFoundException, SQLException
    {
        conn = DBConn.getConnection();
        return conn;
    }


    // 데이터 입력 담당 메소드
    public int add(ScoreDTO dto) throws SQLException
    {
        // 변수 선언
        int result = 0;

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = String.format("INSERT INTO TBL_SCORE(SID, NAME, KOR, ENG, MAT) VALUES(SCORESEQ.NEXTVAL, '%s', %d, %d, %d)"
                , dto.getName(), dto.getKor(), dto.getEng(), dto.getMat());

        // 쿼리문 실행
        result = stmt.executeUpdate(sql);

        // 리소스 반납
        stmt.close();

        // 리턴
        return result;
    }


    // 전체 리스트 출력 담당 메소드
    public ArrayList<ScoreDTO> lists() throws SQLException
    {
        // 변수 선언
        ArrayList<ScoreDTO> result = new ArrayList<ScoreDTO>();

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = "SELECT SID, NAME, KOR, ENG, MAT"
                + ", (KOR + ENG + MAT) AS TOT"
                + ", (KOR + ENG + MAT)/3 AS AVG"
                + ", RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK"
                + " FROM TBL_SCORE"
                + " ORDER BY SID ASC";

        // 쿼리문 실행
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next())
        {
            ScoreDTO dto = new ScoreDTO();

            dto.setSid(rs.getString("SID"));
            dto.setName(rs.getString("NAME"));
            dto.setKor(rs.getInt("KOR"));
            dto.setEng(rs.getInt("ENG"));
            dto.setMat(rs.getInt("MAT"));
            dto.setTot(rs.getInt("TOT"));
            dto.setAvg(rs.getDouble("AVG"));
            dto.setRank(rs.getInt("RANK"));

            result.add(dto);
        }

        // 리소스 반납
        rs.close();
        stmt.close();

        // 리턴
        return result;
    }


    // 이름 검색 담당 메소드(오버로딩)
    public ArrayList<ScoreDTO> lists(String name) throws SQLException
    {
        // 변수 선언
        ArrayList<ScoreDTO> result = new ArrayList<ScoreDTO>();

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = String.format("SELECT SID, NAME, KOR, ENG, MAT, TOT, AVG, RANK"
                + " FROM"
                + " (SELECT SID, NAME, KOR, ENG, MAT"
                + ", (KOR + ENG + MAT) AS TOT"
                + ", (KOR + ENG + MAT)/3 AS AVG"
                + ", RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK"
                + " FROM TBL_SCORE)"
                + " WHERE NAME = '%s'", name);

        // 쿼리문 실행
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next())
        {
            ScoreDTO dto = new ScoreDTO();

            dto.setSid(rs.getString("SID"));
            dto.setName(rs.getString("NAME"));
            dto.setKor(rs.getInt("KOR"));
            dto.setEng(rs.getInt("ENG"));
            dto.setMat(rs.getInt("MAT"));
            dto.setTot(rs.getInt("TOT"));
            dto.setAvg(rs.getDouble("AVG"));
            dto.setRank(rs.getInt("RANK"));

            result.add(dto);
        }

        // 리소스 반납
        rs.close();
        stmt.close();

        // 리턴
        return result;
    }


    // 번호 검색 담당 메소드(오버로딩)
    public ArrayList<ScoreDTO> lists(int sid) throws SQLException
    {
        // 변수 선언
        ArrayList<ScoreDTO> result = new ArrayList<ScoreDTO>();

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = String.format("SELECT SID, NAME, KOR, ENG, MAT, TOT, AVG, RANK"
                + " FROM"
                + " (SELECT SID, NAME, KOR, ENG, MAT"
                + ", (KOR + ENG + MAT) AS TOT"
                + ", (KOR + ENG + MAT)/3 AS AVG"
                + ", RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK"
                + " FROM TBL_SCORE)"
                + " WHERE SID =%d", sid);

        // 쿼리문 실행
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next())
        {
            ScoreDTO dto = new ScoreDTO();

            dto.setSid(rs.getString("SID"));
            dto.setName(rs.getString("NAME"));
            dto.setKor(rs.getInt("KOR"));
            dto.setEng(rs.getInt("ENG"));
            dto.setMat(rs.getInt("MAT"));
            dto.setTot(rs.getInt("TOT"));
            dto.setAvg(rs.getDouble("AVG"));
            dto.setRank(rs.getInt("RANK"));

            result.add(dto);
        }

        // 리소스 반납
        rs.close();
        stmt.close();

        // 리턴
        return result;
    }


    // 인원 수 확인 담당 메소드
    public int count() throws SQLException
    {
        // 변수 선언
        int result = 0;

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = "SELECT COUNT(*) AS COUNT FROM TBL_SCORE";

        // 쿼리문 실행
        ResultSet rs = stmt.executeQuery(sql);

        if (rs.next())
        {
            result = rs.getInt(1);
        }

        // 리소스 반납
        rs.close();
        stmt.close();

        // 리턴
        return result;
    }


    // 데이터 수정 담당 메소드 
    // -> 레코드의 값을 바꾸는 메소드 => 업뎃 쿼리문의 set할 애들 다 줘야 함
    public int modify(ScoreDTO dto) throws SQLException
    {
        // 변수 선언
        int result = 0;

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = String.format("UPDATE TBL_SCORE SET NAME='%s', KOR=%d, ENG=%d, MAT=%d WHERE SID=%s"
                , dto.getName(), dto.getKor(), dto.getEng(), dto.getMat(), dto.getSid());

        // 쿼리문 실행
        result = stmt.executeUpdate(sql);

        // 리소스 반납
        stmt.close();

        // 리턴
        return result;
    }


    // 데이터 삭제 담당 메소드
    public int remove(int sid) throws SQLException
    {
        // 변수 선언
        int result = 0;

        // 작업 객체 생성
        Statement stmt = conn.createStatement();

        // 쿼리문 준비
        String sql = String.format("DELETE FROM TBL_SCORE WHERE SID=%d", sid);

        // 쿼리문 실행
        result = stmt.executeUpdate(sql);

        // 리소스 반납
        stmt.close();

        // 리턴
        return result;
    }


    // 데이터베이스 연결 종료 담당 메소드
    public void close() throws SQLException
    {
        DBConn.close();
    }
}

ScoreProcess.java

package com.test;

import java.util.ArrayList;
import java.util.Scanner;

public class ScoreProcess
{
    // 주요 속성 구성 → 데이터베이스 액션 처리 전담 객체 → ScoreDAO
    private ScoreDAO dao;


    // 생성자 정의(사용자 정의 생성자)
    public ScoreProcess()
    {
        dao = new ScoreDAO();
    }


    // 성적 입력 기능
    public void sungjukInsert()
    {
        try
        {
            // 데이터베이스 연결
            dao.connection();

            // 레코드 수 확인
            int count = dao.count();

            Scanner sc = new Scanner(System.in);

            do
            {
                System.out.println();
                System.out.printf("%d번 학생 성적 입력(이름 국어 영어 수학) : ", (++count));
                String name = sc.next();

                if (name.equals("."))
                {
                    break;
                }

                int kor = sc.nextInt();
                int eng = sc.nextInt();
                int mat = sc.nextInt();

                // 입력받은 항목들을 토대로 ScoreDTO 객체 구성
                ScoreDTO dto = new ScoreDTO();
                dto.setName(name);
                dto.setKor(kor);
                dto.setEng(eng);
                dto.setMat(mat);

                // dao의 add() 메소드 호출
                int result = dao.add(dto);

                if (result > 0)
                {
                    System.out.println("성적 입력이 완료되었습니다.");
                }

            } while (true);

            // 데이터베이스 연결 종료
            dao.close();

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }


    // 성적 전체 출력 기능
    public void sungjukSelectAll()
    {
        try
        {
            // 데이터베이스 연결
            dao.connection();

            // 인원수 확인
            int count = dao.count();

            System.out.println();
            System.out.printf("전체 인원 : %d명\n", count);
            System.out.println("번호   이름   국어   영어   수학   총점   평균   석차");

            for (ScoreDTO dto : dao.lists())
            {
                System.out.printf("%3s  %4s  %4d  %5d  %5d  %5d  %5.1f  %5d\n"
                                , dto.getSid(), dto.getName()
                                , dto.getKor(), dto.getEng(), dto.getMat()
                                , dto.getTot(), dto.getAvg(), dto.getRank());
            }

            // dao의 close() 메소드 호출 → 데이터베이스 연결 종료
            dao.close();

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }


    // 이름 검색 출력 기능
    public void sungjukSearchName()
    {
        try
        {
            // 검색할 이름 입력받기
            Scanner sc = new Scanner(System.in);
            System.out.print("검색할 이름 입력 : ");
            String name = sc.next();

            // 데이터베이스 연결
            dao.connection();

            // dao의 lists() 메소드 호출 → 매개변수로 검색할 이름을 문자열 형태로 넘겨주기
            ArrayList<ScoreDTO> arrayList = dao.lists(name);

            if (arrayList.size() > 0)
            {
                // 수신된 내용 출력
                System.out.println("번호   이름   국어   영어   수학   총점   평균   석차");

                for (ScoreDTO dto : arrayList)
                {
                    System.out.printf("%3s  %4s  %4d  %5d  %5d  %5d  %5.1f  %5d\n"
                                    , dto.getSid(), dto.getName()
                                    , dto.getKor(), dto.getEng(), dto.getMat()
                                    , dto.getTot(), dto.getAvg(), dto.getRank());
                }
            }
            else
            {
                // 수신된 내용이 없다는 상황 안내
                System.out.println("검색 결과가 존재하지 않습니다.");
            }

            // 데이터베이스 연결 종료
            dao.close();

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }


    // 성적 수정 기능
    public void sungjukUpdate()
    {
        try
        {
            // 수정할 대상의 번호 입력받기
            Scanner sc = new Scanner(System.in);
            System.out.print("수정할 번호를 입력하세요 : ");
            int sid = sc.nextInt(); 

            // 데이터베이스 연결
            dao.connection();

            // 수정할 대상 수신 
            ArrayList<ScoreDTO> arrayList = dao.lists(sid);

            if (arrayList.size() > 0)
            {
                // 수신된 내용 출력
                System.out.println("번호   이름   국어   영어   수학   총점   평균   석차");

                for (ScoreDTO dto : arrayList)
                {
                    System.out.printf("%3s  %4s  %4d  %5d  %5d  %5d  %5.1f  %5d\n"
                                    , dto.getSid(), dto.getName()
                                    , dto.getKor(), dto.getEng(), dto.getMat()
                                    , dto.getTot(), dto.getAvg(), dto.getRank());
                }

                System.out.println();
                System.out.println("수정 데이터 입력(이름 국어 영어 수학) : ");
                String name = sc.next();
                int kor = sc.nextInt();
                int eng = sc.nextInt();
                int mat = sc.nextInt();

                // dto 구성
                ScoreDTO dto = new ScoreDTO();
                dto.setName(name);
                dto.setKor(kor);
                dto.setEng(eng);
                dto.setMat(mat);
                dto.setSid(String.valueOf(sid));

                // 구성된 dto 를 넘겨주며 dao의 modify() 메소드 호출
                int result = dao.modify(dto);
                if (result > 0)
                {
                    System.out.println("수정이 완료되었습니다.");
                }
            }
            else
            {
                // 수신된 내용이 존재하지 않는 상황 전달(안내)
                System.out.println("수정 대상이 존재하지 않습니다.");
            }

            // 데이터베이스 연결 종료
            dao.close();

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }


    // 성적 삭제 기능
    public void sungjukDelete()
    {
        try
        {
            // 삭제할 번호 입력받기
            Scanner sc = new Scanner(System.in);
            System.out.print("삭제할 번호를 입력하세요 : ");
            int sid = sc.nextInt();

            // 데이터베이스 연결
            dao.connection();

            // dao 의 lists() 메소드 호출 → 삭제할 대상 검색
            ArrayList<ScoreDTO> arrayList = dao.lists(sid);

            if (arrayList.size() > 0)
            {
                // 수신된 내용 출력
                System.out.println("번호   이름   국어   영어   수학   총점   평균   석차");

                for (ScoreDTO dto : arrayList)
                {
                    System.out.printf("%3s  %4s  %4d  %5d  %5d  %5d  %5.1f  %5d\n"
                                    , dto.getSid(), dto.getName()
                                    , dto.getKor(), dto.getEng(), dto.getMat()
                                    , dto.getTot(), dto.getAvg(), dto.getRank());
                }

                System.out.print(">> 정말 삭제하시겠습니까?(Y/N) : ");
                String response = sc.next();
                if (response.equals("Y") || response.equals("y"))
                {
                    int result = dao.remove(sid);
                    if (result > 0)
                    {
                        System.out.println("삭제가 완료되었습니다.");
                    }
                }
                else
                {
                    System.out.println("취소되었습니다.");
                }

            } else
            {
                // 수신된 내용이 존재하지 않는 상황 전달(안내)
                System.out.println("삭제할 대상이 존재하지 않습니다.");

            }

            // 데이터베이스 연결 종료
            dao.close();

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }
}

ScoreMain.java

package com.test;

import java.util.Scanner;

public class ScoreMain
{
    public static void main(String[] args)
    {
        ScoreProcess prc = new ScoreProcess();
        Scanner sc = new Scanner(System.in);

        do
        {
            System.out.println();
            System.out.println("====[ 성적 처리 ]===="); // 컨트롤 알트 방향키 -> 복사
            System.out.println("1. 성적 입력"); // 알트 쉬프트 a -> 토글
            System.out.println("2. 성적 전체 출력");
            System.out.println("3. 이름 검색 출력");
            System.out.println("4. 성적 수정");
            System.out.println("5. 성적 삭제");
            System.out.println("=====================");
            System.out.print(">> 선택(1~5, -1종료) : ");
            String menus = sc.next();

            try
            {
                int menu = Integer.parseInt(menus);

                if (menu == -1)
                {
                    System.out.println();
                    System.out.println("프로그램이 종료되었습니다.");
                    return;
                }

                switch (menu)
                {
                case 1:
                    // 성적 입력 기능 수행
                    prc.sungjukInsert();
                    break;
                case 2:
                    // 성적 전체 출력 기능 수행
                    prc.sungjukSelectAll();
                    break;
                case 3:
                    // 이름 검색 출력 기능 수행
                    prc.sungjukSearchName();
                    break;
                case 4:
                    // 성적 수정 기능 수행
                    prc.sungjukUpdate();
                    break;
                case 5:
                    // 성적 삭제 기능 수행
                    prc.sungjukDelete();
                    break;
                }

            } catch (Exception e)
            {
                System.out.println(e.toString());
            }

        } while (true);
    }
}