티스토리 뷰

CHAPTER 16. JDBC로 데이터베이스와 JSP 연동

 

 

 

 

1. JDBC의 개요

JDBC는 자바에서 데이터베이스와 관련된 작업을 처리할 수 있도록 도와주는 자바 표준 인터페이스이다.

관계형 데이터베이스 시스템에 접근해 SQL 문을 실행하기 위한 자바 API 또는 자바 라이브러리이다.

JDBC API는 java.sql.* 패키지를 import해야 사용할 수 있다.

(JSP와 DB를 연동하기 위한 것)

 

 

JSP와 DB 연동

① java.sql.* 패키지 임포트

② JDBC 드라이버 로딩

③ 데이터 베이스 접속을 위한 Connection 객체 생성

④ 쿼리문을 실행하기 위한 객체 생성

⑤ 쿼리 실행

⑥ 쿼리 실행의 결과 값(int, ResultSet) 사용

⑦ 사용된 객체 역순 종료

 

Step 1. DB연결 ( ① ~ ③)

Step 2. Data 확보 ( ④ ~ ⑤)

Step 3. Data 활용 (⑥ ~ ⑦)

 

 

 

 

 

 

 

 

2. JDBC 드라이버 로딩 및 DBMS 접속

데이터 베이스에 접근하는 첫 단계는 JDBC 드라이버를 로딩하는 것이다. 

JDBC 드라이버를 로딩하고 나면 데이터베이스를 연결하는데 작업이 종료되면 데이터베이스 연결을 해제한다.

 

 

 

 

2-1. JDBC 드라이버 로딩하기

JDBC 드라이버 로딩 단계에서는 드라이버 인터페이스를 구현하는 작업으로 Class.forName() 메소드를 이용하여 JDBC 드라이버를 로딩한다.

드라이버가 로딩되면 자동으로 객체가 생성되고 DriverManager 클래스에 등록된다.

(로딩은 프로그램 수행 시 한번만 하면 된다.)

 

Class.forNmae(String className);

 

 

 

 

 

 

2-2. Connection 객체 생성하기

JDBC 드라이버에서 데이터베이스와 연결된 커넥션을 가져오기 위해 DriverManger 클래스의 getConnection() 메소드를 사용한다.

DriverManager 클래스를 사용하여 Connection 객체를 생성할 때 JDBC 드라이버를 검색하고 검색된 드라이버를 이용하여 Connection 객체를 생성한 후 반환한다.

즉, 

 

객체를 생성하는 방법은 세가지가 있다.

하지만 static Connection getConnection(String url, String user, String password) 를 가장 많이 사용한다.

왜냐하면 sql에 접근하려면 주소뿐만 아니라 id와 password가 필요하기 때문에 어차피 넣어주어야하기 때문이다.

static Connection getConnection(String url)
static Connection getConnection(String url, String user, String password)
static Connection getConnection(String url, properties info)

 

properties info 는 객체를 생성하여 매개변수로 사용하는 방법이다.

 

 

 

* static Connection getConnection(String url) 메소드 사용

<%
	Connection conn = null;
    try{
    	Class.forName("com.mysql.jdbc.Driver");
        conn=DriverManger.getConnection("jdbc:mysql://localhost:3306/jspbookdb?user=rood&password=1234");
    }
    catch(SQLException ex){
    	//예외 발생 처리
    }
%>

 

URL 주소 하나에 서버, DB 이름, ID, PASSWORD가 모두 들어간다.

하지만, 코드가 복잡하기 때문에 사용에 있어 불편함이 있다.

 

 

 

* static Connection getConnection(String url, String user, String password) 메소드 사용

<%
	Connection conn = null;
    try{
    	Class.forName("com.mysql.jdbc.Driver");
        conn=DriverManger.getConnection("jdbc:mysql://localhost:3306/jspbookdb","root", "1234");
    }
    catch(SQLException ex){
    	//예외 발생 처리
    }
