Java에서 DB에 연결할 수 있게 해주는 Java Programming API(Java에 기본 내장된 인터페이스)
➡ JDBC는 java.sql 패키지에서 제공
- Java의 JDBC 관련 인터페이스
- DBMS (Oracle)
- Oracle에서 Java와 연결할 때 사용할 JDBC를 상속받아 구현할 클래스 모음(ojdbc10.jar 라이브러리)
그렇다면, JDBC를 이용하기 위해 단계별로 해야하는 것들에 대해서 알아보자!
JDBC 객체 참조 변수를 선언해야한다(java.sql 패키지의 인터페이스로 import 해야함!)
📑 Connection
DB 연결 정보를 담을 객체
Connection conn = null;
🤷♀️ 여기서 잠깐 ❓
DB연결 정보는 DBMS 타입, 이름, IP, Port, 계정명, 비밀번호 저장을 말한다.
DBeaver의 계정 접속 방법과 유사하다고 할 수 있으며 이 연결 정보는 Java와 DB 사이를 연결해주는 통로 역할을 할 것이다.
📑 Statement
Connection을 통해 SQL문을 DB에 전달하여 실행하고 생성된 결과 (ResultSet, 성공한 행의 개수)를 반환(Java)하는데 사용되는 객체
Statement stmt = null;
📑 ResultSet
SELECT 질의 성공 시 반환되는데, 조회 결과 집합을 나타내는 객체
ResultSet rs = null;
참조변수에 알맞은 객체를 대입한다.
◾ 런타임 시점에 해당 경로의 클래스를 동적으로 로드함
Class.forName("oracle.jdbc.driver.OracleDriver");
▷ () 안에 작성된 클래스의 객체를 반환한다.
▶ 메모리에 객체가 생성되어지고 JDBC 필요 시 알아서 참조하여 사용되기에 생략해도 자동으로 메모리 로드가 진행된다! BUT, 명시적으로 작성하는 걸 권장하기에 적어주면 좋다!
◾ DriverManager 객체를 이용해서 Connection 객체를 만들어 이용
String type = "jdbc:oracle:thin:@"; ▷▶ JDBC 드라이버 종류
String ip = "localhost"; ▷▶ DB 서버 컴퓨터 IP // == 127.0.0.1 (loop back ip)
String port = ":1521"; ▷▶ 포트번호 // 1521 (기본값)
String sid =":XE"; ▷▶ DB 이름 // url == jdbc:oracle:thin:@localhost:1521:XE
String user = "kh_lmk"; ▷▶ 사용자계정
String pw = "kh1234"; ▷▶ 비밀번호
❗ 단점 : 개인정보가 들어간 데이터를 넣기 때문에 보안상의 문제가 있으니 주의가 필요함 🤦♀️
객체를 만든 후 DriverManager에 전달하는데... 여기서?
DriverManager란 ❓ 메모리에 로드된 JDBC 드라이버를 이용해서 Connection 객체를 만드는 역할을 말한다.
conn = DriverManager.getConnection(type+ip+port+sid,user,pw);
url == jdbc:oracle:thin:@localhost:1521:XE
📣 주의 사항
JAVA에서 작성되는 SQL은 마지막에 ; 을 찍으면 안된다!
❌ String sql ="SELECT EMP_ID, EMP_NAME, SALARY, HIRE_DATE FROM EMPLOYEE;";
⭕ String sql ="SELECT EMP_ID, EMP_NAME, SALARY, HIRE_DATE FROM EMPLOYEE";
◾ Connection 객체를 통해서 생성
stmt = conn.createStatement();
rs =stmt.executeQuery(sql);
//▷▶ executeQuery() : SELECT문 수행 메서드, ResultSet 반환
SQL을 수행해서 반환 받은 결과 (ResultSet)를 한 행씩 접근해서 컬럼값 얻어오기
while(rs.next()) {
✔rs.next() : rs가 참조하고 있는 ResultSet 객체의 첫 번째 컬럼부터 순서대로 한행씩 이동하며 다음 행이 있을 경우,
true, 없으면 false 반환!
◾ [작성방법] : rs.get자료형("컬럼명")
String empId = rs.getString("EMP_ID");
//▶ "200", ➡ 현재 행의 "EMP_ID" 문자열 컬럼의 값을 얻어옴
String empName = rs.getString("EMP_NAME"); //▶ "선동일"
int salary = rs.getInt("SALARY"); //▶ 8,000,000
//[java.sql.Date]
Date hireDate = rs.getDate("HIRE_DATE"); //▶ YYYY-MM-DD 1990-02-06
System.out.printf("사번 : %s / 이름 : %s / 급여 : %d / 입사일 : %s \n",
empId, empName, salary, hireDate);
//👀 java.sql.Date의 toString()은 yyyy-mm-dd 형식으로 오버라이딩 되어있음.
}
사용한 JDBC 객체 자원 반환하기!
(close())
▷ Connection, Statement, ResultSet 으로 실행했다면,
close할 때는 생성된 역순(ResultSet➡Statement➡Connection)으로 닫는 것을 권장함.
📣 finally 안 try~catch문 중 try부분에 작성!
if(rs!= null) rs.close();
if(stmt!= null) stmt.close();
if(conn!= null) conn.close(); //▶ 각자 독립적인 객체들이기에 각각 다 닫아줘야 함!
/*
직급명, 급여를 입력받아 해당 직급에서 입력 받은 급여보다 많이 받는 사원의 이름, 직급명, 급여, 연봉을 조회하여 출력
✔ 단, 조회결과가 없으면 "조회 결과 없음" 출력!
✔조회 결과가 있으면 아래와 같이 출력!
[입력내용]
직급명 입력 : 부사장
급여 입력 : 5000000
[출력내용]
송종기 / 부사장 / 6000000 /72000000
노옹철 / 부사장 /3700000/44400000
*/
// Employee (empName, jobName, salary, annualIncome)
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Scanner sc = new Scanner(System.in);
try {
System.out.print("직급명 입력 : ");
String input1 = sc.next();
System.out.print("급여 입력 : ");
int input2 = sc.nextInt();
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "kh_lmk";
String pw = "kh1234";
conn = DriverManager.getConnection(url,user,pw);
String sql = "SELECT EMP_NAME, JOB_NAME, SALARY, SALARY*12 AS ANNUALINCOME"
+ " FROM EMPLOYEE"
+ " JOIN JOB USING(JOB_CODE)"
+ " WHERE JOB_NAME = '" + input1 +"'"
+ " AND SALARY > "+input2;
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
List<Employee> list = new ArrayList<Employee>();
while(rs.next()) {
String empName = rs.getString("EMP_NAME");
String jobName = rs.getString("JOB_NAME");
long salary = rs.getInt("SALARY");
long annualIncome = rs.getInt("ANNUALINCOME");
list.add(new Employee(empName, jobName, salary, annualIncome));
}
if(list.isEmpty()) {
System.out.println("조회 결과 없음");
}else {
for(Employee employee : list) {
System.out.println(employee);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(rs != null) rs.close();
if(stmt != null) rs.close();
if(conn != null) rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//입사일을 입력("2000-01-01") 받아 입력 받은 값 보다 먼저 입사한 사람의 이름, 입사일, 성별(M,F) 조회
Scanner sc = new Scanner(System.in);
Connection conn = null;
Statement stmt =null;
ResultSet rs = null;
try {
System.out.println("입사일 입력(YYYY-MM-DD) : ");
String input = sc.next();
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "kh_lmk";
String pw = "kh1234";
conn = DriverManager.getConnection(url,user,pw);
String sql = "SELECT EMP_NAME 이름 , TO_CHAR(HIRE_DATE,'YYYY\"년\" MM\"월\" DD\"일\"') 입사일,"
+ " DECODE(SUBSTR(EMP_NO,8,1),1,'M',2,'F') AS 성별"
+ " FROM EMPLOYEE"
+ " WHERE HIRE_DATE < TO_DATE('"+input+"')";
stmt = conn.createStatement();
rs=stmt.executeQuery(sql);
List<Employee> list = new ArrayList<Employee>();
while(rs.next()) {
Employee emp = new Employee();
emp.setEmpName(rs.getString("이름")); //조회 시 컬럼명이 "이름"
emp.setHireDate(rs.getString("입사일")); //조회 시 컬럼명이 "입사일"
emp.setGender(rs.getString("성별").charAt(0)); //조회 시 컬럼명이 "성별" / char 형태이기에 ! charaAt사용
//JaVA의 char : 문자 1개의 의미
//DB의 char : 고정길이 문자열 (== String)
list.add(emp);
}
// 조회결과가 없는 경우
if(list.isEmpty()) {
System.out.println("조회결과 없음");
}else {
for(int i =0; i<list.size();i++) {
System.out.printf("%02d) %s / %s / %c\n",i+1,list.get(i).getEmpName(), list.get(i).getHireDate(),list.get(i).getGender() );
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(rs !=null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}