JAVA개념&실습

JDBC : 07. ScoreDTO/ScoreDAO/PreparedStatement/성적처리 실습

u_SZero 2023. 5. 24. 00:03

! 현재 배워가고 있는 주인장이 쓴 글이니 정보의 정확성에 유의하시기 바랍니다 !


 

■■■ PreparedStatement ■■■

더보기

1. Statement 의 execute 메소드는
   문자열로 구성된 SQL 구문을 DBMS 로 전달하는 역할을 수행하며,
   내부적으로 SQL 구문을 JDBC 드라이버가 읽을 수 있는 형식으로
   전처리(precompile)하게 된다.

   이후 드라이버는 DBMS에 전처리된 요구사항을 전송하게 되는데,
   SQL 구문을 매번 전처리 과정을 거쳐서 전송하게 되기 때문에
   반복적인 작업에서 속도가 느려질 수 있는 한계를 갖고 있다.
     ----

   이에 반하여, PreparedStatement 는
   전처리된 Statement 로 주어진 SQL 구문을 미리 전처리 과정을 거친 상태로
   보관해 두기 때문에 반복적인 작업을 수행하는 데 있어 매우 유리하다.

   Statement 의 서브 클래스인 PreparedStatement 는
   Statement 의 모든 기능을 상속받으며
   IN 매개변수의 위치에 데이터베이스로 전송될 값을 지정하기 위해
   필요한 전체 모든 메소드들의 집합을 포함시킨다.
   또한, 세 개의 메소드 『execute(), executeUpdate(), executeQuery()』는
   아무런 파라미터도 가지지 않는다.
   이러한 메소드들의 Statement 형태(즉, SQL 매개변수를 가지는 형태)는
   PreparedStatement 객체에서 사용되지 않는다.

2. IN 매개변수 넘겨주기
   PreparedStatement 객체를 실행하기 전에
   각 『?』 매개변수의 값이 설정되어 있어야 한다.
   이것은 『setXxx()』 메소드를 호출하여 이루어지게 되며
   이 때, 『Xxx』는 매개변수에 대한 적당한 형(Type)이다.
   『setXxx()』 메소드의 첫 번째 인자는 설정된 매개변수의 순번이고,
   두 번째 인자는 매개변수가 설정될 값이다.

※ Connection 의 대표적 메소드
   
   - createStatement()
     : SQL 구문을 Database 에 전달하기 위해 Statement 객체를 생성한다.

   - preparedStatement(String sql)
     : 파라미터가 포함된 SQL 문을 Database 에 전달하기 위해
       PreparedStatement 객체를 생성한다.

   - preparedCall(String sql)
     : 데이터베이스의 Stored Procedure 를 호출하기 위해
       CallableStatement 객체를 생성한다.

   - close()
     : 현재의 Connection 객체에 할당된 System Resource 를 즉시 반환한다.


 


 

[실습 개요]

 

○ 성적 처리 → 데이터베이스 연동(데이터베이스 연결 및 액션 처리) JDBC04_scott.sql 활용
    - ScoreDTO 클래스 활용(속성만 존재하는 클래스 , getter / setter 구성)
    - ScoreDAO 클래스 활용(데이터베이스 액션 처리)
    - Process 클래스 활용(업무 단위 기능 구성)
    - DBConn 클래스(데이터베이스 연결 전담 전용 객체 처리)
    
※ 단, 모든 작업 객체는 PreparedStatement 를 활용한다.

여러 명의 이름, 국어점수, 영어점수, 수학점수를 입력받아
총점, 평균, 석차 등을 계산하여 출력하는 프로그램을 구현한다.


실행 예)

=====[ 성적 처리 ]=====
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종료) : 3

>> 검색할 이름 입력 : 홍길동

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

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

 


 

 

ScoreDTO.java

int        kor, eng, mat, tot, rank
String  sid, name
double avg

package com.test;

public class ScoreDTO
{
	//번호  이름  국어  영어  수학  총점  평균  석차

	// 주요 속성 구성
	private int kor, eng, mat, tot, rank;
	private String sid, name;
	private double avg;
	
	// getter / setter 구성
	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 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 double getAvg()
	{
		return avg;
	}
	public void setAvg(double avg)
	{
		this.avg = avg;
	}
	
	
}

 

 

 

 

 

