데이터베이스

성적관리프로그램_ DB CRUD(실습_Spring 사용x)_ 22.06.30(day09)

양빵빵 2022. 6. 30. 12:13

1. 성적 저장 기능

2. 전체 학생 성적 조회 기능

3. 개별 학생 성적 조회 기능

4. 성적 수정 기능

5. 성적 정보 삭제 기능

 

package com.jdbc.basic.score.domain;

import lombok.*;

@Setter @Getter
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 모든 필드 초기화 생성자
@ToString
@Builder // 객체 생성시 생성자 역할을 대신


// 데이터베이스 score 테이블의 행데이터를 저장할 객체
public class Score {

    private int stuNum;
    private String stuName;
    private int kor;
    private int eng;
    private int math;
    private int total;
    private double average;


    // 총점, 평균을 계산하는 메서드
    public void calc(){
        this.total = kor + eng + math;
        this.average = Math.round((total / 3.0) * 100) / 100;
    }
}
package com.jdbc.basic.score.repository;

import com.jdbc.basic.score.domain.Score;

import java.util.Map;

public interface ScoreRepository {

    // 성적 정보 저장
    boolean save(Score score);

    // 성적 정보 삭제
    boolean remove(int stuNum);

    // 성적 정보 수정
    boolean modify(Score score);

    // 전체 성적 조회
    Map<Integer, Score> findAll();

    // 개별 성적 조회
    Score findOne(int stuNum);
}
package com.jdbc.basic.score.controller;


import com.jdbc.basic.score.domain.Score;

import java.util.HashMap;
import java.util.Map;

// 데이터들을 전처리 후처리하고 저장 관리하는 클래스
public class ScoreController {

    // 성적 정보가 저장될 맵
    private static final Map<Integer, Score> scoreMap;

    static {
        scoreMap = new HashMap<>();
    }

    // 학생 성적정보 입력 기능
    public void insertStudent(Score score){
        // 메모리에 저장
                scoreMap.put(score.getStuNum(), score);

       // DB에 저장 명령

    }

}

 

package com.jdbc.basic.score.repository;

import com.jdbc.basic.Connect;
import com.jdbc.basic.score.domain.Score;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

