11. 응용 실습으로 들어가기 전에
개념여기까지는
JDBC의 부품과 기본 구조를 하나씩 본 단계였다.
이제부터는 그 요소들을 한 문제 안에서 함께 사용하는 단계다.
그래서 응용 실습은 단순히 코드를 한 줄 더 쓰는 문제가 아니라,
앞에서 배운 개념들이 실제로 어떻게 묶여서 쓰이는지 확인하는 구간이라고 보면 된다.
즉, 지금부터는
- DB 접속
Statement또는PreparedStatement- 조회나 변경 실행
- 결과 유무 확인
- 반복문과 조건 분기
- 입력값 처리
를 한 문제 안에서 함께 써야 한다.
또 응용 실습에서는 개념만 아는 것으로 끝나지 않고,
문제에서 요구한 출력 형식과 실행 순서까지 맞춰야 한다는 점도 중요하다.
12. 응용 실습 1 - SelectEmpLab
문제에서 무엇을 하려는지이 문제는 단순히 조회 하나만 실행하는 문제가 아니다.
랜덤값에 따라 서로 다른 조회를 두 갈래로 처리하는 프로그램을 만드는 문제다.
즉, 지금까지 따로따로 봤던 DB 접속,
Statement생성, 조회 실행, 결과 출력, 조건 분기, 날짜 또는 급여 형식 맞추기를 한 문제 안에서 함께 써야 한다.
이 예제에서 사용된 개념
ConnectionStatementexecuteQuery()ResultSetRandomif-else- 숫자 출력 가공
- 날짜 출력 가공
- 정렬
코드 흐름
- DB 서버에 접속한다.
Random으로true또는false를 만든다.true이면 직원 이름과 월급을 조회한다.false이면 직원 이름과 입사 날짜를 오래된 순으로 조회한다.- 문제 형식에 맞게 출력한다.
- 사용한 자원을 닫는다.
코드 예제package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Random; public class SelectEmpLab { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/edudb?characterEncoding=UTF-8&serverTimezone=UTC"; String user = "jdbctest"; String passwd = "jdbctest"; try (Connection conn = DriverManager.getConnection(url, user, passwd); Statement stmt = conn.createStatement()) { // 1. DB 연결과 SQL 실행 객체를 준비함 Random random = new Random(); boolean flag = random.nextBoolean(); // 2. true / false 랜덤값 생성 String sql; if (flag) { // 3. true면 이름 + 월급 조회 sql = "select ename, format(sal, 0) sal from emp"; } else { // 4. false면 이름 + 입사일 조회(오래된 순) sql = "select ename, date_format(hiredate, '%Y년 %m월 %d일') hireinfo " + "from emp order by hiredate asc"; } try (ResultSet rs = stmt.executeQuery(sql)) { // 5. 선택된 SQL 실행 if (flag) { while (rs.next()) { // 6. 월급 조회 결과 출력 System.out.println(rs.getString("ename") + " 직원의 월급은 " + rs.getString("sal") + "달러입니다."); } } else { while (rs.next()) { // 7. 입사일 조회 결과 출력 System.out.println(rs.getString("ename") + " 직원은 " + rs.getString("hireinfo") + "에 입사하였습니다."); } } } } catch (Exception e) { System.out.println(e.getMessage()); } } } // 실행 예시(true 분기) // SMITH 직원의 월급은 800달러입니다. // ALLEN 직원의 월급은 1,600달러입니다. // 실행 예시(false 분기) // SMITH 직원은 1980년 12월 17일에 입사하였습니다. // ALLEN 직원은 1981년 02월 20일에 입사하였습니다.
코드 해설이 문제의 핵심은
Random결과에 따라
실행할 조회문 자체가 달라진다는 점이다.
true일 때는ename,sal을 조회하고,
false일 때는ename,hiredate를 조회한다.
즉, 연결과 실행 구조는 같지만SQL과 출력 형식이 분기된다.
또 월급은
format(sal, 0)으로 천 단위,를 붙여 가져오고,
입사일은date_format(hiredate, '%Y년 %m월 %d일')로 바로 출력 형식에 맞춰 가져온다.
즉, 자바 쪽에서 다시 가공하기보다SQL에서 미리 보기 좋게 만들어 두는 방식이다.
결국 이 문제는
같은 JDBC 흐름 위에서 SQL과 출력 형식을 분기 처리하는 응용 문제라고 이해하면 된다.
헷갈리기 쉬운 부분이 문제는
if-else가 자바 코드 출력만 나누는 것이 아니라,
실행할 조회문 자체를 나누는 구조라는 점이 중요하다.
또 입사일 정렬은
order by hiredate asc를 써야
오래된 입사 순으로 출력할 수 있다.
출력 문장은 문제에서 요구한 형식 그대로 맞추는 것이 중요하다.
그래서달러입니다.,입사하였습니다.같은 끝 문구도 함께 확인해야 한다.
13. 응용 실습 2 - CheckEmpLab
문제에서 무엇을 하려는지이 문제는 사용자가 입력한 직원 이름을 기준으로
그 직원이 실제로 근무 중인지 확인해 주는 프로그램이다.
겉보기에는 간단한 검색처럼 보이지만, 실제로는
- 사용자 입력
- 조건 조회
- 결과 유무 확인
- 존재하면 상세 정보 출력
- 존재하지 않으면 다른 메시지 출력
- 계속할지 물어보고 반복 실행
이 한꺼번에 들어 있다.
이 예제에서 사용된 개념
Scanner- 조건 조회
PreparedStatement- 대소문자 구분 없는 비교
if(rs.next())- 반복문
코드 흐름
- DB 서버에 접속한다.
- 검색할 직원 이름을 입력받는다.
- 입력한 이름으로 직원을 조회한다.
- 결과가 있으면 근무 중이라는 메시지와 상세 정보를 출력한다.
- 결과가 없으면 근무하지 않는다고 출력한다.
- 계속할지 물어보고 반복하거나 종료한다.
코드 예제package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Scanner; public class CheckEmpLab { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/edudb?characterEncoding=UTF-8&serverTimezone=UTC"; String user = "jdbctest"; String passwd = "jdbctest"; String sql = "select ename, date_format(hiredate, '%Y년 %m월') hireinfo, deptno " + "from emp where upper(ename) = upper(?)"; try (Connection conn = DriverManager.getConnection(url, user, passwd); PreparedStatement pstmt = conn.prepareStatement(sql); Scanner scan = new Scanner(System.in)) { // 1. DB 연결, SQL 틀, 입력 객체 준비 while (true) { // 2. 계속 검색할 수 있도록 반복 시작 System.out.print("검색하려는 직원 이름을 입력하세요 : "); String name = scan.nextLine(); // 3. 검색할 직원 이름 입력 pstmt.setString(1, name); // 4. 첫 번째 ? 자리에 입력한 이름 설정 try (ResultSet rs = pstmt.executeQuery()) { // 5. 조건 조회 실행 if (rs.next()) { // 6. 직원이 존재하면 첫 번째 행으로 이동한 상태 System.out.println(rs.getString("ename") + " 직원은 근무중입니다."); System.out.println(rs.getString("hireinfo") + "에 입사했고 현재 " + rs.getInt("deptno") + " 번부서에서 근무하고 있습니다."); } else { // 7. 직원이 없으면 안내 문구 출력 System.out.println(name + " 직원은 근무하지 않습니다."); } } System.out.print("계속 검토하시겠습니까?(y/n) : "); String answer = scan.nextLine(); // 8. 계속할지 입력받음 if (!answer.equalsIgnoreCase("y")) { System.out.println("프로그램을 종료합니다."); break; } } } catch (Exception e) { System.out.println(e.getMessage()); } } } // 실행 예시 // 검색하려는 직원 이름을 입력하세요 : smith // SMITH 직원은 근무중입니다. // 1980년 12월에 입사했고 현재 20 번부서에서 근무하고 있습니다.
코드 해설이 문제는 단순 검색이 아니라
결과가 있느냐 없느냐에 따라 출력이 갈리는 조회 문제다.
여기서 중요한 점은 이름 비교를 대소문자 구분 없이 처리해야 한다는 것이다.
그래서upper(ename) = upper(?)형태로 비교해서
SMITH,smith,Smith처럼 입력해도 같은 직원으로 찾을 수 있게 만들었다.
또
PreparedStatement를 사용했기 때문에
입력한 이름을?자리에 넣고 실행하는 구조가 분명하다.
그리고 이 예제는 한 번 조회하고 끝나는 것이 아니라
검색 → 결과 확인 → 계속 여부 판단 → 반복 또는 종료 흐름으로 움직인다.
즉, 이 문제는
입력값을 조건으로 조회하고, 결과 유무에 따라 다른 출력을 만드는 응용 문제라고 이해하면 된다.
헷갈리기 쉬운 부분직원이 존재하지 않는 경우는 SQL 오류가 아니라
조건에 맞는 결과가 없는 경우다.
그래서if(rs.next())로 먼저 존재 여부를 확인해야 한다.
또 상세 정보 출력에서 연도와 월 형식은
date_format(hiredate, '%Y년 %m월')로 미리 가공해서 가져오는 구조다.
14. 응용 실습 3 - InsertBookLab
문제에서 무엇을 하려는지이 문제는 사용자에게 도서명, 가격, 도서분류를 입력받아
book테이블에 저장하는 프로그램을 만드는 문제다.
단순히 한 번 저장하고 끝나는 것이 아니라,
계속 입력할지 물어보고 원할 때까지 반복 처리해야 한다.
또 도서분류는 문자열을 직접 입력하는 것이 아니라
숫자를 선택해서b01,b02,b03,b04,b05중 하나로 바꿔 넣어야 한다.
여기서는 앞에서 생성한
book(id, title, price, kind)구조를 기준으로 본다.
이 예제에서 사용된 개념
PreparedStatement- 사용자 입력
- 반복문
- 선택 메뉴 처리
executeUpdate()- 입력 성공 횟수 누적
코드 흐름
- DB 서버에 접속한다.
- 도서명과 가격을 입력받는다.
- 도서분류 번호를 입력받는다.
- 선택한 번호를
b01~b05코드로 바꾼다.PreparedStatement로book테이블에 저장한다.- 저장 성공 횟수를 증가시킨다.
- 계속 입력할지 물어보고 반복하거나 종료한다.
- 마지막에 총 입력 건수를 출력한다.
코드 예제package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.Scanner; public class InsertBookLab { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/edudb?characterEncoding=UTF-8&serverTimezone=UTC"; String user = "jdbctest"; String passwd = "jdbctest"; String sql = "insert into book(title, price, kind) values (?, ?, ?)"; int count = 0; try (Connection conn = DriverManager.getConnection(url, user, passwd); PreparedStatement pstmt = conn.prepareStatement(sql); Scanner scan = new Scanner(System.in)) { // 1. DB 연결, SQL 틀, 입력 객체 준비 while (true) { // 2. 도서 입력 반복 시작 System.out.print("도서명을 입력하세요 : "); String title = scan.nextLine(); // 3. 도서명 입력 System.out.print("가격을 입력하세요 : "); int price = Integer.parseInt(scan.nextLine()); // 4. 가격 입력 System.out.println("도서분류에 대한 넘버를 입력하세요."); System.out.println(" 1. 프로그래밍 언어"); System.out.println(" 2. 웹 프로그래밍"); System.out.println(" 3. 빅데이터"); System.out.println(" 4. 데이터베이스"); System.out.println(" 5. 인프라"); System.out.print("선택(1~5) : "); int menu = Integer.parseInt(scan.nextLine()); // 5. 도서분류 번호 입력 String kind; switch (menu) { case 1: kind = "b01"; break; case 2: kind = "b02"; break; case 3: kind = "b03"; break; case 4: kind = "b04"; break; case 5: kind = "b05"; break; default: System.out.println("도서분류 번호는 1~5만 입력할 수 있습니다."); continue; } // 6. 입력한 번호를 b01~b05 코드로 변환 pstmt.setString(1, title); // 7. 첫 번째 ? 자리에 도서명 설정 pstmt.setInt(2, price); // 8. 두 번째 ? 자리에 가격 설정 pstmt.setString(3, kind); // 9. 세 번째 ? 자리에 도서분류 코드 설정 int result = pstmt.executeUpdate(); // 10. book 테이블에 데이터 저장 if (result > 0) { count++; System.out.println("정보가 입력되었습니다."); } System.out.print("계속 입력하겠습니까?(y/n) : "); String answer = scan.nextLine(); // 11. 계속 입력 여부 확인 if (!answer.equalsIgnoreCase("y")) { break; } } System.out.println(count + "개의 데이터 입력 완료!"); // 12. 전체 입력 성공 건수 출력 } catch (Exception e) { System.out.println(e.getMessage()); } } } // 실행 예시 // 도서명을 입력하세요 : 자바의 정석 // 가격을 입력하세요 : 36000 // 선택(1~5) : 1 // 정보가 입력되었습니다. // 계속 입력하겠습니까?(y/n) : n // 1개의 데이터 입력 완료!
코드 해설이 문제의 핵심은
사용자가 입력한 여러 값을 가공해서book테이블에 저장하는 흐름이다.
도서명과 가격은 바로 넣을 수 있지만,
도서분류는 사용자가 입력한 숫자를 그대로 저장하는 게 아니라
b01~b05코드로 바꿔서 넣어야 한다.
그래서 이 예제는
입력값 받기 → 메뉴 번호를 분류 코드로 변환 →
PreparedStatement에 값 넣기 → 저장 실행 → 성공 건수 누적흐름으로 이해하면 된다.
또
PreparedStatement를 반드시 사용해야 하므로
insert into book(title, price, kind) values (?, ?, ?)틀을 먼저 만들고
각 자리에 값을 채운 뒤executeUpdate()를 실행하는 구조를 써야 한다.
마지막에는 반복 입력이 끝난 뒤
누적한count를 이용해 총 몇 건이 저장되었는지 출력한다는 점도 중요하다.
헷갈리기 쉬운 부분
book테이블의id가 자동 증가라면
insert할 때는title,price,kind만 넣으면 된다.
또 도서분류 번호가 1~5가 아닌 경우는
잘못된 입력이므로 저장하지 않고 다시 반복하게 만드는 것이 자연스럽다.
15. 응용 실습 4 - SelectBookLab
문제에서 무엇을 하려는지이 문제는 메뉴를 보여 주고,
선택한 번호에 따라 서로 다른 조건의 도서 목록을 출력하는 프로그램을 만드는 문제다.
즉, 단순 조회 하나가 아니라
메뉴 분기 + 조건이 다른 여러 개의 조회문을 반복해서 처리해야 한다.
또 1번과 2번은 4개 컬럼 전체를 출력하고,
3번부터 6번은 제목과 가격만 출력해야 한다는 차이도 있다.
여기서도 앞에서 생성한
book(id, title, price, kind)구조를 기준으로 본다.
이 예제에서 사용된 개념
- 메뉴 출력
if-else또는switch- 조건이 다른 여러 개의 조회문
- 반복 실행
- 가격 출력 가공
- 전체 열 출력과 일부 열 출력 구분
코드 흐름
- 메뉴를 출력한다.
- 사용자가 번호를 선택한다.
- 번호에 맞는 조회문을 결정한다.
- 조회를 실행한다.
- 선택한 메뉴에 따라 4개 컬럼 전체 또는 제목과 가격만 출력한다.
- 계속할지 물어보고 다시 메뉴로 돌아가거나 종료한다.
코드 예제package jdbcexam; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Scanner; public class SelectBookLab { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/edudb?characterEncoding=UTF-8&serverTimezone=UTC"; String user = "jdbctest"; String passwd = "jdbctest"; try (Connection conn = DriverManager.getConnection(url, user, passwd); Statement stmt = conn.createStatement(); Scanner scan = new Scanner(System.in)) { // 1. DB 연결, SQL 실행 객체, 입력 객체 준비 while (true) { // 2. 메뉴 반복 시작 System.out.println("1. 모두 출력하기"); System.out.println("2. 가격이 높은 순으로 출력하기"); System.out.println("3. 20000 이상의 도서들만 출력하기"); System.out.println("4. 웹 프로그래밍 도서들만 출력하기"); System.out.println("5. 데이터베이스와 인프라 도서들만 출력하기"); System.out.println("6. 도서명에 '자바'를 포함하는 도서들만 출력하기"); System.out.print("원하는 메뉴의 번호를 선택 : "); int menu = Integer.parseInt(scan.nextLine()); // 3. 사용자가 원하는 메뉴 선택 String sql = null; boolean printAll = false; switch (menu) { case 1: sql = "select id, title, concat(format(price, 0), '원') fprice, kind from book"; printAll = true; break; case 2: sql = "select id, title, concat(format(price, 0), '원') fprice, kind " + "from book order by price desc"; printAll = true; break; case 3: sql = "select title, concat(format(price, 0), '원') fprice from book where price >= 20000"; break; case 4: sql = "select title, concat(format(price, 0), '원') fprice from book where kind = 'b02'"; break; case 5: sql = "select title, concat(format(price, 0), '원') fprice from book " + "where kind in ('b04', 'b05')"; break; case 6: sql = "select title, concat(format(price, 0), '원') fprice from book " + "where title like '%자바%'"; break; default: System.out.println("메뉴는 1~6 중에서 선택해야 합니다."); continue; } // 4. 선택한 메뉴에 맞는 조회문 결정 try (ResultSet rs = stmt.executeQuery(sql)) { // 5. 선택한 조회문 실행 boolean hasData = false; while (rs.next()) { hasData = true; // 6. 결과가 있는지 확인하면서 출력 if (printAll) { // 7. 1번, 2번은 모든 컬럼 출력 System.out.println(rs.getInt("id") + "\t" + rs.getString("title") + "\t" + rs.getString("fprice") + "\t" + rs.getString("kind")); } else { // 8. 3번~6번은 제목과 가격만 출력 System.out.println(rs.getString("title") + "\t" + rs.getString("fprice")); } } if (!hasData) { System.out.println("조회된 도서가 없습니다."); } } System.out.print("계속 처리하겠습니까?(y/n) : "); String answer = scan.nextLine(); // 9. 계속 처리 여부 확인 if (!answer.equalsIgnoreCase("y")) { System.out.println("프로그램을 종료합니다."); break; } } } catch (Exception e) { System.out.println(e.getMessage()); } } } // 실행 예시 // 원하는 메뉴의 번호를 선택 : 6 // 자바의 정석 36,000원 // 계속 처리하겠습니까?(y/n) : n // 프로그램을 종료합니다.
코드 해설이 문제의 핵심은
메뉴에 따라 서로 다른 조회문을 선택해서 실행하는 것이다.
여기서는 1~6번 메뉴마다
sql문자열을 다르게 정하고,
그 뒤 공통으로executeQuery()를 실행하는 구조를 사용했다.
또 1번과 2번은
id,title,price,kind전체를 출력해야 하고,
3번부터 6번은 제목과 가격만 출력해야 하므로
printAll같은 기준을 두고 출력 형식을 나눠 처리했다.
가격은 문제 조건에 맞게
concat(format(price, 0), '원')형태로 SQL에서 미리 가공했다.
즉, 이 예제의 핵심 흐름은 이렇다.
메뉴 선택 → 메뉴별 SQL 결정 → 조회 실행 → 출력 형식 분기 → 계속 여부 확인
또 잘못된 메뉴 번호를 입력했을 때는
바로 다음 반복으로 넘어가 다시 메뉴를 선택하게 만든 점도 함께 볼 수 있다.
헷갈리기 쉬운 부분
4. 웹 프로그래밍 도서들만 출력하기는
kind = 'b02'조건으로 처리해야 한다.
또
5. 데이터베이스와 인프라 도서들만 출력하기는
두 분류를 함께 조회해야 하므로
in ('b04', 'b05')처럼 묶어서 처리하는 방식이 자연스럽다.
1번과 2번만 전체 컬럼 출력이고,
3번부터 6번은 제목과 가격만 출력이라는 차이도 놓치기 쉽다.
16. 전체 흐름 정리
개념지금까지 본 내용은 따로따로 흩어진 예제처럼 보여도 사실 하나의 흐름이다.
처음에는
JDBC가 무엇인지 먼저 잡고,
그다음에는Connection,Statement,ResultSet,PreparedStatement같은 핵심 부품의 역할을 이해했다.
이어서
DBConnect로 실제 연결을 확인했고,
emp테이블로 조회 기본 구조와 조건 조회,next()처리, 정렬·그룹 조회·서브쿼리·조인까지 보았다.
그다음
student에서는
테이블 생성 → 데이터 삽입 → 조회 → 추가 입력 → 수정 → 삭제 → 마지막 테이블 삭제 흐름을 차례대로 보았다.
그리고
visitor예제로 자원 반납을 보고,
이미지 예제로 파일 데이터 처리까지 확장한 뒤,
마지막에는 응용 실습으로 지금까지 배운 내용을 한 번에 묶어 보았다.
즉, 이번 범위는 한 줄로 정리하면 이렇다.
자바에서
JDBC를 이용해 DB에 접속하고, 조회하고, 데이터를 바꾸고, 입력값을 처리하는 전체 기본 흐름을 익히는 범위다.
이제는 개별 객체 이름을 아는 수준에서 끝나는 것이 아니라,
연결 → 실행 → 결과 처리 → 입력값 반영 → 자원 반납까지를 하나의 흐름으로 볼 수 있어야 한다.
다시 말하면, 이번 범위의 핵심은
문법 한 줄을 외우는 것이 아니라
자바 프로그램이 DB와 실제로 어떻게 연결되고 움직이는지 전체 흐름을 이해하는 것이다.
핵심 특징
- 앞부분은 연결과 핵심 객체 이해
- 중간은 조회 구조와 조회 확장
- 그다음은
student테이블로 보는 생성/삽입/조회/입력/수정/삭제/테이블 삭제 흐름- 마지막은 자원 반납, 이미지 처리, 응용 문제