ScoreDAO.java

package com.test;

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

import com.util.DBConn;

public class ScoreDAO
{
	/*
	=====[ 성적 처리 ]=====
	1. 성적 입력
	2. 성적 전체 출력
	3. 이름 검색 출력
	4. 성적 수정
	5. 성적 삭제
	=======================
	*/
	// 연결 속성 구성
	public Connection conn;
	
	// 데이터베이스 연결
	public Connection Connection() throws ClassNotFoundException, SQLException
	{
		conn = DBConn.getConnection();
		return conn;
	}
	
	// 성적 입력 메소드
	public int add(ScoreDTO dto) throws SQLException
	{
		int result = 0;
		
		String sql = "INSERT INTO TBL_SCORE(SID, NAME, KOR, ENG, MAT) VALUES(SCORESEQ.NEXTVAL, ?, ?, ?, ?)";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		pstmt.setString(1, dto.getName());
		pstmt.setInt(2, dto.getKor());
		pstmt.setInt(3, dto.getEng());
		pstmt.setInt(4, dto.getMat());
		
		result = pstmt.executeUpdate();
		
		pstmt.close();
		
		return result;
	}
	
	// 전체 학생 수 count 메소드
	public int countAll() throws SQLException
	{
		int result = 0;
		
		String sql = "SELECT COUNT(*) AS COUNT FROM TBL_SCORE";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		ResultSet rs = pstmt.executeQuery();
		
		while (rs.next())
		{
			result = rs.getInt("COUNT");
		}
		
		rs.close();
		pstmt.close();
		
		return result;
	}
	
	// 전체 학생 성적 출력 메소드
	public ArrayList<ScoreDTO> lists() throws SQLException
	{
		ArrayList<ScoreDTO> result = new ArrayList<ScoreDTO>();
		
		String sql = "SELECT SID, NAME, KOR, ENG, MAT, (KOR+ENG+MAT) AS TOT, ROUND(((KOR+ENG+MAT)/3), 2) AS AVG, RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK FROM TBL_SCORE";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		ResultSet rs = pstmt.executeQuery();
		
		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();
		pstmt.close();
		
		return result;
	}
	
	// 학생 검색 메소드
	public ArrayList<ScoreDTO> search(String key, String value) throws SQLException
	{
		ArrayList<ScoreDTO> result = new ArrayList<ScoreDTO>();
		String sql = "";
		
		PreparedStatement pstmt;
		
		
		if (key.equals("SID"))
		{
			sql = "SELECT SID, NAME, KOR, ENG, MAT, (KOR+ENG+MAT) AS TOT, ROUND(((KOR+ENG+MAT)/3), 2) AS AVG, RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK FROM TBL_SCORE WHERE SID = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, Integer.parseInt(value));
		}
		else
		{
			sql = "SELECT SID, NAME, KOR, ENG, MAT, (KOR+ENG+MAT) AS TOT, ROUND(((KOR+ENG+MAT)/3), 2) AS AVG, RANK() OVER(ORDER BY (KOR+ENG+MAT) DESC) AS RANK FROM TBL_SCORE WHERE NAME = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, value);
		}
			
		ResultSet rs = pstmt.executeQuery();
		
		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();
		pstmt.close();
		
		return result;
		
	}
	
	// 검색한 결과 count 메소드
	public int searchCount(String key, String value) throws SQLException
	{
		int result = 0;
		String sql = "";
		PreparedStatement pstmt;
		
		
		
		if (key.equals("SID"))
		{
			sql = "SELECT COUNT(*) AS COUNT FROM TBL_SCORE WHERE SID = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, Integer.parseInt(value));
		}
		else
		{
			sql = "SELECT COUNT(*) AS COUNT FROM TBL_SCORE WHERE NAME = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, value);
		}
		
		ResultSet rs = pstmt.executeQuery();
		
		while (rs.next())
		{
			result = rs.getInt("COUNT");
		}
		
		rs.close();
		pstmt.close();
		
		return result;
	}

	
	// 학생 성적 수정 메소드
	public int modify(ScoreDTO dto) throws SQLException
	{
		int result = 0;
		
		String sql = "UPDATE TBL_SCORE SET NAME = ?, KOR = ?, ENG = ?, MAT = ? WHERE SID = ?";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		pstmt.setString(1, dto.getName());
		pstmt.setInt(2, dto.getKor());
		pstmt.setInt(3, dto.getEng());
		pstmt.setInt(4, dto.getMat());
		pstmt.setInt(5, Integer.parseInt(dto.getSid()));
		
		result = pstmt.executeUpdate();
		
		pstmt.close();
		
		return result;
	}
	
	
	// 학생 성적 삭제 메소드
	public int delete(int sid) throws SQLException
	{
		int result = 0;
		
		String sql = "DELETE FROM TBL_SCORE WHERE SID = ?";
		
		PreparedStatement pstmt = conn.prepareStatement(sql);
		
		pstmt.setInt(1, sid);
		
		result = pstmt.executeUpdate();
		
		pstmt.close();
		
		return result;
	}
	