%>

 

URL, USER, PASSWORD를 따로 작성해준다. 이러한 방법을 사용하면 이전 방법보다 사용이 편리하다.

그렇기 때문에 가장 많이 사용하는 방법이다.

 

 

 

 

* static Connection getConnection(String url, properties info) 메소드 사용

<%
	Connection conn = null;
    try{
    	Class.forName("com.mysql.jdbc.Driver");
        Properties props = new Properties();
        props.put("user","root");
        props.put("password", "1234");
        conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/jspbookdb",props);
    }
    catch(SQLException ex){
    	//예외 발생 처리
    }
%>

 

properties라는 객체를 생성하여 객체 안에 값을 넣어준다.

객체 생성 없이도 사용가능하기 때문에 굳이 properties를 사용하지 않아도되기때문에 다른 방법 사용을 더 많이 한다.

 

 

 

 

 

 

 

2-3. 데이터베이스 연결 닫기

데이터베이스 연결이 끝났으면 Connection 객체를 해제해야한다.

리소스를 사용하여 낭비되기 때문에 끝나면 바로 해제하는 것이 좋다.

void close() throws SQLException

 

사용예시

<%
	Connection conn = null;
    try{
    	//JDBC 드라이버 로딩
        //Connection 객체 생성
   }catch(SQLException e){
  	 	//예외 발생 처리
   } finally{
   		if(conn != null) conn.close();
   } 
%>

 

 

 

 

 

 

JDBC API로 데이터베이스 접속하기

예제 16-1

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Database SQL</title>
</head>
<body>
	<%
	
		Connection conn = null;
		try{
			String url="jdbc:mysql://localhost:3306/jspbookdb_test";
			String user="root";
			String password = "12";
			
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection(url, user, password);
			out.println("데이터베이스 연결이 성공했습니다."); 
		}
		catch(SQLException ex){
			out.println("데이터베이스 연결이 실패했습니다.<br>");
			out.println("SQLException : " +ex.getMessage());
		}
		finally{
			if (conn != null){
				conn.close();
			}
		}
	%>
</body>
</html>

 

문자열 변수에 각 각 url user password 값을 넣어줬다.

그리고 Clss.forName() 메소드를 사용하여 JDBC 드라이버를 로딩시켜줬다.

그 후 DriverManager클래스의 getConnection() 메소드를 사용하여 Connection 객체를 생성하고 주소를 반환해주었다.

그 후 데이터 연결이 완료되었다는 메시지를 출력해주고, 만약 오류가 발생하면 실패했다는 메시지와 오류가 왜 발생했는지를 반환해주도록 하고 모두 완료되었다면 리소스를 해제했다.

 

 

 

 

성공

 

db이름 다름

DB의 이름이 달라 연결을 실패했을 경우 출력이다.

밑의 SQLException 문구를 보면 알수없는 database라는 문구가 뜬 것을 볼 수 있다.

 

 

id 다름

 

password 다름

 

 

 

 

 

 

 

 

 

 

 

3. 데이터베이스 쿼리 실행

Connection 객체를 생성하여 데이터베이스가 연결되었다면 쿼리 실행 객체를 이용해 쿼리를 실행한다.

쿼리 실행 객체는 Statement, PreparedStatement, CallableStatement 가 있다.

 

 

3-1. Statement 객체로 데이터 접근하기

Statement 객체는 정적인 쿼리에 사용한다. (정적이라는 것은 변수 X)

Statement 객체는 하나의 쿼리를 사용하고 나면 더는 사용할 수 없다. (재사용이 불가능함.)

그렇기 때문에 간단한 쿼리문을 사용하는 경우에 좋다.

Statement 객체를 생성하면 executeQuery() 나 executeUpdate() 메소드를 호출해서 쿼리문을 실행해야한다.

 

 

 

Statement 객체의 메소드 종류

