
DB는 개념이다!
<조건>
1. 공유
2. 통행
3. 저장
4. 운영
자바에서 DB 프로그래밍을 하기 위해 사용되는 API
JDBC API 사용 어플리케이션의 기본 구성

자바는 DBMS 종류에 상관없이 하나의 JDBC API를 사용해서 데이터베이스 작업을 처리할 수 있다.
DBMS와 통신을 담당하는 자바 클래스
DBMS별로 알맞은 JDBC 드라이버 필요
-> 보통 jar파일로 제공
JDBC 드라이버 로딩
** 로딩? 하드디스크로부터 메모리에 올리는 것
로딩코드
Class.forName("JDBC드라이버 클래스의 완전한 이름");
주요 DBMS의 JDBC드라이버
- 오라클 : oracle.jdbc.driver.OracleDriver
- MySQL : com.mysql.jdbc.Driver
- MS SQL 서버 : com.microsoft.sqlserver.jdbc.SQLServerDriver
JDBC URL
Oracle: jdbc:oracle:thin:@HOST:PORT:SID
MySQL : jdbc:mysql://HOST[:PORT]/DBNAME[?param=value& param1...]
MS SQL : jdbc:sqlserver://HOST[:PORT];databaseName=DB
-> 오라클 드라이버는 thin 드라이버와 OCI 드라이버가 있는데, thin 드라이버는 자바 언어로만 구현된 JDBC 드라이버로서 JDK만 설치되어 있으면 어디서는 사용할 수 있다.
JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
-> 외우는 방법 : 오라클 JDBC 드라이버는 오라클꺼다~
데이터베이스 커넥션(연결 객체) 생성
-> 순서 : 1)jdbcDriver 2)계정아이디 3)비밀번호
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "사용자계정명";
String dbPass = "비밀번호";
-> 커넥션 객체에 이 세개를 담는다.
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
Statement 생성
stmt = conn.createStatement();
쿼리 실행
rs = stmt.excuteQuery(query);
쿼리 실행 결과 출력
-> while(rs.next()) 사용
사용한 Statement객체 종료
-> 중요! 닫지 않으면 메모리가 꽉차서 Connection 객체와 연결이 끊어진다.
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(SQLException ex){}
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@page import="java.sql.DriverManager"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>회원 목록</title>
</head>
<body>
MEMBER 테이블의 내용<br>
<table width="100%" border="1">
<tr>
<th>이름</th><th>아이디</th><th>이메일</th>
</tr>
<%
//1.JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//-->오라클 JDBC 드라이버는 오라클꺼다~~
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
//2.데이터베이스 커넥션(연결 객체) 생성
//jdbcDriver? 2)계정아이디? 3)비밀번호?
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER";
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Connection 객체에 위에서 만든 세개 담기
//3.Statement 생성
stmt = conn.createStatement();
//4.쿼리 실행
rs = stmt.executeQuery(query);
//5.쿼리 실행 결과 출력
while(rs.next()){
out.print("<tr>");
out.print("<td><a href='viewMember_pool.jsp?memberId="+rs.getString("MEMBERID")+"'>"+rs.getString("NAME")+"</td>");
out.print("<td>"+rs.getString("MEMBERID")+"</td>");
out.print("<td>"+rs.getString("EMAIL")+"</td>");
out.print("</tr>");
}
}catch(SQLException ex){
out.print(ex.getMessage());
ex.printStackTrace();
}finally{
//6.사용한 Statement객체 종료 (중요!!! 닫지않으면 메모리 꽉차서 Connection객체와 연결 끊어짐)
if(rs!=null)try{rs.close();}catch(SQLException ex){}
if(stmt!=null)try{stmt.close();}catch(SQLException ex){}
//7.커넥션 객체 종료
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
%>
</table>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>이름 변경 폼</title>
</head>
<body>
<form method="post" action="update.jsp">
<table border="1">
<tr>
<td>아이디</td><td><input type="text" name="memberId" size="10" /></td>
<td>이름</td>
<td><input type="text" name="name" size="10" /></td>
</tr>
<tr>
<td colspan="4"><input type="submit" value="변경" /></td>
</tr>
</table>
</form>
</body>
</html>
Statement 객체를 이용한 쿼리 실행
-> select문 실행 시 ResultSet executeQuery(String query) 메서드 사용
===> ResultSet을 결과값으로 리턴!
ResultSet에서 값 조회
next()메서드로 데이터 조회 여부 확인(커서가 이동됨)

데이터 조회를 위한 주요 메서드
-> ResultSet은 현재 커서 위치에 있는 행으로부터 데이터를 읽어오기 위해 get~~()형태의 메서드를 제공한다.
ex) getString(), getInt(),getLong()...
ResultSet에서 데이터 조회하는 코드
PreparedStatement를 이용한 처리
stmt = conn.prepareStatement(
"insert into MEMBER (MEMBERID, NAME, EMAIL) values (?, ?, ?)");
pstmt.setString(1, “a001”); // 첫번째 물음표의 값 지정
Pstmt.setString(2, “김은대"); // 두번째 물음표의 값 지정
pstmt.executeUpdate()
PreparedStatement의 사용 이유
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
//파라미터 목록 중 memberId 및 name을 get함
String memberId = request.getParameter("memberId");
String name = request.getParameter("name");
out.print("memberId : "+ memberId + ", name : " + name + "<br>");
//jdbc 드라이버 로딩(메모리에 올림)
Class.forName("oracle.jdbc.driver.OracleDriver");
//커넥션 객체 선언
Connection conn = null;
//Statement 객체 선언
Statement stmt = null;
String query = "UPDATE MEMBER SET NAME = '"+name+"' WHERE MEMBERID = '"+memberId+"'";
int updateCount = 0;
try{
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
//커넥션 객체 생성
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Statement 객체 생성
stmt = conn.createStatement();
//insert,update,delete --> executeUpdate()
//select --> executeQuery()
updateCount = stmt.executeUpdate(query);
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
if(stmt!=null)try{stmt.close();}catch(SQLException ex){}
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
if(updateCount>0){
out.print(memberId + "의 이름을 " + name + "(으)로 변경");
}else{
out.print(memberId + " 아이디가 없음");
}
%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>MEMBER 테이블에 레코드 입력</title>
</head>
<body>
<form method="post" action="insert.jsp">
<table border="1">
<tr>
<th>아이디</th>
<td><input type="text" name="memberid" size="10"></td>
<th>비밀번호</th>
<td><input type="password" name="password" size="10"></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="name" size="10"></td>
<th>이메일</th>
<td><input type="text" name="email" size="10"></td>
</tr>
<tr>
<td colspan="4"><input type="submit" value="입력" /></td>
</tr>
</table>
</form>
</body>
</html>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
String memberid = request.getParameter("memberid");
String password = request.getParameter("password");
String name = request.getParameter("name");
String email = request.getParameter("email");
out.print(memberid + ", " + password + ", " + name + ", " + email);
Class.forName("oracle.jdbc.driver.OracleDriver");
//커넥션 객체 선언
Connection conn = null;
//Statement 객체 선언
PreparedStatement pstmt = null;
String query = "INSERT INTO MEMBER(MEMBERID,PASSWORD,NAME,EMAIL) "
+ " VALUES(?,?,?,?)";
try{
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
//커넥션 객체 생성
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Statement 객체 생성
pstmt = conn.prepareStatement(query);
pstmt.setString(1, memberid);
pstmt.setString(2, password);
pstmt.setString(3, name);
pstmt.setString(4, email);
//insert,update,delete --> executeUpdate()
//select --> executeQuery()
pstmt.executeUpdate();
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
if(pstmt!=null)try{pstmt.close();}catch(SQLException ex){}
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
%>
<!DOCTYPE html>
<html>
<head>
<title>입력</title>
</head>
<body>
MEMBER 테이블에 새로운 레코드를 입력했습니다.
</body>
</html>
package dto;
//자바빈 클래스
public class Mem {
private String memberid;
private String password;
private String name;
private String email;
//기본생성자
public Mem() {
super();
}
public String getMemberid() {
return memberid;
}
public void setMemberid(String memberid) {
this.memberid = memberid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
데이터베이스와 연결된 커넥션을 미리 만들어서 풀(pool)속에 저장해두고 있다가 필요할 때에 커넥션을 풀에서 가져다 쓰고, 사용이 끝나면 다시 풀에 반환하는 기법
특징
커넥션을 미리 생성해두기 때문에 사용자가 DB를 사용할 때마다 매번 생성하는 것보다 더 빠른 속도를 보장한다.
커넥션의 최대 생성 개수도 제어해주기 때문에 많은 사용자가 몰려도 과부하를 방지할 수 있다.
1. 필요 라이브러리
설치 방법
https://mvnrepository.com/ 에서
commons-dbcp검색
Apache Commons DBCP클릭 - 2.9.0 클릭
jar 클릭해서 다운로드
commons-pool검색
Apache Commons Pool클릭 - 2.9.0
jar 클릭해서 다운로드
commons-logging검색
Apache Commons Logging 클릭 - 1.2
jar 클릭해서 다운로드
다운로드 받은 파일들 복사해서 WEB-INF\lib에 붙여넣기
2.데이터 베이스 세팅
1)계정 생성 및 권한 부여
2)테이블 생성
package jdbc;
import java.sql.DriverManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
//서블릿 클래스
public class DBCPInit extends HttpServlet {
@Override
public void init() throws ServletException{
//JDBC Driver를 로딩
loadJDBCDriver();
//커넥션풀을 초기화
initConnectionPool();
}
//JDBC Driver를 로딩
private void loadJDBCDriver() {
try {
//커넥션풀이 내부에서 사용할 JDBC Driver를 로딩함
Class.forName("oracle.jdbc.driver.OracleDriver");
}catch(ClassNotFoundException ex){
throw new RuntimeException("fail to load JDBC Driver", ex);
}
}
//커넥션풀을 초기화
private void initConnectionPool() {
try {
//의국에서 새로운 외과 의사를 생성할 때 필요한 외과가 있어야 함
//커넥션풀에서 새로운 커넥션을 생성할 때 사용할 커넥션 팩토리를 생성
ConnectionFactory connFactory =
new DriverManagerConnectionFactory(
"jdbc:oracle:thin:@localhost:1521:xe"
,"jspexam"
,"java"
);
//DBCP는 커넥션풀에 커넥션을 보관할 때 PoolableConnection을 사용
//이 Class는 내부적으로 실제 Connection을 담고 있음
//커넥션풀을 관리
PoolableConnectionFactory poolableConnFactory =
new PoolableConnectionFactory(connFactory, null);
//커넥션이 유효한지 여부 검사 시 사용할 쿼리
poolableConnFactory.setValidationQuery("select 1");
//커넥션 풀의 설정 정보 생성
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
//유휴 커넥션 검사 주기(1/1000초)
//놀고 있는 커넥션을 풀에서 제거하는 시간 기준 (5분)
poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
//풀에 보관중인 커넥션이 유효한지 검사할지 여부
poolConfig.setTestWhileIdle(true);
//커넥션 최소 개수
poolConfig.setMinIdle(4);
//커넥션 최대 개수
poolConfig.setMaxTotal(50);
//커넥션풀의 설정 정보를 생성. 팩토리와 커넥션풀 설정을 파라미터로 받음
GenericObjectPool<PoolableConnection> connectionPool =
new GenericObjectPool<>(poolableConnFactory, poolConfig);
//풀러블커넥션팩토리에도 생성이 된 커넥션 풀을 연결
poolableConnFactory.setPool(connectionPool);
//커넥션풀을 제공하는 JDBC 드라이버를 등록함
Class.forName("org.apache.commons.dbcp2.PoolingDriver");
PoolingDriver driver = (PoolingDriver)DriverManager.getDriver("jdbc:apache:commons:dbcp:");
//커넥션 풀 드라이버에 생성된 커넥션풀을 등록
//jdbc:apache:commons:dbcp:ddit
driver.registerPool("ddit", connectionPool);
}catch(Exception e) {
throw new RuntimeException(e);
}//end try
}//end initConnectionPool();
}
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//커넥션을 제공해주는 클래스
public class ConnectionProvider {
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection("jdbc:apache:commons:dbcp:ddit");
}
}
package jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//하나의 클래스에 같은 이름의 메소드를 여러번 사용 가능?
//오버로딩
public class JdbcUtil {
public static void close(ResultSet rs) {
if(rs!=null) try {rs.close();}catch(SQLException ex) {}
}
public static void close(Statement stmt) {
if(stmt!=null) try {stmt.close();}catch(SQLException ex) {}
}
public static void close(Connection conn) {
if(conn!=null) try {conn.close();}catch(SQLException ex) {}
}
public static void close(PreparedStatement pstmt) {
if(pstmt!=null) try {pstmt.close();}catch(SQLException ex) {}
}
public static void rollback(Connection conn) {
if(conn!=null) try {conn.close();}catch(SQLException ex) {}
}
}
DBCP 이용한 방법으로 list 출력하기
<%@page import="jdbc.ConnectionProvider"%>
<%@page import="jdbc.JdbcUtil"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
MEMBER 테이블의 내용<br>
<table width="100%" border="1">
<tr>
<th>이름</th><th>아이디</th><th>이메일</th>
</tr>
<%
//1.JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//-->오라클 JDBC 드라이버는 오라클꺼다~~
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
//2.데이터베이스 커넥션(연결 객체) 생성
//1)jdbcDriver? 2)계정아이디? 3)비밀번호?
String jdbcDriver = "jdbc:apache:commons:dbcp:ddit";
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER";
// conn = DriverManager.getConnection(jdbcDriver); 이제 이거 안씀
conn = ConnectionProvider.getConnection();
//3.Statement 생성
stmt = conn.createStatement();
//4.쿼리 실행
rs = stmt.executeQuery(query);
//5.쿼리 실행 결과 출력
while(rs.next()){
out.print("<tr>");
out.print("<td><a href='viewMember.jsp?memberId="+rs.getString("MEMBERID")+"'>"+rs.getString("NAME")+"</td>");
out.print("<td>"+rs.getString("MEMBERID")+"</td>");
out.print("<td>"+rs.getString("EMAIL")+"</td>");
out.print("</tr>");
}
}catch(SQLException ex){
out.print(ex.getMessage());
ex.printStackTrace();
}finally{
//6.사용한 Statement객체 종료
JdbcUtil.close(rs);
JdbcUtil.close(stmt);
//7.커넥션 객체 종료 -> dbcp이니까 커넥션 객체를 커넥션 풀로 반환
JdbcUtil.close(conn);
}
%>
</table>
</body>
</html>
위 리스트에서 a태그(memberid)클릭 시 상세화면 이동
<%@page import="dto.Mem"%>
<%@page import="jdbc.ConnectionProvider"%>
<%@page import="jdbc.JdbcUtil"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String memberId = request.getParameter("memberId");
%>
<!DOCTYPE html>
<html>
<head>
<title>회원 정보</title>
</head>
<body>
<%
//jdbc 드라이버 로딩(메모리에 올림)
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Mem memVO = new Mem();
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER "
+ " WHERE MEMBERID = '"+memberId+"'";
try{
// conn = DriverManager.getConnection(
// "jdbc:oracle:thin:@localhost:1521:xe",
// "jspexam",
// "java");
conn = ConnectionProvider.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
if(rs.next()){
memVO.setMemberid(rs.getString("MEMBERID"));
memVO.setName(rs.getString("NAME"));
memVO.setPassword(rs.getString("PASSWORD"));
memVO.setEmail(rs.getString("EMAIL"));
}
out.print("memVO : " + memVO.toString());
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
//6.사용한 Statement객체 종료
JdbcUtil.close(rs);
JdbcUtil.close(stmt);
//7.커넥션 객체 종료 -> dbcp이니까 커넥션 객체를 커넥션 풀로 반환
JdbcUtil.close(conn);
}
%>
<c:set var="memVO" value="<%=memVO%>" scope="request" />
<!-- scope="request" 면 하나의 객체를 공유해서 쓸수있다 -->
<table border="1">
<tr>
<th>아이디 </th><td>${memVO.memberid}</td>
</tr>
<tr>
<th>비밀번호 </th><td>${memVO.password}</td>
</tr>
<tr>
<th>이름</th><td>${memVO.name}</td>
</tr>
<tr>
<th>이메일</th><td>${memVO.email}</td>
</tr>
</table>
</body>
</html>