2022. 3. 5. 20:40ㆍLanguage`/Java
"일단 JDBC Interface를 사용하려면 JDBC Driver가 필요하다"
1. 각 DBMS에 알맞은 드라이버를 구글링을 통해서 다운로드한다
2. 다운로드 후, 해당 드라이버를 자바 프로젝트 상에 적용시켜줘야 한다
현재 "sample" DB내의 "user" 테이블 현황
CREATE TABLE user(
idx INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
gender CHAR(2) NOT NULL,
bth DATE NOT NULL,
PRIMARY KEY(idx)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
1. 드라이버 로드
- DBMS에 맞는 드라이버를 다운로드하면 해당 드라이버를 로드해줘야 한다
Class.forName("[드라이버]");
- Class.forName()은 동적으로 JDBC 드라이브 클래스를 로드해주는 코드이다
- 지정한 드라이브 클래스가 객체화
- DriverManager.registerDriver()를 호출해서 드라이버 리스트에 등록된다
Oracle 드라이버
"oracle.jdbc.driver.OracleDriver"
>> Class.forName("oracle.jdbc.driver.OracleDriver");
MySQL 드라이버
// 예전 Version
"com.mysql.jdbc.Driver"
// 최신 Version
"com.mysql.cj.jdbc.Driver"
>> Class.forName("com.mysql.jdbc.Driver");
>> Class.forName("com.mysql.cj.jdbc.Driver");
MaridDB 드라이버
"org.mariadb.jdbc.Driver"
>> Class.forName("org.mariadb.jdbc.Driver");
2. DB연결을 위한 Connection 객체 생성
- 최근에는 Connection 객체 생성 단계에서 Class.forName()까지 같이 수행해주기 때문에 따로 Class.forName()을 작성할 필요가 없다
Connection con = DriverManager.getConnection(url, user, pwd);
url
- 해당 DB의 URL을 작성해야 한다
- 해당 DB의 위치
※ 오라클
"jdbc:oracle:thin:@[IP]:[포트 번호]:[서비스 이름]
IP : 로컬에 DB가 저장되어 있으면 "localhost"라고 작성하면 된다
포트 번호 : 오라클 DB의 포트 번호 :: default = 1521
서비스 이름(SID) : DB를 식별할 수 있는 이름
>> "jdbc:oracle:thin:@localhost:1521:orcl"
>> "jdbc:oracle:thin:@192.168.0.10:1521:xe"
※ MySQL
"jdbc:mysql://[IP]:[포트번호]/[DB이름]"
>> "jdbc:mysql://localhost:3306/test"
>> "jdbc:mysql://192.168.0.10:3306/sample"
※ MariaDB
"jdbc:mariadb://[IP]:[포트번호]/[DB이름]"
>> "jdbc:mariadb://localhost:3307/test"
>> "jdbc:mariadb://192.168.0.10:3307/sample"
user
- DB의 계정명
pwd
- 해당 DB의 계정의 비밀번호
// Oracle Version
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl" // url
"test" // id
"1234" // pwd
}
// MySQL Version
Connection con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/sample" // url
"test" // id
"1234" // pwd
}
// MariaDB Version
Connection con = DriverManager.getConnection(
"jdbc:mariadb://localhost:3307/sample" // url
"test" // id
"1234" // pwd
}
3. SQL 쿼리문 & 실행
- 요청할 SQL문을 전송할 때 필요하다
1) 정적인 쿼리문 Statement
Statement stmt = con.createStatement();
- 단일로 사용할 때 속도가 빠르다
- 쿼리에 인자를 부여할 수 없다
- 매번 컴파일을 수행해야 한다
- 쿼리 문장 분석
- 컴파일
- 실행
String url = "jdbc:mysql://localhost:3306/sample";
String user = "test";
String pwd = "1234";
Connection con = DriverManager.getConnection(url, user, pwd);
// getConnection을 통해서 자동적으로 Class.forName()까지 수행
Statement stmt = con.createStatement();
String sql = "SELECT * FROM user;"; // 정적인 SQL 쿼리문
ResultSet rs = stmt.executeQuery(sql); // SQL 쿼리문에 대한 결과값 저장
while(rs.next()){ // 결과값에서 ROW별로 순차적으로 가져오기
int idx = rs.getInt("idx");
String name = rs.getString("name");
String gender = rs.getString("gender");
Date birth = rs.getDate("bth");
// ROW의 각 COLUMN의 타입에 맞게 필드값 가져오기
System.out.println("## " + idx);
System.out.println("name : " + name);
System.out.println("gender : " + gender);
System.out.println("birthday : " + birth);
}
- Statement는 정적인 SQL 쿼리문을 통해서 해당 쿼리문에 대한 결과를 가져와야 한다
- 정적인 SQL 쿼리문 : 그 자체로 완성된 쿼리문
- ResultSet을 통해서 해당 SQL 쿼리문의 결과를 저장한다
- 여기서 next()는 해당 결과를 ROW별로 가져올 수 있다
- ROW의 각 COLUMN의 타입에 맞게 필드값을 가져와야 한다
- getInt("[컬럼명]"); / getString("[컬럼명]"); / getDate("[컬럼명]");
- 여기서 컬럼명은 대소문자를 구분하지 않는다
- get~()는 컬럼의 순서로도 지정할 수 있는데 컬럼의 첫번째는 1부터 시작한다
2) 동적인 쿼리문 PreparedStatement
PreparedStatement pstmt = con.preparedStatement();
- 쿼리에 인자를 부여할 수 있다
- 처음 컴파일된 후, 이후에는 컴파일을 수행하지 않는다
- 여러번 수행될 때 속도가 빠르다
- 가독성이 좋다
- 기존 Statement보다 성능이 좋다
>> 사용자의 입력값으로 쿼리를 생성할 경우 사용한다
String url = "jdbc:mysql://localhost:3306/sample";
String user = "test";
String pwd = "1234";
Connection con = DriverManager.getConnection(url, user, pwd);
// getConnection을 통해서 자동적으로 Class.forName()까지 수행
String sql = "SELECT * FROM user WHERE idx BETWEEN ? AND ?";
// 동적인 SQL 쿼리문
// 사용자가 "?" 부분에 적절한 값을 넣어줘야 완성된 SQL 쿼리문이 된다
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setInt(1, 1);
pstmt.setInt(2, 3);
// "?" 부분에 값을 채워넣는 코드
ResultSet rs = pstmt.executeQuery();
while(rs.next()){ // 결과값에서 ROW별로 순차적으로 가져오기
int idx = rs.getInt("idx");
String name = rs.getString("name");
String gender = rs.getString("gender");
Date birth = rs.getDate("bth");
// ROW의 각 COLUMN의 타입에 맞게 필드값 가져오기
System.out.println("## " + idx);
System.out.println("name : " + name);
System.out.println("gender : " + gender);
System.out.println("birthday : " + birth);
}
- 동적인 SQL 쿼리문에는 "?"라는 미지의 값을 설정해줘야 한다
- 이 값은 User가 원하는 값으로 설정해줘야 한다
- pstmt.set~~('파라미터인덱스', '값')으로 설정해줘야 한다
- '파라미터인덱스'는 동적인 SQL 쿼리문의 "?"의 인덱스를 나타낸다
- 만약 pstmt.setIint(2, 3)이면 동적인 SQL쿼리문의 두번째 "?"에 '3'이라는 값을 넣겠다는 것이다
Statement의 execute~()
- SELECT 요청의 경우 executeQuery(String sql)을 통해서 요청해야 한다
- return값은 ResultSet "Set" 개념으로 각 ROW별로 return된다
- INSERT/UPDATE/DELETE의 경우 executeUpdate(String sql)를 통해서 요청해야 한다
- return값은 해당 테이블에서 변경된 ROW의 수만큼 return된다
PreparedStatement의 execute~()
- PreparedStatement의 경우 미리 컴파일 한 후, "?"의 값만 변경해서 재사용하기 때문에 execute~()에 인자가 존재하지 않는다