🍁JDBC 라이브러리 클래스
1. Connection
DB에 연결 또는 종료한다.
2. Statement
모든 SQL을 실행하는 역할을 한다.
3. ResultSet
데이터베이스로부터 쿼리의 결과를 저장하고 조회한다.
ResultSet 클래스는 Interator, 향상된 for문, 스트림, 커서와 비슷하다.
Statement의 종류
1. Statement
- 기본형이다.
- 매개 변수 처리가 번거롭다.
- 안정성과 가독성이 낮다.
2. PreparedStatement
- 개량형이다.
- 매개 변수 처리에 특화되어 있다.
- 안정성과 가독성이 높다.
기존 Statement에 매개변수 처리 과정을 손쉽고 안전하게 할 수 있게 만든 게 PreparedStatement이다.
3. CallableStatement
- 개량형이다.
- 프로시저 전용이다.
🍁Statement
반환값이 없는 insert 쿼리
반환값이 없는 쿼리는 select를 제외한 나머지 SQL을 의미한다.
tlbAddress 테이블 생성
SELECT * FROM tblAddress;
DROP TABLE tblAddress;
CREATE TABLE tblAddress (
seq NUMBER PRIMARY KEY,
name VARCHAR2(30) NOT NULL,
age NUMBER NOT NULL,
gender CHAR(1) NOT NULL,
address VARCHAR2(300) NOT NULL,
regdate DATE DEFAULT sysdate NOT null
);
CREATE SEQUENCE seqAddress;
INSERT INTO tblAddress (seq, name, age, gender, address, regdate)
VALUES (seqAddress.nextVal, 'Isaac', 20, 'm', '서울시 강남구 역삼동', default);
SELECT * FROM tblAddress;
COMMIT;
inser 쿼리를 실행할 DB를 만들었다.
executeUpdate 메서드
int stat.executeUpdate(String sql);
int result = stat.executeUpdate(sql);
if (result == 1) {
System.out.println("삽입 성공");
} else {
System.out.println("삽입 실패");
}
executeUpdate 메서드의 실행은 SQL Developer에서 Ctrl + Enter를 누르는 것과 동일하다.
그리고 숫자를 돌려주는데, 이는 적용된 행의 개수이다. 이 숫자에 따라 작업이 성공했는지, 실패했는지를 알 수 있기 때문에 일종의 피드백 값이 된다.
문자열로 쿼리를 작성
자바는 SQL을 모르기 때문에 SQL을 문자열로 취급한다.
Servlet이 HTML, CSS, JavaScript를 모르기 때문에 문자열로 "<html>"을 만드는 것과 같은 상황이다.
서로 전혀 다른 상황에서 만들어진 언어이기 때문에 언어가 호환될 수는 없다.
String sql = "";
그래서 자바는 insert가 뭔지 모르기 때문에 쿼리를 작성하기 위한 문자열을 따로 만든다.
작업을 쉽게 하려면 편집기에서 쿼리를 작성한 다음에 복사하여 가져오는 방법을 사용하면 된다.
Connection으로 Statement 생성
// stat = new Statement(); //X
stat = conn.createStatement();
Statement는 SQL을 실행하기 위한 역할인데, stat = new Statement(); 이렇게 작성하면 어디에 접속할지 모르기 때문에 오브젝트를 만들 때에는 평범한 스타일로 만들지 않고, Connection을 통해 만들도록 되어 있다.
자원 해제(정리)
stat.close();
conn.close();
자미가에 자원을 해제해 주어야 한다.
ORA-00911: invalid character
String sql = "INSERT INTO tblAddress (seq, name, age, gender, address, regdate) VALUES (seqAddress.nextVal, 'Sopia', 21, 'f', '서울시 강남구 대치동', default);"; //에러 발생
JDBC에서 쿼리의 끝에 문장 종결자 ';'를 포함하여 작성하면 발생하는 에러이다.
전체 코드
Connection conn = null;
Statement stat = null;
try {
conn = DBUtill.open(); //DB 접속
if (!conn.isClosed()) {
System.out.println("DB 접속 성공");
//query
String sql = "INSERT INTO tblAddress (seq, name, age, gender, address, regdate) VALUES (seqAddress.nextVal, 'Sopia', 21, 'f', '서울시 강남구 대치동', default)";
//stat
stat = conn.createStatement();
//반환값이 없는 쿼리
int result = stat.executeUpdate(sql);
if (result == 1) {
System.out.println("삽입 성공");
} else {
System.out.println("삽입 실패");
}
//자원 해제(정리)
stat.close();
conn.close();
} else {
System.out.println("DB 접속 실패");
}
} catch (Exception e) {
e.printStackTrace();
}
insert 쿼리가 실행되어 데이터가 잘 들어간 것을 확인할 수 있다.
반환값이 없는 update 쿼리
Connection conn = null;
Statement stat = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "UPDATE tblAddress SET age = age + 1";
int result = stat.executeUpdate(sql);
if (result > 0) {
System.out.println("수정 성공");
} else {
System.out.println("수정 실패");
}
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
반환값이 없는 delete 쿼리
Connection conn = null;
Statement stat = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "DELETE FROM tblAddress WHERE seq = 1";
int result = stat.executeUpdate(sql);
if (result > 0) {
System.out.println("삭제 성공");
} else {
System.out.println("삭제 실패");
}
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
반환값이 없는 create 쿼리
Connection conn = null;
Statement stat = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "CREATE TABLE tblAddress (\r\n"
+ " seq NUMBER PRIMARY KEY,\r\n"
+ " name VARCHAR2(30) NOT NULL,\r\n"
+ " age NUMBER NOT NULL,\r\n"
+ " gender CHAR(1) NOT NULL,\r\n"
+ " address VARCHAR2(300) NOT NULL,\r\n"
+ " regdate DATE DEFAULT sysdate NOT null\r\n"
+ ")";
int result = stat.executeUpdate(sql);
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
동적으로 table을 생성하였다.
사용자 입력을 받는 insert 쿼리
사용자에게 추가할 사람의 정보를 입력받아 tblAddress에 새로운 사람을 등록하는 insert 작업을 해보도록 하자.
Scanner scan = new Scanner(System.in);
String name = "";
String age = "";
String gender = "";
String address = "";
Connection conn = null;
Statement stat = null;
try {
System.out.print("이름: ");
name = scan.nextLine();
System.out.print("나이: ");
age = scan.nextLine();
System.out.print("성별(m, f): ");
gender = scan.nextLine();
System.out.print("주소: ");
address = scan.nextLine();
conn = DBUtil.open();
if (!conn.isClosed()) {
System.out.println("DB 접속 성공");
String sql = String.format("INSERT INTO tblAddress (seq, name, age, gender, address, regdate) VALUES (seqAddress.nextVal, '%s', %s, '%s', '%s', default)", name, age, gender, address);
stat = conn.createStatement();
int result = stat.executeUpdate(sql);
if (result == 1) {
System.out.println("삽입 성공");
} else {
System.out.println("삽입 실패");
}
stat.close();
conn.close();
} else {
System.out.println("DB 접속 실패");
}
} catch (Exception e) {
e.printStackTrace();
}
🍂반환값이 있는 insert 쿼리
ResultSet stat.execute(String sql);
반환값이 있는 쿼리는 select 쿼리를 의미한다.
select
- 단일값 반환: 1행 1열
- 다중값 반환: 1행 N열
- 다중값 반환: N행 1열
- 다중값 반환: N행 N열
단일값 반환: 1행 1열
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "SELECT count(*) as cnt FROM tblAddress";
rs = stat.executeQuery(sql);
//System.out.println(rs); //oracle.jdbc.driver.OracleResultSetImpl@41c2284a
rs.next(); //커서 1줄 전진
int count = rs.getInt(1); //index
System.out.println(count);
count = rs.getInt("cnt"); //컬럼명
System.out.println(count);
rs.close();
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
rs.next()로 커서를 1줄 전진하여 현재 커서가 가리키고 있는 레코드의 원하는 컬럼을 접근하여 데이터를 가져올 수 있다. 이때 커서를 1줄 전진하게 되면 컬럼명을 가리키게 된다.
close를 하는 순서는 항상 생성할 때의 역순이다.
출력되는 숫자는 sql 쿼리로 받아낸 count(*) 값이다.
getInt()
rs.getInt(); 안에 숫자를 넣으면 컬럼 위치(index)이고, 문자열을 넣으면 컬럼명이 된다.
가공된 값에는 Alias를 붙여 호출할 수 있다.
숫자를 사용하는 것보다 컬럼명으로 호출하는 게 가독성도 좋고 사용하기에 편리하다.
다중값 반환: 1행 N열
사용자가 입력한 숫자(seq)의 데이터를 반환하는 쿼리를 만들어보도록 하자.
Scanner scan = new Scanner(System.in);
System.out.print("번호: ");
String seq = scan.nextLine();
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "SELECT * FROM tblAddress WHERE seq = " + seq;
rs = stat.executeQuery(sql);
if (rs.next()) {
System.out.println("번호: " + rs.getString("seq"));
System.out.println("이름: " + rs.getString("name"));
System.out.println("나이: " + rs.getString("age"));
System.out.println("성별: " + rs.getString("gender"));
System.out.println("주소: " + rs.getString("address"));
System.out.println("날짜: " + rs.getString("regdate"));
} else {
System.out.printf("입력한 %s번의 데이터가 없습니다.\n", seq);
}
rs.close();
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
다중값 반환: N행 1열
rs.next()를 이용해 table에 들어 있는 모든 사람의 이름을 출력해 보도록 하자.
rs.next()
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "SELECT name FROM tblAddress";
rs = stat.executeQuery(sql);
rs.next();
System.out.println(rs.getString("name"));
rs.next();
System.out.println(rs.getString("name"));
rs.close();
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
rs.next()를 실행하고 출력하면서 모든 사람의 이름을 출력할 수 있다.
while (rs.next())
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "SELECT name FROM tblAddress";
rs = stat.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("name"));
}
rs.close();
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
while문 안에 rs.next()를 넣으면 더 이상 출력할 데이터가 없을 경우 자동으로 빠져나와 모든 사람의 이름이 출력된다.
다중값 반환: N행 N열
table에 들어있는 모든 사람의 번호, 이름, 나이, 주소를 출력해 보도록 하자.
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
conn = DBUtil.open();
stat = conn.createStatement();
String sql = "select * from tblAddress";
rs = stat.executeQuery(sql);
System.out.println("[번호]\t[이름]\t[나이]\t[주소]");
while(rs.next()) {
System.out.printf("%s\t%s\t%s\t%s\n", rs.getString("seq"), rs.getString("name"), rs.getString("age"), rs.getString("address"));
}
rs.close();
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
데이터베이스에 있는 값을 잘 가져온 것을 확인할 수 있다.