JDBC에 대한 대화내용
try
{
con.open();
con.executeQuery(sql);
con.commit();
}
catch(e)
{
con.rollback();
}
finally
{
con.close();
}
뒤에 메소드는 약간 다르지만 저 형식은 jsp나 java에서 바이블 이다.
executeQuery() 는 ResultSet을 반환받는것이고 커밋이 필요하지 않다.
executeUpdate() 는 업데이트를 수행하는거라 반드시 커밋을 해야 저장이 된다.
업데이트 = (insert|update|delete)
업데이트라는건 서버의 데이터를 변형시키는것이며 sql 쿼리의 UPDATE문을 의미하는게 아니다.
쿼리는 총 4종류이다.
CRUD 라고 부르는데 Create | Read | Update | Delete
각각에 맞게 사용하는 코드형태는 거의 비슷하다
mysql에선 $result = mysql_query(sql);
echo "전체게시물: ".mysql_num_rows($result);
while($row = mysql_fetch_array($result)) { /*처리*/ }
이 가능하다.. 한번 쿼리 날리고서 그 반환레코드의 전체 행 카운트를 알아낼 수가 있고
또 그 반환레코드를 바로 루프 돌수가 있다
하지만 jdbc는 그런것이 없다.
String sql__ = "select count(*) from table";
String sql = "select * from table";
Statement stmt;
Resultset rs;
try
{
stmt = con.createStatement();
rs = stmt.executeQuery(sql__);
rs.next();
int count = rs.getInt(rowcount);
out.println("전체게시물 : " + count + "건");
rs = stmt.executeQuery(sql);
while(rs.next())
{
out.println(rs.getInt("idx"))
}
}
con 변수의 객체생성은 생략..
중요한건 오라클 jdbc에서는 스칼릿 형태의 반환값을 처리할때엔 (단일 row)
(다중 row 반환값 처리할때에도 마찬가지) 모든 반환값에 대해 접근을 하려면
무조건 rs.next()를 해줘야 한다는것이다.
쉽게 말하자면 반환레코드의 시작 인덱스카운트는 0부터 시작한다고 가정한다면
최초 rs에 대한 포인터는 -1부터 시작이므로
next()를 해줘서 첫번째 레코드를 가리키도록 이동을 해야함.
카운트를 구하고 다중열 레코드를 리턴받는걸 한번에 구현하려면
쿼리를 두번 날려야 한다는점.. 한번 날려서 하려면
Statement 클래스를 사용하지 않고 PreparedStatement 클래스를 사용한다.
String localCode = request.getParameter("lcode");
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "" +
" SELECT centcode, centname " +
" FROM SBBGCT " +
" WHERE locacode = ? " +
" ORDER BY centname ASC ";
try
{
con = DbConn.getConnection();
pstmt = con.prepareStatement(sql,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
pstmt.setString(1, locaCode);
rs = pstmt.executeQuery();
rs.last();
int i = 1;
int count = rs.getRow();
rs.beforeFirst();
out.println("전체 레코드 : " + count + "개");
while(rs.next())
{
// 처리
}
}
...
PreparedStatement 클래스를 사용한 예제
일반적으로 rs.next()를 하게되면 뒤로 갈수가 없다. 이는 odbc에도 있다.
TYPE_SCROLL_INSENSITIVE 은 enum이라고 해서 상수일뿐이다.
1005 라는 숫자를 리턴한다.
ResultSet.TYPE_SCROLL_INSENSITIVE <--- 1005
해당 rs에 대해 커서를 앞으로갔따가 뒤로 갔따가 할 수 있다는 뜻
위에 코드를 보면 rs.last() 처럼 맨 뒤로 갔다가 카운트 세고
다시 beforeFirst()해서 처음으로 갔으니 커서의 방향성에 대해 자유로워야 한다는게 전제조건이 된다.
그래서 TYPE_SCROLL_INSENSITIVE를 넘겨줌
기본값은 TYPE_SCROLL_SENSITIVE
pstmt = con.prepareStatement(sql);
이렇게 하면 오버로딩 처리되서 뒤에꺼 디펄트값이 적용됨.
pstmt = con.prepareStatement(sql);
pstmt = con.prepareStatement(sql, TYPE_SCROLL_SENSITIVE);
이 두개는 같고 ResultSet.CONCUR_READ_ONLY는 커서에 대해서
업데이트를 할것인가에 대한 설정 디비에서 데이터를 받아와서
그 결과물을 jdbc 단에서 변경을 할 필요가 있다면 ResultSet.CONCUR_UPDATABLE
이 상수를 넘겨주면 됨.
이건 아마 1008인가 그럴것이다. 하지만 그럴일은 거의 없으니....
거의 대부분 ResultSet.CURSOR_READ_ONLY 이걸 쓴다.
하지만 쓰기 귀찮아서 안쓰는거 뿐... 안써도 기본값으로 저게 적용되므로
rs.last();
int count = rs.getRow();
rs.beforeFirst();
맨 뒤로 가서 getRow로 행의 갯수를 세고 다시 맨 앞으로 가서 while(rs.next()) {}
단점이 반환된 레코드의 데이터가 많을경우 절대 쓰면 안됨. 적은 데이터를 처리할때 사용
데이터가 많을땐 무조건 카운트쿼리 따로 날려야 함.
idx name memo
5 kim 테스트
3 lee 그냥
1 seo 하이
이경우 이 레코드의 다음 시퀀스값을 알아내려면... 그니깐 6을 알아내려면 MAXVALUE 이 칼럼을 활용하면 됨.
단, 해당 테이블에 시퀀스가 적용이 되어있어야 함. 이런것처럼 기본칼럼들이 많다.
시퀀스라는건 해당 테이블에 매번 갱신/기록되는게 아니라 엑세스 시점에서 최단 인덱스를 타고 측정되는 수치