jdbc 프로그래밍 방법
0. java.sql import 하기
import java.sql.*;
첫번째 줄에 java.sql.*을 import 한다.
1. JDBC 드라이버를 선택하고 메모리에 적재하여 DriverManager에 자동으로 등록시킴
Class 클래스의 forName() 메소드 사용
try { Class.forName("com.mysql.jdbc.Driver");}
catch ( java.lang.ClassNotFoundException e ) {
System.err.println("Driver load 에러: " + e.getMessage() );
e.printStackTrace();
}
jdbc8.0.28에서는 로드하지 않아도 됨.
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
2. 특정 데이터베이스와 연결
DriverManager 클래스, Connection 인터페이스 사용
Connection con = null;
try { // MySQL 데이터베이스와 연결
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/university", "root", "onlyroot");
}
catch( SQLException e ) { System.err.println("conn 에러:" + e.getMessage() ); }
3. Statement 객체 생성
Connection인터페이스를 이용하여 Statement 객체 생성
Statement, PreparedStatement, CallableStatement 인터페이스 중의 한 객체를 생성하여 나중에 쿼리 실행하게 함
3-1. Statement 객체 생성
Statement stmt = null;
stmt = con.createStatement(); // statement 객체 생성
stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
//Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY오류를 처리한 구문
3-2. PreparedStatement 객체 생성
PreparedStatement prStmt;
prStmt = con.prepareStatement("select * from enrol where cno=? and final = ?;");
prStmt = con.prepareStatement("select * from enrol where cno=? and final = ?;", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
//Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY오류를 처리한 구문
3-3. CallableStatement 객체 생성
CallableStatement st = null;
st = con.prepareCall("call SelectStOfSno(?, ?, ?, ?)" );
4. sql 질의 실행과 결과 반환
Connection 객체에서 만든 다음 인터페이스 중의 한 객체 이용하여 쿼리 실행 및 결과 전달 받음
4-1. Statement: 완성된 SQL 문의 실행
Statement 객체 생성 및 쿼리 실행
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select * from student;");
int cnt = stmt.executeUpdate("update student set year = year + 1;");
boolean b = stmt.execute("delete from student where sno=300;");
중요 메소드
ResultSet executeQuery(String sql)
int executeUpdate(String sql)
boolean execute(String sql)
4-2. PreparedStatement: 파라미터가 포함된 SQL문의 실행
PreparedStatement 객체 생성 및 질의 실행
PreparedStatement prStmt1= con.prepareStatement("select * from enrol where cno= ? and grade = ? ;" );
PreparedStatement prStmt2 = con.prepareStatement("update student set year = year + 1 where sno = ? ;" );
prStmt1.setString(1, "c123"); // 첫번째 파라미터: cno = 'c123'
prStmt1.setString(2, "A"); // 두번째 파라미터: grade = 'A'
prStmt2.setInt(1, 100); // 첫번째 파라미터: sno = 100
ResultSet rs = prStmt1.executeQuery();
int cnt = pStmt2.executeUpdate();
IN 파라미터가 포함된 SQL문으로 객체 생성
IN 파라미터는 ?로 표시
IN 파라미터에 특정한 값을 세팅하기 위해서 setString(), setInt(), setDouble()... 메소드 이용
쿼리 실행은 Statement 와 같음. 하지만 메소드에 파라미터를 전달하지 않음.
중요 메소드
void setXXX(int parameterIndex, XXX x)
ResultSet executeQuery()
int executeUpdate()
boolean execute()
4-3. CallableStatement: 저장 프로시쥬의 실행
CallableStatement 객체 생성 및 질의 실행
CallableStatement cStmt= con.prepareCall( "call SelectStOfSno(?, ?, ?, ?) " );
cStmt.setInt(1, 100); // 첫번째 IN파라미터 값 = 100
cStmt.registerOutParameter(2, Types.VARCHAR); // 2번째 OUT 파라미터
cStmt.registerOutParameter(3, Types.INTEGER); // 3번째 OUT 파라미터
cStmt.registerOutParameter(4, Types.VARCHAR); // 4번째 OUT 파라미터
boolean b = cStmt.execute();
IN, OUT 파라미터가 포함된 저장 프로시쥬어를 위한 객체 생성
IN, OUT 파라미터는 ?로 표시
IN 파라미터에 특정한 값을 세팅하기 위해 setXXX()에소드 이용
OUT 파라미터임을 표시하기 파라미터의 타입을 명시
중요 메소드
void setXXX(int parameterIndex, XXX x)
void registerOutParameter(int parameterIndex, int sqlType)
ResultSet executeQuery()
int executeUpdate()
boolean execute()
5. 메소드
ResultSet executeQuery(String sql)
ResultSet executeQuery()
Executes the given SQL statement, which returns a single ResultSet object.
int executeUpdate(String sql)
int executeUpdate()
Executes the given SQL statement, which may be an INSERT, UPDATE,
or DELETE statement or an SQL statement that returns nothing, such as
an SQL DDL statement.
boolean execute(String sql)
boolean execute()
Executes the given SQL statement, which may return multiple results.
void setXXX(int parameterIndex, XXX x)
Sets the designated parameter to the given x
void registerOutParameter(int parameterIndex, int sqlType)
Registers the OUT parameter in ordinal position parameterIndex
to the JDBC type sqlType(java.sql.Types에 정의됨).
5-1. executeQuery
하나의 ResultSet 객체를 반환하는 결과의 SQL 문장을 실행
5-2. executeUpdate
insert, update, delete sql문은 반영된 row수를 리턴
create table, drop table등의 DDL sql은 아무것도 반환하지 않는다(0 반환)
5-3. execute
-프로그래머가 컴파일 시에 알 수 없는 내용의 SQL 문장을 수행
-여러 형태의 결과를 반환할 경우
@한 개 이상의 ResultSet 객체를 반환하는 경우
@하나 이상의 갱신횟수를 반환할 경우
@ResultSet 객체와 갱신횟수의 조합을 반환할 경우
-저장 프로시져(Stored Procedure)를 실행
true를 반환: 한개 이상의 ResultSet객체를 반환한 경우
ResultSet rs = stmt.getResultSet(); 를 이용하여 ResultSet객체를 받아 처리
stmt.getMoreResults()==true이면 rs = stmt.getResultSet(); 반복
false를 반환: 갱신횟수를 반환할 경우
int cnt = stmt.getUpdateCount(); 를 이용하여 갱신회수 접근
2개 이상의 갱신회수를 반환하는 경우 stmt.getUpdateCount()==-1이 될때까지 갱신회수 접근
if (stmt.execute(sql) == false) {
int cnt;
do {
cnt = stmt.getUpdateCount();
… cnt를 처리 …
stmt.getMoreResults();
}
while (cnt != -1) ;
}
6. SQL 실행 결과 접근
6-1. ResultSet 객체의 처리
-SQL이 실행되어 ResultSet 객체가 반환되면 결과 투플 중 한 투플을 가리키는 포인터인 커서(cursor)가 내부적으로 생성됨
-처음에 커서는 첫 투플 이전을 포인트함(위치0)
-ResultSet 인터페이승의 next()메소드를 실행하면 커서가 다음 투플을 포인트하게 되며, 이 때 다음 투플이 있으면 true를, 없으면 false를 반환함
-커서의 현재 포인팅 투플에서 애트리뷰트는 getXXX() 메소드로 접근함
-커서 이동 메소드: first(), last(), beforeFirst(), afterLast(), absolute(int pos)
-다양한 메소드 문서: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
ResultSet 대표적인 메소드 | 설명 |
next() | 커서를 다음으로 이동 |
first() | 커서를 맨 처음으로 이동 |
last() | 커서를 맨 마지막으로 이동 |
getRow() | 현재 커서의 열 번호를 리턴 |
getString(int columnIndex) or getString(String columnLabel) | 현재 커서의 columnIndex 또는 columnLabel에 해당하는 문자열 반환 |
getInt(int columnIndex) or getInt(String columnLabel) | 현재 커서의 columnIndex 또는 columnLabel에 해당하는 정수 반환 |
wasNull() | Reports whether the last column read had a value of SQL NULL |
6-2. getXXX() 메소드
-검색된 여러 투플에서 특정 애트리뷰트 접근을 위한 메소드
-getArray(), getBoolean(), getFloat(), getDouble(), getInt(), getString(), getDate(), getTime() , getObject() 등 타입별 메소드가 있음
-애트리뷰트(컬럼, 열) 이름 또는 애트리뷰트 인덱스를 사용하여 접근할 애트리뷰트 지정(애트리뷰트 인덱스는 1부터 시작)
String s = rs.getString("sname");
String s = rs.getString(2);
-가져올 애트리뷰트의 타입을 모를 때에는 getObject() 메소드 이용
Object obj = rs.getObject(1);
반환된 값이 원시 타입의 값일 경우 Character, Integer, Float, Double 등 Wrapper 클래스의 객체로 반환됨
6-3. ResultSetMetaData 클래스
-ResultSet 객체의 애트리뷰트 타입, 이름, 타이틀, 개수 등에 에 대한 정보를 얻는데 사용되는 인터페이스
-ResultSetMetaData에 있는 메소드 사용하여 열에 대한 정보 얻음
int getColumnCount() : 애트리뷰트 개수를 반환
String getColumnLabel(int column) : 주어진 컬럼번호의 타이틀 반환
String getColumnName(int column) : 주어진 컬럼번호의 이름 반환
int getColumnType(int column) : 주어진 컬럼번호의 타입번호를 반환
-사용 예
stmt = con.createStatement(); // Statement 생성
rs = stmt.executeQuery("select * from student;");
ResultSetMetaData rsm = rs.getMetaData();
int cnt = rsm.getColumnCount(); // cnt에는 4 저장
String cname = rsm.getColumnName(1); // cname에는 "sno" 저장
6-4. null 애트리뷰트 다루기
ResultSet의 wasNull() 메소드
-읽어들인 마지막 애트이뷰트(열)이 null인지 아닌지를 판별하여 true 또는 false를 반환
-사용 예
int age = rs.getInt("age");
if (! rs.wasNull())
System.out.println(" * 나이: " + age);
-애트리뷰트가 null일 때 getXXX()를 사용하면 자동적으로 null이 반환됨