위 글은 해당 카테고리의 수업 강의 자료를 정리한 것입니다.
1. JDBC
- 데이터베이스를 다루기 위한 자바 API (Application Programming Interface)
- JDBC를 통해서 DBMS의 종류와 관계 없이 질의문을 던져서 데이터를 수신
- 각 데이터베이스의 접속에 대한 상세한 정보가 불필요
- JDBC 인터페이스
- 프로그래머에게 쉬운 데이터베이스와 연동되는 프로그램을 작성할 수 있게 하는 도구
- JDBC 드라이버
- JDBC 인터페이스를 구현하여 실제로 DBMS를 작동시켜서 질의를 던지고 결과를 받음
1.1 JDBC를 통한 Oracle과의 연동 테스트
package ch11;
import java.sql.*;
public class DriverTest{
public static void main(String args[]){
Connection con;
try{
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(url, "webdb", "1234");
//con=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "1234");
System.out.println("Success");
}
catch(SQLException ex){ System.out.println("SQLException" + ex);}
catch(Exception ex){ System.out.println("Exception:" + ex);}
}
}
2. 데이터베이스 조작을 위한 자바 라이브러리
2.1 JDBC API (java.sql 패키지)
- Driver: 모든 드라이버 클래스들이 구현해야 하는 인터페이스
- DriverManager: 드라이버를 로드하고 데이터베이스에 연결
- Connection: 특정 데이터베이스와의 연결
- Statement: SQL문을 실행해 작성된 결과를 반환
- PreparedStatement: 사전에 컴파일된 SQL문을 실행
- ResultSet: SQL문에 대한 결과를 얻어냄
2.2 JSP와 데이터베이스의 직접적인 연동
JSP 페이지 내에서 직접 데이터베이스 관련 코드가 혼재되어 있어 추후 페이지 변경 등의 작업이 있을 때 유리하지 못함
예제: JSP 스크립트릿으로 데이터베이스를 연동하여 member 테이블에 있는 레코드를 조회
<%@ page contentType="text/html;charset=UTF-8" import="java.sql.*"%>
<%@ page import="java.util.*, ch11.*"%>
<%
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String id = "",
pwd = "",
name = "",
num1 = "",
num2 = "",
email = "",
phone = "",
zipcode = "",
address = "",
job = "";
int counter = 0;
try {
String url = "jdbc:oracle:thin:@localhost:1521:xe";
conn = DriverManager.getConnection(url, "webdb", "1234");
stmt = conn.createStatement();//Statement 생성
rs = stmt.executeQuery("select * from tblRegister"); //질의실행결과를 ResultSet에 담는다.
%>
<html>
<head>
<title>JSP에서 데이터베이스 연동</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#FFFFCC">
<h2>JSP 스크립틀릿에서 데이터베이스 연동 예제</h2><br/>
<h3>회원정보</h3>
<table bordercolor="#0000ff" border="1">
<tr>
<td><strong>ID</strong></td>
<td><strong>PWD</strong></td>
<td><strong>NAME</strong></td>
<td><strong>NUM1</strong></td>
<td><strong>NUM2</strong></td>
<td><strong>EMAIL</strong></td>
<td><strong>PHONE</strong></td>
<td><strong>ZIPCODE/ADDRESS</strong></td>
<td><strong>JOB</strong></td>
</tr>
<%
if (rs != null) {
while (rs.next()) {
id = rs.getString("id");
pwd = rs.getString("pwd");
name = rs.getString("name");
num1 = rs.getString("num1");
num2 = rs.getString("num2");
email = rs.getString("email");
phone = rs.getString("phone");
zipcode = rs.getString("zipcode");
address = rs.getString("address");
job = rs.getString("job");
%>
<tr>
<td><%=id%></td>
<td><%=pwd%></td>
<td><%=name%></td>
<td><%=num1%></td>
<td><%=num2%></td>
<td><%=email%></td>
<td><%=phone%></td>
<td><%=zipcode%>/<%=address%></td>
<td><%=job%></td>
</tr>
<%
counter++;
}//end while
}//end if
%>
</table>
<br/>
total records :<%=counter%>
<%
} catch (SQLException sqlException) {
System.out.println("sql exception");
} catch (Exception exception) {
System.out.println("exception");
} finally {
if (rs != null)
try {rs.close();}
catch (SQLException ex) {}
if (stmt != null)
try {stmt.close();}
catch (SQLException ex) {}
if (conn != null)
try {conn.close();}
catch (Exception ex) {}
}
%>
예제: 데이터베이스에 관련된 코드를 JSP 페이지로부터 분리
- JDBC 코드들 (RegisterMgr.java)
package ch11;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
public class RegisterMgr {
private final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";
private final String JDBC_URL = "jdbc:oracle:thin:@localhost:1521:xe";
private final String USER = "webdb";
private final String PASS = "1234";
public RegisterMgr() {
try{
Class.forName(JDBC_DRIVER);
}catch(Exception e){
System.out.println("Error : JDBC 드라이버 로딩 실패");
}
}
public Vector<RegisterBean> getRegisterList() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector<RegisterBean> vlist = new Vector<RegisterBean>();
try {
conn = DriverManager.getConnection(JDBC_URL, USER, PASS);
String strQuery = "select * from tblRegister";
stmt = conn.createStatement();
rs = stmt.executeQuery(strQuery);
while (rs.next()) {
RegisterBean bean = new RegisterBean();
bean.setId (rs.getString("id"));
bean.setPwd (rs.getString("pwd"));
bean.setName (rs.getString("name"));
bean.setNum1 (rs.getString("num1"));
bean.setNum2 (rs.getString("num2"));
bean.setEmail (rs.getString("email"));
bean.setPhone (rs.getString("phone"));
bean.setZipcode (rs.getString("zipcode"));
bean.setAddress (rs.getString("address"));
bean.setJob (rs.getString("job"));
vlist.addElement(bean);
}
} catch (Exception ex) {
System.out.println("Exception" + ex);
} finally {
if(rs!=null) try{rs.close();} catch(SQLException e){}
if(stmt!=null) try{stmt.close();}catch(SQLException e){}
if(conn!=null) try{conn.close();}catch(SQLException e){}
}
return vlist;
}
}
- 레코드들 (RegisterBean.java)
package ch11;
public class RegisterBean{
private String id;
private String pwd;
private String name;
private String num1;
private String num2;
private String email;
private String phone;
private String zipcode;
private String address;
private String job;
public void setId(String id) {
this.id = id;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public void setName(String name) {
this.name = name;
}
public void setNum1(String num1) {
this.num1 = num1;
}
public void setNum2(String num2) {
this.num2 = num2;
}
public void setEmail(String email) {
this.email = email;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public void setAddress(String address) {
this.address = address;
}
public void setJob(String job) {
this.job = job;
}
public String getId() {
return id;
}
public String getPwd() {
return pwd;
}
public String getName() {
return name;
}
public String getNum1() {
return num1;
}
public String getNum2() {
return num2;
}
public String getEmail() {
return email;
}
public String getPhone() {
return phone;
}
public String getZipcode() {
return zipcode;
}
public String getAddress() {
return address;
}
public String getJob() {
return job;
}
}
- JSP 페이지 (usingJDBCBean.jsp)
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*, ch11.*"%>
<jsp:useBean id="regMgr" class="ch11.RegisterMgr"/>
<html>
<head>
<title>JSP에서 데이터베이스 연동</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#FFFFCC">
<h2>Bean를 사용한 데이터베이스 연동 예제</h2><br/>
<h3>회원정보</h3>
<table bordercolor="#0000ff" border="1">
<tr>
<td><strong>ID</strong></td>
<td><strong>PASSWD</strong></td>
<td><strong>NAME</strong></td>
<td><strong>NUM1</strong></td>
<td><strong>NUM2</strong></td>
<td><strong>EMAIL</strong></td>
<td><strong>PHONE</strong></td>
<td><strong>ZIPCODE/ADDRESS</strong></td>
<td><strong>JOB</strong></td>
</tr>
<%
Vector<RegisterBean> vlist = regMgr.getRegisterList();
int counter = vlist.size();
for(int i=0; i<vlist.size(); i++){
RegisterBean regBean = vlist.get(i);
%>
<tr>
<td><%=regBean.getId()%></td>
<td><%=regBean.getPwd()%></td>
<td><%=regBean.getName()%></td>
<td><%=regBean.getNum1()%></td>
<td><%=regBean.getNum2()%></td>
<td><%=regBean.getEmail()%></td>
<td><%=regBean.getPhone()%></td>
<td><%=regBean.getZipcode()%>/<%=regBean.getAddress()%></td>
<td><%=regBean.getJob()%></td>
</tr>
<%}%>
</table>
<br/><br/>
total records : <%= counter %>
</body>
</html>
3. ConnectionPool을 사용한 데이터베이스 연결 기능 향상
3.1 ConnectionPool이란?
- 웹 프로그램은 실질적으로 데이터베이스에 연결하고 질의를 던지고 결과를 받아오는 부분에서 많은 시간을 소요
- 이러한 과정이 서버에 많은 부하를 주게 됨
- ConnectionPool을 사용해서 보다 효율적으로 데이터베이스에 연동
예제: ConnectionPool을 이용한 데이터베이스 프로그램
* Copyright(c) 2001 iSavvix Corporation (http://www.isavvix.com/)
*
* All rights reserved
*
* Permission to use, copy, modify and distribute this material for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of iSavvix Corporation not be used in
* advertising or publicity pertaining to this material without the
* specific, prior written permission of an authorized representative of
* iSavvix Corporation.
*
* ISAVVIX CORPORATION MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES,
* EXPRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST
* INFRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE
* SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL ISAVVIX CORPORATION OR
* ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
* LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELATING
* TO THE SOFTWARE.
*
*/
package ch11;
import java.sql.*;
import java.util.Properties;
import java.util.Vector;
/**
* Manages a java.sql.Connection pool.
*
* @author Anil Hemrajani
*/
public class DBConnectionMgr {
private Vector connections = new Vector(10);
private String _driver = "oracle.jdbc.driver.OracleDriver",
_url = "jdbc:oracle:thin:@localhost:1521:xe",
_user = "webdb",
_password = "1234";
private boolean _traceOn = false;
private boolean initialized = false;
private int _openConnections = 10;
private static DBConnectionMgr instance = null;
public DBConnectionMgr() {
}
/** Use this method to set the maximum number of open connections before
unused connections are closed.
*/
public static DBConnectionMgr getInstance() {
if (instance == null) {
synchronized (DBConnectionMgr.class) {
if (instance == null) {
instance = new DBConnectionMgr();
}
}
}
return instance;
}
public void setOpenConnectionCount(int count) {
_openConnections = count;
}
public void setEnableTrace(boolean enable) {
_traceOn = enable;
}
/** Returns a Vector of java.sql.Connection objects */
public Vector getConnectionList() {
return connections;
}
/** Opens specified "count" of connections and adds them to the existing pool */
public synchronized void setInitOpenConnections(int count)
throws SQLException {
Connection c = null;
ConnectionObject co = null;
for (int i = 0; i < count; i++) {
c = createConnection();
co = new ConnectionObject(c, false);
connections.addElement(co);
trace("ConnectionPoolManager: Adding new DB connection to pool (" + connections.size() + ")");
}
}
/** Returns a count of open connections */
public int getConnectionCount() {
return connections.size();
}
/** Returns an unused existing or new connection. */
public synchronized Connection getConnection()
throws Exception {
if (!initialized) {
Class c = Class.forName(_driver);
DriverManager.registerDriver((Driver) c.newInstance());
initialized = true;
}
Connection c = null;
ConnectionObject co = null;
boolean badConnection = false;
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
// If connection is not in use, test to ensure it's still valid!
if (!co.inUse) {
try {
badConnection = co.connection.isClosed();
if (!badConnection)
badConnection = (co.connection.getWarnings() != null);
} catch (Exception e) {
badConnection = true;
e.printStackTrace();
}
// Connection is bad, remove from pool
if (badConnection) {
connections.removeElementAt(i);
trace("ConnectionPoolManager: Remove disconnected DB connection #" + i);
continue;
}
c = co.connection;
co.inUse = true;
trace("ConnectionPoolManager: Using existing DB connection #" + (i + 1));
break;
}
}
if (c == null) {
c = createConnection();
co = new ConnectionObject(c, true);
connections.addElement(co);
trace("ConnectionPoolManager: Creating new DB connection #" + connections.size());
}
return c;
}
/** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
public synchronized void freeConnection(Connection c) {
if (c == null)
return;
ConnectionObject co = null;
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
if (c == co.connection) {
co.inUse = false;
break;
}
}
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
if ((i + 1) > _openConnections && !co.inUse)
removeConnection(co.connection);
}
}
public void freeConnection(Connection c, PreparedStatement p, ResultSet r) {
try {
if (r != null) r.close();
if (p != null) p.close();
freeConnection(c);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void freeConnection(Connection c, Statement s, ResultSet r) {
try {
if (r != null) r.close();
if (s != null) s.close();
freeConnection(c);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void freeConnection(Connection c, PreparedStatement p) {
try {
if (p != null) p.close();
freeConnection(c);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void freeConnection(Connection c, Statement s) {
try {
if (s != null) s.close();
freeConnection(c);
} catch (SQLException e) {
e.printStackTrace();
}
}
/** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
public synchronized void removeConnection(Connection c) {
if (c == null)
return;
ConnectionObject co = null;
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
if (c == co.connection) {
try {
c.close();
connections.removeElementAt(i);
trace("Removed " + c.toString());
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
private Connection createConnection()
throws SQLException {
Connection con = null;
try {
if (_user == null)
_user = "";
if (_password == null)
_password = "";
Properties props = new Properties();
props.put("user", _user);
props.put("password", _password);
con = DriverManager.getConnection(_url, props);
} catch (Throwable t) {
throw new SQLException(t.getMessage());
}
return con;
}
/** Closes all connections and clears out the connection pool */
public void releaseFreeConnections() {
trace("ConnectionPoolManager.releaseFreeConnections()");
Connection c = null;
ConnectionObject co = null;
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
if (!co.inUse)
removeConnection(co.connection);
}
}
/** Closes all connections and clears out the connection pool */
public void finalize() {
trace("ConnectionPoolManager.finalize()");
Connection c = null;
ConnectionObject co = null;
for (int i = 0; i < connections.size(); i++) {
co = (ConnectionObject) connections.get(i);
try {
co.connection.close();
} catch (Exception e) {
e.printStackTrace();
}
co = null;
}
connections.removeAllElements();
}
private void trace(String s) {
if (_traceOn)
System.err.println(s);
}
}
class ConnectionObject {
public java.sql.Connection connection = null;
public boolean inUse = false;
public ConnectionObject(Connection c, boolean useFlag) {
connection = c;
inUse = useFlag;
}
}
<%@ page contentType="text/html;charset=UTF-8" import="java.sql.*, ch11.*" %>
<%
DBConnectionMgr pool = DBConnectionMgr.getInstance();
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String id = "",
pwd = "",
name = "",
num1 = "",
num2 = "",
email = "",
phone = "",
zipcode = "",
address = "",
job = "";
int counter = 0;
try{
conn = pool.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from tblRegister");
%>
<html>
<head>
<title>JSP에서 데이터베이스 연동</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#FFFFCC">
<h2>JSP 스크립틀릿에서 Connection Pool을 이용한 데이터베이스 연동 예제</h2>
<br/>
<h3>회원정보</h3>
<table bordercolor="#0000ff" border="1">
<tr>
<td><strong>ID</strong></td>
<td><strong>PWD</strong></td>
<td><strong>NAME</strong></td>
<td><strong>NUM1</strong></td>
<td><strong>NUM2</strong></td>
<td><strong>EMAIL</strong></td>
<td><strong>PHONE</strong></td>
<td><strong>ZIPCODE/ADDRESS</strong></td>
<td><strong>JOB</strong></td>
</tr>
<%
if(rs!=null){
while(rs.next()){
id = rs.getString("id");
pwd = rs.getString("pwd");
name = rs.getString("name");
num1 = rs.getString("num1");
num2 = rs.getString("num2");
email = rs.getString("email");
phone = rs.getString("phone");
zipcode = rs.getString("zipcode");
address = rs.getString("address");
job = rs.getString("job");
%>
<tr>
<td><%= id %></td>
<td><%= pwd %></td>
<td><%= name %></td>
<td><%= num1 %></td>
<td><%= num2 %></td>
<td><%= email %></td>
<td><%= phone %></td>
<td><%= zipcode %>/<%= address %></td>
<td><%= job %></td>
</tr>
<%
counter++;
}//end while
}//end if
%>
</table><br/>
total records : <%= counter %>
<%
}catch(SQLException sqlException){
System.out.println("sql exception");
}catch(Exception exception){
System.out.println("exception");
}finally{
if( rs != null )
try{ rs.close(); }
catch(SQLException ex) {}
if( stmt != null )
try { stmt.close(); }
catch(SQLException ex) {}
if( conn != null )
try{ pool.freeConnection(conn); }
catch(Exception ex){}
}
%>
3.2 Pooling 기법
- 효율적으로 복수의 사용자에게 서비스하기 위해 미리 데이터베이스 연결을 위한 객체들을 생성
- Connection 객체의 재사용
- 데이터베이스 연결 객체를 매번 생성, 사용, 해제하지 않고 처음 만들어둔 데이터베이스 연결 객체를 계속 사용
- 사용자에게 필요한 응답을 주는데 걸리는 시간을 단축하고 시스템 부하를 줄임
- Pooling 기법의 DBConnectionMgr
예제: ConnectionPool과 Bean을 이용한 데이터베이스 연결
package ch11;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Vector;
public class RegisterMgrPool {
private DBConnectionMgr pool = null;
public RegisterMgrPool() {
try{
pool = DBConnectionMgr.getInstance();
}catch(Exception e){
System.out.println("Error : 커넥션 얻어오기 실패");
}
}
public Vector<RegisterBean> getRegisterList() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector<RegisterBean> vlist = new Vector<RegisterBean>();
try {
conn = pool.getConnection();
String strQuery = "select * from tblRegister";
stmt = conn.createStatement();
rs = stmt.executeQuery(strQuery);
while (rs.next()) {
RegisterBean bean = new RegisterBean();
bean.setId (rs.getString("id"));
bean.setPwd (rs.getString("pwd"));
bean.setName (rs.getString("name"));
bean.setNum1 (rs.getString("num1"));
bean.setNum2 (rs.getString("num2"));
bean.setEmail (rs.getString("email"));
bean.setPhone (rs.getString("phone"));
bean.setZipcode (rs.getString("zipcode"));
bean.setAddress (rs.getString("address"));
bean.setJob (rs.getString("job"));
vlist.addElement(bean);
}
} catch (Exception ex) {
System.out.println("Exception" + ex);
} finally {
pool.freeConnection(conn);
}
return vlist;
}
}
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*, ch11.*"%>
<jsp:useBean id="regMgr" class="ch11.RegisterMgrPool" />
<html>
<head>
<title>JSP에서 데이터베이스 연동</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#FFFFCC">
<h2>Bean과 커넥션 풀을 사용한 데이터베이스 연동 예제</h2><br/>
<h3>회원정보</h3>
<table bordercolor="#0000ff" border="1">
<tr>
<td><strong>ID</strong></td>
<td><strong>PASSWD</strong></td>
<td><strong>NAME</strong></td>
<td><strong>NUM1</strong></td>
<td><strong>NUM2</strong></td>
<td><strong>EMAIL</strong></td>
<td><strong>PHONE</strong></td>
<td><strong>ZIPCODE/ADDRESS</strong></td>
<td><strong>JOB</strong></td>
</tr>
<%
Vector<RegisterBean> vlist = regMgr.getRegisterList();
int counter = vlist.size();
for(int i=0; i<vlist.size(); i++){
RegisterBean regBean =vlist.get(i);
%>
<tr>
<td><%=regBean.getId()%></td>
<td><%=regBean.getPwd()%></td>
<td><%=regBean.getName()%></td>
<td><%=regBean.getNum1()%></td>
<td><%=regBean.getNum2()%></td>
<td><%=regBean.getEmail()%></td>
<td><%=regBean.getPhone()%></td>
<td><%=regBean.getZipcode()%>/<%=regBean.getAddress()%></td>
<td><%=regBean.getJob()%></td>
</tr>
<%
}
%>
</table>
<br/>
<br/>
total records : <%= counter %>
</body>
</html>
'강의 > KOSTA' 카테고리의 다른 글
[JSP/Servlet] Model1 구현 (Day25) (1) | 2022.04.11 |
---|---|
[JSP/Servlet] Session and Cookies (Day23) (0) | 2022.04.05 |
[JSP/Servlet] JSP and JavaBeans (Day22) (0) | 2022.04.04 |
[JSP/Servlet] Servlet Basic Syntax (Day22) (0) | 2022.04.04 |
[JSP/Servlet] JSP Internal Object (Day22) (0) | 2022.04.04 |