메소드 반환유형 설명
executeQuery(String sql) ResultSet select 문을 실행할 때 사용한다.(ResultSet 객체 반환)
executeUpdate(String sql) int 삽입, 수정, 삭제와 관련된 SQL 문 실행에 사용한다.
close() void Statement 객체를 반환할 때 사용한다.

 

 

 

 

- executeQuery() 메소드로 데이터 조회하기

executeQuery() 메소드는 정적인  select 쿼리문을 통해 데이터를 검색하는데 사용한다.

 

 

사용예시

<%
	Connection conn=null;
    ...(생략)...
    Statement stmt = conn.createStatement();
    String sql = "select * from member where id='1'";
    ResultSet rs = stmt.executeQuery(sql);
    stmt.close();
%>

 

먼저 Connection 객체를 생성한 뒤 Statement 객체를 생성한다.

그 후 select문을 작성한 후 ResultSet의 매개변수로 넣어준다.

ResultSet은 반환하므로 반환한 것을 조회하여 읽는 select와 함께 사용된다.

 

 

 

 

 

- executeUpdate() 메소드로 데이터 삽입, 수정, 삭제하기

executeUpdate() 메소드는 insert, update, delete쿼리문을 통해 데이터를 삽입, 수정, 삭제하는데 사용한다.

 

 

executeUpdate()메소드 사용하여 데이터 삽입한 경우 예시

<%
	Connection conn = null;
    ...(생략)...
    Statement stmt = conn.createStatement();
    String sql = "insert into member(id,name, passwd) values ('1', '홍길순', '1234')";
    int rs = stmt.executeUpdate(sql);
%>

 

위의 코드와 같이 sql 변수에 넣을 값을 목적에 맞게 작성해주면 사용이 가능하다.

 

 

 

 

 

 

Statement 객체로 insert 쿼리문 실행하기

예제 16-2

 

member.sql

use jspbookdb;
create table if not exists member(
	id varchar(20) not null,
    passwd varchar(20),
    name varchar(30),
    primary key (id)
);
select * from member;

workbench에서 테이블을 생성해준다.

이때 not exists 명령어는 생성이 되어 있지않으면 create를 실행하여 생성을 하고 생성이 되어 있다면 create를 실행하지 않는다.

not null은 값이 반드시 입력되어야한다는 뜻의 명령어이다. (HTML에서 required와 같음)

primary key는 id로 설정하여 동일한 값을 가질 수 없도록 했다.

 

 

 

insert01.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Database SQL</title>
</head>
<body>
	<form action="insert01_process.jsp" method="post">
		<p> 아이디 : <input type="text" name="id">
		<p> 비밀번호 : <input type="text" name="passwd">
		<p> 이름 : <input type="text" name="name">
		<p> <input type="submit" value="전송">
	</form>
</body>
</html>

로그인 폼을 만들어 submit되면 process로 이동하게 했다.

 

 

 

dbconn.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		Connection conn = null;
		
		String url = "jdbc:mysql://localhost:3306/jspbookdb";
		String user = "root";
		String password = "1234";
		
		Class.forName("com.mysql.jdbc.Driver");
		conn=DriverManager.getConnection(url,user,password);
	%>
</body>
</html>

DB와 연결하는 코드를 작성했다.

 

첫번째로 파라미터를 확보하여 문자열 변수에 담아준다.

그리고 Step 1인 DB연결을 해주었다.

DB 연결을 위해 Connection 객체를 생성했다.

그후 Class.forName()메소드를 사용하여 JDBC드라이버를 로딩했다.

DB연결을 위해 이전에 선언했던 변수에 Connection 객체 주소를 반환했다.

 

 

 

 