// Oracle DBMS에 성적 정보를 CRUD하는 클래스
public class ScoreOracleRepo implements ScoreRepository {
    @Override
    public boolean save(Score score) {

        String sql = "INSERT INTO score " +
                "VALUES (seq_score.nextval, ?,?,?,?,?,?)";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, score.getStuName());
            pstmt.setInt(2, score.getKor());
            pstmt.setInt(3, score.getEng());
            pstmt.setInt(4, score.getMath());
            pstmt.setInt(5, score.getTotal());
            pstmt.setDouble(6, score.getAverage());

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }

    }

    @Override
    public boolean remove(int stuNum) {

        String sql = "DELETE FROM score WHERE stu_num=?";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, stuNum);

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }
    }

    @Override
    public boolean modify(Score score) {
        String sql = "UPDATE score " +
                " SET kor =?, eng = ?, math = ?, total = ?, average = ? " +
                " WHERE stu_num = ?";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, score.getKor());
            pstmt.setInt(2, score.getEng());
            pstmt.setInt(3, score.getMath());
            pstmt.setInt(4, score.getTotal());
            pstmt.setDouble(5, score.getAverage());

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }
    }

    @Override
    public Map<Integer, Score> findAll() {

        Map<Integer, Score> scoreMap = new HashMap<>();

        String sql = "SELECT * FROM score ORDER BY stu_num";

        try (Connection conn = Connect.makeConnection()) {

            PreparedStatement pstmt = conn.prepareStatement(sql);

            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                Score s = new Score(
                        rs.getInt("stu_num")
                        , rs.getString("stu_name")
                        , rs.getInt("kor")
                        , rs.getInt("eng")
                        , rs.getInt("math")
                        , rs.getInt("total")
                        , rs.getDouble("average")
                );
                scoreMap.put(s.getStuNum(), s);

            }
            return scoreMap;


        } catch (Exception e) {
            e.printStackTrace();
            return Collections.emptyMap();
        }
    }

    @Override
    public Score findOne(int stuNum) {

        String sql = "SELECT * FROM score WHERE stu_num = ?";

        try (Connection conn = Connect.makeConnection()) {

            PreparedStatement pstmt = conn.prepareStatement(sql);

            pstmt.setInt(1, stuNum);

            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                Score s = new Score(
                        rs.getInt("stu_num")
                        , rs.getString("stu_name")
                        , rs.getInt("kor")
                        , rs.getInt("eng")
                        , rs.getInt("math")
                        , rs.getInt("total")
                        , rs.getDouble("average")
                );
                return s;
            }

            return null;


        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

 

 

 

 

@Test
    @DisplayName("성적 정보를 수정해야 한다.")
    void findModify(){

        // given [객체에서 수정 진행]
        Score score =  repository.findOne(3);
        score.setKor(80);
        score.setEng(80);
        score.setMath(80);
        score.setTotal(80);
        score.calc();

        //when - 테스트할 상황
        boolean result = repository.modify(score);

        //then - 테스트 후 예상되는 결과
        Score newScore = repository.findOne(3);
        assertEquals(80, newScore.getAverage());
}

 

 

 

 

 

 

 

==== 최종 코드 ↓ =====

package com.jdbc.basic.score.domain;

import lombok.*;

@Setter @Getter
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 모든 필드 초기화 생성자
@ToString
@Builder // 객체 생성시 생성자 역할을 대신


// 데이터베이스 score 테이블의 행데이터를 저장할 객체
public class Score {

    private int stuNum;
    private String stuName;
    private int kor;
    private int eng;
    private int math;
    private int total;
    private double average;


    // 총점, 평균을 계산하는 메서드
    public void calc(){
        this.total = kor + eng + math;
        this.average = Math.round((total / 3.0) * 100) / 100;
    }
}

 

package com.jdbc.basic.score.repository;

import com.jdbc.basic.score.domain.Score;

import java.util.Map;

public interface ScoreRepository {

    // 성적 정보 저장
    boolean save(Score score);

    // 성적 정보 삭제
    boolean remove(int stuNum);

    // 성적 정보 수정
    boolean modify(Score score);

    // 전체 성적 조회
    Map<Integer, Score> findAll();

    // 개별 성적 조회
    Score findOne(int stuNum);

    // 반 전체 평균 조회
    double getClassAverage();

}

 

package com.jdbc.basic.score.repository;

import com.jdbc.basic.Connect;
import com.jdbc.basic.score.domain.Score;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

// Oracle DBMS에 성적 정보를 CRUD하는 클래스
public class ScoreOracleRepo implements ScoreRepository {
    @Override
    public boolean save(Score score) {

        String sql = "INSERT INTO score " +
                "VALUES (seq_score.nextval, ?,?,?,?,?,?)";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, score.getStuName());
            pstmt.setInt(2, score.getKor());
            pstmt.setInt(3, score.getEng());
            pstmt.setInt(4, score.getMath());
            pstmt.setInt(5, score.getTotal());
            pstmt.setDouble(6, score.getAverage());

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }

    }

    @Override
    public boolean remove(int stuNum) {

        String sql = "DELETE FROM score WHERE stu_num=?";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, stuNum);

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }
    }

    @Override
    public boolean modify(Score score) {
        String sql = "UPDATE score " +
                " SET kor =?, eng = ?, math = ?, total = ?, average = ? " +
                " WHERE stu_num = ?";

        try (Connection conn = Connect.makeConnection()) {
            // 트랜잭션 처리
            conn.setAutoCommit(false); // 자동커밋 설정 끄기

            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, score.getKor());
            pstmt.setInt(2, score.getEng());
            pstmt.setInt(3, score.getMath());
            pstmt.setInt(4, score.getTotal());
            pstmt.setDouble(5, score.getAverage());
            pstmt.setDouble(6, score.getStuNum());

            int result = pstmt.executeUpdate();

            if (result != 0) {
                conn.commit(); // 커밋 완료
                return true;
            } else {
                conn.rollback(); // 롤백
                return false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return false;

        }
    }

    @Override
    public Map<Integer, Score> findAll() {

        Map<Integer, Score> scoreMap = new HashMap<>();

        String sql = "SELECT * FROM score ORDER BY stu_num";

        try (Connection conn = Connect.makeConnection()) {

            PreparedStatement pstmt = conn.prepareStatement(sql);

            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                Score s = new Score(
                        rs.getInt("stu_num")
                        , rs.getString("stu_name")
                        , rs.getInt("kor")
                        , rs.getInt("eng")
                        , rs.getInt("math")
                        , rs.getInt("total")
                        , rs.getDouble("average")
                );
                scoreMap.put(s.getStuNum(), s);

            }
            return scoreMap;


        } catch (Exception e) {
            e.printStackTrace();
            return Collections.emptyMap();
        }
    }

    @Override
    public Score findOne(int stuNum) {

        String sql = "SELECT * FROM score WHERE stu_num = ?";

        try (Connection conn = Connect.makeConnection()) {

            PreparedStatement pstmt = conn.prepareStatement(sql);

            pstmt.setInt(1, stuNum);

            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                Score s = new Score(
                        rs.getInt("stu_num")
                        , rs.getString("stu_name")
                        , rs.getInt("kor")
                        , rs.getInt("eng")
                        , rs.getInt("math")
                        , rs.getInt("total")
                        , rs.getDouble("average")
                );
                return s;
            }

            return null;


        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public double getClassAverage() {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT AVG(average) AS avg_cls\n")
                .append("FROM score");

        try (Connection conn = Connect.makeConnection()){
            PreparedStatement pstmt = conn.prepareStatement(sql.toString());
            ResultSet rs = pstmt.executeQuery();

            if(rs.next()) {
                return rs.getDouble("avg_cls");
            }

        } catch (SQLException e) {
           e.printStackTrace();
        }
        return 0.0;
    }
}

 

