JSP에서 데이터베이스와 연동하는 방법에 대해 알아보기 전에, 선행학습이 필요하다
해당 링크를 통해 SQL문에 대한 선행학습부터! ▶ SQL기본 문법


◆ JDBC ( Java DataBase Connectivity )

자바에서 DB를 연동하여 SQL문을 실행할 수 있도록 해주는 자바API
JDBC를 사용하기 위해선 import java.sql.*; 이 필요하고,
try~catch문 안에서 이루어져야 한다. ( JSP는 try~catch가 필수는 아님 )


▶ 1. DB서버 연결

1-1. ojdbc8.jar 라이브러리 추가

Oracle을 사용하기 위해선 해당 DB사이트에서 라이브러리 다운이 필요하다.
 ojdbc.jar파일 다운로드 후 프로젝트의 WEB-INF/lib 디렉터리에 추가해준다.

또는 SqlDeveloper나 Oracle자체에도 해당 라이브러리가 내장되어 있기 때문에 해당 파일을 복사해서 사용해도 무방하다.

  • SqlDeveloper
    sqldeveloper-17.2.0.188.1159-no-jre\sqldeveloper\jdbc\lib
  • Oracle
    C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

▶ Java프로젝트에서 라이브러리 추가

웹 프로젝트의 경우 lib디렉터리에 jar파일만 추가해 주어도 되지만, 자바 프로젝트의 경우에는 다른 방법으로 라이브러리를 추가해야한다.

프로젝트 우 클릭 -> BuildPath -> Configure BuildPath -> Libraries탭 -> Add External JARs로 해당 jar파일 추가


1-2. DriverManager가 사용해야 될 클래스를 탑재시키는 코드가 필요

java코드 또는 스크립트 렛( <% %> )안에 class.forName("oracle.jdbc.driver.OracleDriver");작성

  • 해당 메서드의 인자 값은 데이터베이스 종류에 따라 달라진다.(정해져 있는 값임)
  • 1-1의 ojdbc8.jar 라이브러리 추가가 되어있는 상태여야만 가능하다.


1-3. DriverManager객체로 Connection 객체 연결( 필수정보 3가지가 필요하다. )

DB와 연결된 Connection객체를 반환받아야 한다.
 Connection conn = DriverManager.getConnection(url, "계정", "비밀번호");

  • 인자1 : 해당 DB의 종류와 DB서버의 주소 ( 위치정보 )
  • 인자2 : 사용할 DB접속 계정명
  • 인자3 : 해당 DB에 설정한 비밀번호
  • url 입력 : String url = "jdbc:oracle:thin:@192.168.10.80:1521:xe";
    => 데이터베이스 종류에 따라 설정이 다를 수 있다.
<%
import java.sql.*;

class.forName(oracle.jdbc.driver.OracleDriver);
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String user = "gunbin";
String pass = "1234";
Connection conn = DriverManager.getConnection(url, user, pass); 
%>


▶ 2. 패킷 전송/수신


2-1. sql 문 작성

String형태로 sql문을 작성 한다.
( DDL 작업은 DB에서 하고, DML작업등의 경우만 JAVA에서 처리한다. )
ex) String sql = “insert into baby values(‘이순신’,’1’,’3.49’,’2018-01-04’,null)”;


2-2. 패킷화

Connection객체의 메서드를 이용하여 sql문을 패킷화 해주는 PreparedStatements객체를 반환 받는다.
ex ) PreparedStatement ps = conn.prepareStatement(sql); // 패킷화

  • 또는 Statement state = conn.createStatement();를 이용하여 execute(sql)을 통하여 SQL문을 실행하는 방법 또한 가능하지만, 이는 동적 value값 할당이 불가능 하기 때문에 예전방법이다.


2-3. 패킷전송 및 실행 유도

PreparedStatements객체의 메서드로 패킷 전송을 시도한다.
ex ) int r = ps.executeUpdate(); // 실행된 행 반환
처리하고자 하는 명령문의 종류에 따라 메서드가 달라진다.

  • executeUpdate()
    데이터 변경이 일어나는 insert, update, delete문의 경우에 쓰는 메서드
    ( 처리된 행의 개수를 int형으로 반환한다. )
  • executeQuery()
    데이터를 가져오는 select문의 경우에 쓰는 메서드
    ( ResultSet객체 반환 )
...
Connection conn = DriverManager.getConnection(url, user, pass); 