insert01_process.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Database SQL</title>
</head>
<body>
	<%@include file="dbconn.jsp" %>
	<%
		request.setCharacterEncoding("utf-8");
	
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		String name = request.getParameter("name");
		
		Statement stmt = null;
		
		try{
			String sql = "insert into member(id,passwd,name) values ('"+id+"','"+passwd+"','"+name+"')";
			stmt = conn.createStatement();
			stmt.executeUpdate(sql);
			out.println("member 테이블 삽입이 성공했습니다.");
		}
		catch(SQLException ex){
			out.println("member 테이블 삽입이 실패했습니다. <br>");
			out.println("SQLException : " +ex.getMessage());
		}
		finally{
			if(stmt!=null){
				stmt.close();
			}
			if(conn!=null){
				conn.close();
			}
			
		}
	%>
</body>
</html>

 

DB 연결이 끝난후 process에서는 Step2인 data 확보를 해주었다.

파라미터 값을 확보했고 Statements 객체를 생성해주었다.

그 후 문자열 변수 sql에 쿼리를 작성하고 담아주었다.

그 후 executeUpdate() 메소드를 사용하여 쿼리를 실행 했다.

 

원래의 단계라면 data 결과 값 반환을 해야하지만 select문이 아닌 insert문을 작성했으므로 반환 받아 출력할 필요가 없다 그렇기 때문에 작성하지 않아도 된다.

 

 

 

 

로그인

 

기존 테이블 데이터 값

기존의 테이블을 조회하면 값이 없는 것을 확인할 수 있다.

 

 

 

데이터 삽입한 후 테이블 데이터 조회

테이블 값을 삽입 후 조회를 하면 이전과 다르게 값이 들어가 있다.

 

 

 

여러개 데이터 삽입 후 테이블 데이터 조회

 

 

같은 아이디를 입력했을 경우

테이블을 생성할때 id를 primary key로 주었다.

그렇기 때문에 같은 id 값을 입력했을 경우 삽입이 실패했다는 메세지와 primary key라서 값이 중복되어 실패했다는 메세지를 볼 수 있다.

 

 

 

 

 

 

3-2. PreparedStatement 객체로 데이터 접근하기

PrepareStatement 객체는 동적인 쿼리에 사용한다. (동적인 쿼리는 변수를 사용한다.)

Statement와 다르게 하나의 객체로 여러번 쿼리를 실행할 수 있다.(재사용이 가능함)

매개변수 sql은 데이터베이스에 보낼 쿼리문이고 이전에서는 쿼리문에 하나하나의 값을 한번에 작성했지만 PrepareStatement 에서는 (?) 이와 같이 물음표로 표기하고 나중에 입력해준다.

물음표의 값을 할당하기 위해 setXxx() 메소드를 사용한다. 매개변수로 설정한 물음표의 위치 값은 1부터 시작한다.

 

 

 

setXxx() 메소드의 종류

메소드 반환 유형 설명
setString( int ParameterIndex, String x) void 필드 유형이 문자열인 경우
setInt( int ParameterIndex, Int x) void 필드 유형이 정수형인 경우
setLong( int ParameterIndex, long x) void 필드 유형이 정수형인 경우
setDouble( int ParameterIndex, double x) void 필드 유형이 실수형인 경우
setFloat( int ParameterIndex, float x) void 필드 유형이 실수형인 경우
setObject( int ParameterIndex, Object x) void 필드 유형이 객체인 경우
setDate( int ParameterIndex, Date x) void 필드 유형이 날짜형인 경우
setTimestamp( int ParameterIndex, Timestamp x) void 필드 유형이 시간형인 경우

 

 

 

 

PrepareStatement 객체의 메소드 유형

메소드 반환 유형 설명
executeQuery() ResultSet select 문을 실행할 때 사용한다.(ResultSet 객체 반환)
executeUpdate() int 삽입, 수정, 삭제와 관련된 SQL 문 실행에 사용한다.
close() void PrepareStatement 객체를 반환할 때 사용한다.

 

 

 

 

 

 

- executeQuery() 메소드로 데이터 조회하기