package com.jdbc.basic.score.controller;


import com.jdbc.basic.score.domain.Score;
import com.jdbc.basic.score.repository.ScoreOracleRepo;
import com.jdbc.basic.score.repository.ScoreRepository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 데이터들을 전처리 후처리하고 저장 관리하는 클래스
public class ScoreController {

    // 성적 정보가 저장될 맵
    private static Map<Integer, Score> scoreMap;

    // ScoreRepository에 의존성 관계를 가진다.
    private final ScoreRepository repository; // 의존성 관계를 가진 경우 인터페이스로 필드 생성.
    // 누구라도 대체할수 있도록 구현체와 연결하면 x

    public ScoreController() {
        this.repository = new ScoreOracleRepo();
    }

    static {
        scoreMap = new HashMap<>();
    }

    // 학생 성적정보 입력 기능
    public void insertStudent(Score score) {
        // 메모리에 저장
        scoreMap.put(score.getStuNum(), score);

        // DB에 저장 명령
        repository.save(score);
    }

    // 성적 전체 조회
    public List<Score> findAllStudents() {
        Map<Integer, Score> students = repository.findAll();
        scoreMap = students;

        List<Score> scoreList = new ArrayList<>();
        for (Integer stuNum : scoreMap.keySet()) {
            scoreList.add(scoreMap.get(stuNum));
        }
        return scoreList;
    }

    // 반 평균을 구하는 메서드
    public double calsClassAverage() {
        // case 1: 앱 내부에서 구한다. (비추)
        /*double avgSum = 0.0;
        for (Integer stuNum : scoreMap.keySet()) {
            avgSum += scoreMap.get(stuNum).getAverage();
        }
        return avgSum / scoreMap.size();*/

        // case 2: DB에서 전체평균을 구해서 가져온다.
        return repository.getClassAverage();
    }

    // 성적 개별 조회
    public Score findOneStudent(int stuNum) {
        return repository.findOne(stuNum);
    }

    // 성적 수정
    public boolean updateStudent(int stuNum, int kor, int eng, int math) {
        // 1.DB에서 해당 학생을 조회한다.
        Score target = findOneStudent(stuNum);

        if (target != null) {
            //2. 수정 진행
            target.setKor(kor);
            target.setEng(eng);
            target.setMath(math);

            //3. DB에 수정 반영
            return  repository.modify(target);

        }
        return false;
    }

    // 성적정보 삭제
    public boolean deleteStudent(int stuNum){
        return repository.remove(stuNum);
    }

    // 학번으로 조회했을 때 학생 존재 유무를 리턴
public boolean hasScore(int stuNum){
    return repository.findOne(stuNum) != null;
    }


}



 

package com.jdbc.basic.score.view;

public class Run {
    public static void main(String[] args) {

        new ScoreMenu().mainMenu();

    }
}

 

package com.jdbc.basic.score.view;

import com.jdbc.basic.score.controller.ScoreController;
import com.jdbc.basic.score.domain.Score;

import java.util.List;
import java.util.Scanner;

// 화면 출력창
public class ScoreMenu {

    private final ScoreController controller;
    Scanner sc;