String sql = "insert into baby values('이순신','1','3.49','2018-01-04',null)";
PreparedStatement ps = conn.prepareStatement(sql); // 패킷화
int r = ps.executeUpdate();
System.out.println(r + "개의 행이 적용되었습니다.");

// 또는 옛날 방법
Statement state = conn.createStatement();
state.excecute(sql);


▶ 3. 서버 연결 해제

DB작업이 끝난후에 연결을 해제시켜 주어야 한다. conn.close();

  • DB작업 예시
import java.sql.*;
class.forName(oracle.jdbc.driver.OracleDriver);
Connection conn =
DriverManager.getConnection(jdbc:oracle:thin:@localhost:xe,root,1234); 
String sql = insert into baby values(‘원빈’,1,3.22,2017/01/05,null);
PreparedStatement ps = conn.prepareStatement(sql);
int r = ps.executeUpdate();
if(r>0) System.out.println(“성공”);
else System.out.println(“실패”);
conn.cleose();


◆ DB value값 입력

SQL문에 value값을 변수로 넣게 될 경우 String처리가 매우 번거롭기 때문에, PreparedStatement객체는 이를 동적으로 셋팅 할 수 있도록 지원해준다.


▶ SQL value값 동적처리 방법


1. 처리하고자 하는 SQL문의 value값을 ?(물음표)로 처리한다.

String sql = "insert into baby values(?,?,?,?,?)";


2. prepareStatement()메서드의 인자로 보낸다.

PreparedStatement ps = conn.prepareStatement(sql);

실행전 명령문을 패킷화 하는것이기 때문에 이전과 다르지 않다.


3. 물음표(?)로 처리해 두었던 value값을 할당

PrepareStatement객체의 setString() 메서드를 이용해 ? 안에 value값을 할당 할 수 있다.

ps.setString(1, name);
  • setString(번호, value값);

    의 첫번째 인자는 물음표(?)의 순서를 의미하며.
    첫번째는 0이 아닌 1부터 시작한다.

  • ps.setObject, ps.setInt등등 값의 타입에 따라 메서드가 달라질 수 있다.
    ( 단, String은 모든 처리가 가능 )

  • 물음표(?)로 동적 할당 처리를 할 수 있는 값들을 오직 value값들뿐이다.

  • int r = ps.executeUpdate(); 하기 전에 모두 등록해야 사용이 가능하다.
...
String sql = "insert into baby values(?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,"원빈");
ps.setInt(2, 1);
ps.setDouble(3, 3.22);
ps.setString(4, "2017/01/05");
ps.setString(5, null);
int r = ps.executeUpdate();
conn.cleose();


◆ select문 처리

데이터의 변경이 일어나는 insert, update, delete 문은 executeUpdate()메서드를 이용하여 처리된 행을 int형으로 반환하지만,
데이터를 불러오는 등의 작업인 select문은 executeQuery()메서드를 이용하여 ResultSet객체를 반환한다.

ResultSet rs = ps.executeQuery();


▶ ResultSet객체 순회

ResultSet객체는 Iterator객체와 비슷하게 사용한다.

  • rs.next()
    다음 행이 있는지 boolean반환( 최초 넥스트는 데이터가 있는지 없는지 확인 )
    => 다음 행으로 넘어가기 위해 데이터를 뽑아내기 전 꼭 필요한 작업
    => while문을 통해 계속해서 다음 데이터를 뽑아내기 위한 메서드
  • rs.previous()
    이전 레코드로이동
  • rs.first()
    처음으로 이동
  • rs.last()
    마지막으로 이동
  • rs.getString(인덱스 또는 컬럼네임)
    해당 행의 데이터를 뽑아내며, 데이터 타입에 따라 getInt()등 메서드가 달라질 수 있다.


▶ value값 가져오기

ResultSet객체의 getString()메서드의 인자는 인덱스 또는 컬럼네임이 될 수 있으며,
뽑아내는 데이터타입에 따라 getInt(), getDouble, getDate().. 등등으로 바뀔 수 있다.

  • 객체형이 아닌 데이터를 뽑아 낼 때 데이터베이스의 데이터가 null일 경우 int는 0 등으로 뽑아진다.
...
ResultSet rs = ps.executeQuery();
while(rs.next){
    System.out.println(rs.getString(1));
    System.out.println(rs.getString(name));
    System.out.println(rs.getString("gender"));
}