	// 데이터베이스 종료
	public void close() throws SQLException
	{
		DBConn.close();
	}
	
	
}

 

 

 

 

 

ScoreProcess.java

package com.test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

public class ScoreProcess
{
	/*
	1. 성적 입력
	2. 성적 전체 출력
	3. 이름 검색 출력
	4. 성적 수정
	5. 성적 삭제
	*/
	
	private ScoreDAO dao;
	
	// 사용자 정의 생성자
	public ScoreProcess()
	{
		dao = new ScoreDAO();
	}
	
	// 성적 입력 기능
	public void scoreInsert() throws SQLException
	{
		try
		{
			dao.Connection();
			
			int count = dao.countAll();
			
			Scanner sc = new Scanner(System.in);
			
			do
			{

				System.out.printf("\n>> %d번 학생 성적 입력(이름 국어 영어 수학) : ", ++count);
				String name = sc.next();
				
				if (name.equals("."))
					break;
				
				int kor = sc.nextInt();
				int eng = sc.nextInt();
				int mat = sc.nextInt();
				
				ScoreDTO dto = new ScoreDTO();
				
				dto.setName(name);
				dto.setKor(kor);
				dto.setEng(eng);
				dto.setMat(mat);
				
				int result = dao.add(dto);
				
				if (result > 0)
					System.out.println(">> 성적 입력이 완료되었습니다.");
				else
					System.out.println(">> 성적 입력에 실패하였습니다.");
				
			} while (true);
			
			dao.close();
			
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	
	// 성적 전체 출력 기능
	public void scoreLists() throws SQLException
	{
		try
		{
			dao.Connection();
			
			int count = dao.countAll();
			
			System.out.printf("\n전체 인원 : %d명\n", count); 
			
			System.out.println("================================================");
			
			System.out.println("번호  이름    국어 영어 수학 총점  평균  석차");
			
			for (ScoreDTO dto : dao.lists())
			{
				System.out.printf("%3s %5s %4d %4d %4d %5d %.2f %3d\n"
								  , dto.getSid(), dto.getName()
								  , dto.getKor(), dto.getEng(), dto.getMat()
								  , dto.getTot(), dto.getAvg(), dto.getRank());
			}
			System.out.println("");
			
			dao.close();
		
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	
	// 이름 검색 출력 기능
	public void scoreNameLists()
	{
		try
		{
			dao.Connection();
			
			Scanner sc = new Scanner(System.in);
			
			System.out.print("\n>> 검색할 학생의 이름 입력 : ");
			String name = sc.next();
			
			int count = dao.searchCount("NAME", name);
			
			if (count != 0)
			{
				System.out.printf("\n검색 인원 : %d명\n", count); 
				
				System.out.println("================================================");
				
				System.out.println("번호  이름    국어 영어 수학 총점  평균  석차");
				
				
				for (ScoreDTO dto : dao.search("NAME", name))
				{
					System.out.printf("%3s %5s %4d %4d %4d %5d %.2f %3d"
							  , dto.getSid(), dto.getName()
							  , dto.getKor(), dto.getEng(), dto.getMat()
							  , dto.getTot(), dto.getAvg(), dto.getRank());
				}
				System.out.println("");
				
			}
			else
				System.out.println(">> 검색 결과가 존재하지 않습니다.");
			
			
			dao.close();
			
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	
	// 성적 수정 기능 // modify(ScoreDTO dto)
	public void scoreModify()
	{
		try
		{
			dao.Connection();
			
			Scanner sc = new Scanner(System.in);
			
			System.out.print("\n>> 수정할 학생의 번호 입력 : ");
			String sid = sc.next();
			
			ArrayList<ScoreDTO> ArrayList = dao.search("SID", sid);
			
			System.out.println("================================================");
			
			System.out.println("번호  이름    국어 영어 수학 총점  평균  석차");
			
			
			for (ScoreDTO dto : dao.search("SID", sid))
			{
				System.out.printf("%3s %5s %4d %4d %4d %5d %.2f %3d"
						  , dto.getSid(), dto.getName()
						  , dto.getKor(), dto.getEng(), dto.getMat()
						  , dto.getTot(), dto.getAvg(), dto.getRank());
			}
			System.out.println("");
			
			System.out.print(">> 수정할 내용 입력(이름 국어 영어 수학) : ");
			String name = sc.next();
			int kor = sc.nextInt();
			int eng = sc.nextInt();
			int mat = sc.nextInt();
			
			ScoreDTO dto = new ScoreDTO();

			dto.setSid(sid);
			dto.setName(name);
			dto.setKor(kor);
			dto.setEng(eng);
			dto.setMat(mat);
			
			int result = dao.modify(dto);
			
			if (result > 0)
				System.out.println(">> 수정이 완료되었습니다.\n");
			else
				System.out.println(">> 수정에 실패하였습니다.\n");
			
			dao.close();
			
		} catch (Exception e)
		{
			System.out.println(e.toString());
		}
	}
	
	// 성적 삭제 기능
	public void scoreDelete()
	{
		try
		{
			dao.Connection();
			
			System.out.print("\n>> 삭제할 학생의 번호 입력 : ");
			Scanner sc = new Scanner(System.in);
			String sid = sc.next();
			
			ArrayList<ScoreDTO> ArrayList = dao.search("SID", sid);
			
			System.out.println();
			System.out.println("================================================");
			
			System.out.println("번호  이름    국어 영어 수학 총점  평균  석차");
			
			for (ScoreDTO dto : dao.search("SID", sid))
			{
				System.out.printf("%3s %5s %4d %4d %4d %5d %.2f %3d"
						  , dto.getSid(), dto.getName()
						  , dto.getKor(), dto.getEng(), dto.getMat()
						  , dto.getTot(), dto.getAvg(), dto.getRank());
			}
			System.out.println("");
			
			if (ArrayList.size() > 0)
			{
				System.out.println(">> 정말로 삭제하시겠습니까?");
				
				String ch = sc.next();
				
				if (ch.equals("Y") || ch.equals("y"))
				{
					int result = dao.delete(Integer.parseInt(sid));
					
					if (result > 0)
					{
						System.out.println(">> 삭제가 완료되었습니다.");
					}
					else
						System.out.println(">> 삭제에 실패했습니다.");
				}
				else
					System.out.println(">> 삭제가 취소되었습니다.");	
			}
			else
			{
				System.out.println(">> 삭제할 대상이 존재하지 않습니다.");
			}
			
			dao.close();
		} 
		catch (Exception e)
		{
			System.out.println(e.toString());
		}
		
	}
	
}

 

 

 

 

 

ScoreMain.java

/*=================
   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("\n=====[ 성적 처리 ]=====");
			System.out.println("1. 성적 입력");
			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종료) : ");
			
			int menu = sc.nextInt();
			
			try
			{	
				if (menu == -1)
				{
					System.out.println();
					System.out.println("프로그램을 종료합니다.");
					return;
				}
				
				switch (menu)
				{
					case 1 :
						prc.scoreInsert();
						break;
					case 2 :
						prc.scoreLists();
						break;
					case 3 :
						prc.scoreNameLists();
						break;
					case 4 :
						prc.scoreModify();
						break;
					case 5 :
						prc.scoreDelete();
						break;
				}
			} catch (Exception e)
			{
				System.out.println(e.toString());
			}
		} while (true);
		
	}
}

 

 


! 현재 배워가고 있는 주인장이 쓴 글이니 정보의 정확성에 유의하시기 바랍니다 !