    public ScoreMenu() {
        controller = new ScoreController();
        sc = new Scanner(System.in);
    }
    public void mainMenu() {
        while (true) {

            System.out.println("\n ====== 성적 관리 프로그램 ======= ");
            System.out.println("# 1. 성적 정보 입력");
            System.out.println("# 2. 성적 전체 조회");
            System.out.println("# 3. 성적 개별 조회");
            System.out.println("# 4. 성적 정보 수정");
            System.out.println("# 5. 성적 정보 삭제");
            System.out.println("# 9. 끝내기");

            int menu = inputN("\n메뉴입력 : ");

            switch (menu) {
                case 1:
                    insertMenu();
                    break;
                case 2:
                    findAllMenu();
                    break;
                case 3:
                    findOneMenu();
                    break;
                case 4:
                    modifyMenu();
                    break;
                case 5:
                    removeMenu();
                    break;
                case 9:
                    System.out.println("프로그램을 종료합니다.");
                    System.exit(0);
                    return;

                default:
                    System.out.println("\n# 메뉴를 다시 입력하세요.");
            }
        }
    }

    // 5번 메뉴
    private void removeMenu() {
        System.out.println("\n# 삭제할 학생의 학번을 입력하세요!");
        int stuNum = inputN(">>> ");

        if (controller.hasScore(stuNum)) {

            boolean flag = controller.deleteStudent(stuNum);
            if (flag) {
                System.out.println("# 삭제가 완료되었습니다.");
            } else {
                System.out.println("# 삭제에 실패했습니다.");
            }

        } else {
            System.out.println("\n# 해당 학번은 존재하지 않습니다.");
        }
    }

    // 4번 메뉴
    private void modifyMenu() {

        System.out.println("\n# 수정할 학생의 학번을 입력하세요!");
        int stuNum = inputN(">>> ");

        if (controller.hasScore(stuNum)) {

            System.out.println("# 수정할 점수들을 입력하세요.");
            int kor = inputN(" - 국어: ");
            int eng = inputN(" - 영어: ");
            int math = inputN(" - 수학: ");

            boolean flag = controller.updateStudent(stuNum,kor,eng,math);
            if (flag) {
                System.out.println("# 수정이 완료되었습니다.");
            } else {
                System.out.println("#수정이 실패했습니다.");
            }

       } else {
            System.out.println("\n# 해당 학번은 존재하지 않습니다.");
        }

    }

    // 3번 메뉴
    private void findOneMenu() {

        System.out.println("\n# 조회할 학생의 학번을 입력하세요!");
        int stuNum = inputN(">>> ");

        Score student = controller.findOneStudent(stuNum);
        if(student != null) {
            System.out.println("\n## 조회 결과");
            System.out.println("- 학번: " + student.getStuNum());
            System.out.println("- 이름: " + student.getStuName());
            System.out.println("- 국어: " + student.getKor());
            System.out.println("- 영어: " + student.getEng());
            System.out.println("- 수학: " + student.getMath());
            System.out.println("- 총점: " + student.getTotal());
            System.out.println("- 평균: " + student.getAverage());

        } else {
            System.out.println("\n# 해당 학번은 존재하지 않습니다.");
        }

    }

    // 2번 메뉴
    private void findAllMenu() {

        List<Score> students = controller.findAllStudents();

        System.out.printf("\n=============== 모든 성적 정보 (반 평균 : %.2f점) ================\n",
                controller.calsClassAverage());
        System.out.printf("%5s%5s%5s%5s%5s%5s%5s\n"
                , "학번", "이름", "국어", "영어", "수학", "총점", "평균");
        System.out.println("----------------------------------------------");

        for (Score s : students) {
            System.out.printf("%5d %5s%5d  %5d  %5d  %4d   %.2f\n"
                    , s.getStuNum(), s.getStuName(), s.getKor()
                    , s.getEng(), s.getMath(), s.getTotal()
                    , s.getAverage());
        }

    }


    // 1번 메뉴
    private void insertMenu() {
        System.out.println("\n 성적 정보 입력을 시작합니다.");
        System.out.println(" - 이름 :");
        String name = sc.next();

        int kor = inputN(" - 국어:");
        int eng = inputN(" - 영어:");
        int math = inputN(" - 수학:");

        Score score = new Score();
        score.setStuName(name);
        score.setKor(kor);
        score.setEng(eng);
        score.setMath(math);
        score.calc();

        controller.insertStudent(score);

        System.out.printf("\n %s 님의 성정 정보가 저장되었습니다.\n", name);
    }

    // 숫자입력 메서드
    private int inputN(String msg) {
        int n;
        while (true) {
            try {
                System.out.println(msg);
                n = sc.nextInt();
                break;
            } catch (Exception e) {
                sc.nextLine();
                System.out.println("# 정수로만 입력하세요");
            }
        }
        return n;
    }


}