동적인 select 쿼리문을 통해 데이터를 검색하는데 사용한다.

 

<%
	Connection conn = null;
    ...(생략)...
    String sql = "select * from member where id=?";
    PreparedStatement pstmt = conn.PreparedStatement(sql);
    pstmt.setString(1,"1");
    ResultSet rs = pstmt.executeUpdate(sql);
    ...(생략)...
    pstmt.close();
%>

 

sql은 데이터베이스에 보낼 쿼리문을 작성하는 것이다. 

그리고 PreparedStatement는 미리 준비하는 것이므로 객체를 생성하며 sql을 파라미터로 갖는다.

setString은 인덱스의 위치가 1인 것에 1이라는 값을 넣는다는 뜻인데 

여기서 ?는 하나이기 때문에 id의 값이 1이된다.

그후 ResultSet 객체의 rs변수에 모든 객체의 값을 반환한다.

마지막으로 리소스를 해제해주어야 한다.

 

 

 

 

- executeUpdate() 메소드로 데이터 삽입, 수정, 삭제하기

insert, update, delete 쿼리문을 통해 데이터를 삽입, 수정, 삭제하는데 사용한다.

 

<%
	Connection conn = null;
    ...(생략)...
    String sql = "insert into member(id,name, passwd) values (?,?,?)";
    PreparedStatement pstmt = conn.PrepareStatement(sql);
    pstmt.setString(1,"1");
    pstmt.setString(2,"홍길순");
    pstmt.setString(3,"1234");
    pstmt.executeUpdate();
    ...(생략)...
    pstmt.close();
%>

 

insert문을 실행해 데이터베이스에 데이터를 삽입하는 예시이다.

sql 매개변수에는 쿼리문을 작성했다.

쿼리문의 values에는 (?,?,?)이라는 물음표가 들어가는데 값을 할당은 나중에 해준다.

PreparedStatement 객체를 생성하고 생성하며 파라미터 값으로 이전에 작성한 쿼리문을 가진다.

이후 입력하지 않은 값을 할당하는데 인덱스 순서를 앞에 작성하고 뒤에는 값을 작성해준다.

모두 입력했으면 executeUpdate() 메소드를 사용하여 쿼리문을 실행한다.

이후 close()메소드를 사용하여 리소스를 해제했다.

 

 

 

 

 

 

 

PreparedStatement 객체로 insert 쿼리문 실행하기

예제 16-3

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Database SQL</title>
</head>
<body>
	<%@include file="dbconn.jsp" %>
	<%
		request.setCharacterEncoding("utf-8");	
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		String name = request.getParameter("name");
		PreparedStatement pstmt=null;
		
		try{
			
			String sql = "insert into member(id,passwd,name) values (?,?,?)";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1,id);
			pstmt.setString(2,passwd);
			pstmt.setString(3,name);
			pstmt.executeUpdate(); //쿼리 실행 
			out.println("member 테이블 삽입이 성공했습니다.");
		}
		catch(SQLException ex){
			out.println("member 테이블 삽입이 실패했습니다. <br>");
			out.println("SQLException : " +ex.getMessage());
		}
		finally{
			if(pstmt!=null){
				pstmt.close();
			}
			if(conn!=null){
				conn.close();
			}
			
		}
	%>
</body>
</html>

 

이전 16-2에서 작성한 코드에서 process만 수정해주었다.

process에서 statement객체를 사용하여 작성했지만 3번 예제에서는 PreparedStatement 객체를 사용했다.

차이점을 보면 쿼리문을 작성할때 값을 적지 않고 물음표로 두고 객체 생성시 쿼리문을 미리 파라미터로 보내 준비한다.

그 후 값을 할당하고 executeUpdate()메소드를 사용하여 쿼리문을 실행한다.

(Statement에서는 실행시 파라미터로 sql을 주었다.)

 

 

 

로그인 창
데이터 삽입

 

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday