대부분의 페이지가 DB와 연동 (이메일 등)

매번 매개변수를 초기화 해야하는 부담 → 생성자를 오버로딩 하는 방식으로 해결할 수 있다

가장 모듈화가 잘 된 방식이 이 방식.

 

코딩을 할 때는 모듈화가 중요하다. 잘 만들어진 모듈 하나는 열 개발자 안 부럽다.

→ 리팩토링이라고도 한다. 좀 더 코드를 최적화할 수 있는 형태를 생각, 모듈화 하듯

 

❗️앞으로 두고두고 중요한 개념이다

jsp의 내장객체인 application 을 읽을 수 있다면 매개변수는 한번에 읽어올 수 있다.

application 타입 → ServletContext application

 

JDBConnect.java

	public JDBConnect(ServletContext application) {
		String driver = application.getInitParameter("OracleDriver"); 
		
		try {
			Class.forName(driver);
			
			String url = application.getInitParameter("OracleURL");
			String id = application.getInitParameter("OracleId");
			String pwd = application.getInitParameter("OraclePwd");
			
			con = DriverManager.getConnection(url, id, pwd);
			
			System.out.println("DB 연결 성공(인수 생성자 2)");
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

 

JDBCTest2.jsp

	<%
	JDBConnect jdbc3 = new JDBConnect(application);
	jdbc3.close();
	%>

테스트할 페이지에서는 매개변수인 application을 한번 더 호출해주면 된다.

 

 

 

전체코드)

JDBConnect.java

package common;

import java.sql.Statement;

import jakarta.servlet.ServletContext;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBConnect {
	// Connection,
	// statement (쿼리문 쓸 때 필요한 객체, 많이 안쓴다.),
	// PreparedStatement (쿼리문 사용할 떄 필요한 객체 많이쓴다. 쿼리문을 쓸 때 융통성이 좋다.),
	// ResultSet (실행된 쿼리문의 결과를 받아올 떄 필요한 객체)

	public Connection con;
	public Statement stmt;
	public PreparedStatement psmt;
	public ResultSet rs;

	public JDBConnect() {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:XE";

		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "musthave", "1234");

			System.out.println("DB 연결 성공 (기본 생성자)");

		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}

	// 두번째 생성자 방식 - 매개변수로 개인 정보를 숨김
	public JDBConnect(String driver, String url, String id, String pwd) {
		try {
			// JDBC 드라이버 로드
			Class.forName(driver);

			// DB에 연결
			con = DriverManager.getConnection(url, id, pwd);

			System.out.println("DB 연결 성공(인수 생성자 1)");

		} catch (SQLException e) {
			e.printStackTrace();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}
	
	public JDBConnect(ServletContext application) {
		String driver = application.getInitParameter("OracleDriver"); 
		
		try {
			Class.forName(driver);
			
			String url = application.getInitParameter("OracleURL");
			String id = application.getInitParameter("OracleId");
			String pwd = application.getInitParameter("OraclePwd");
			
			con = DriverManager.getConnection(url, id, pwd);
			
			System.out.println("DB 연결 성공(인수 생성자 2)");
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void close() {

		try {
			if (con != null) {
				con.close();
			}
		} catch (Exception e) {

		}
	}
}

 

JDBCTest2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="common.JDBConnect"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h2>JDBCTest1</h2>

	<%
	JDBConnect jdbc1 = new JDBConnect();
	jdbc1.close();
	%>

	<h2>JDBCTest2</h2>

	<%
	String driver = application.getInitParameter("OracleDriver");
	String url = application.getInitParameter("OracleURL");
	String id = application.getInitParameter("OracleId");
	String pwd = application.getInitParameter("OraclePwd");

	JDBConnect jdbc2 = new JDBConnect(driver,url,id,pwd);
	jdbc2.close();
	%>
	
	<h2>JDBCTest3</h2>
	<%
	JDBConnect jdbc3 = new JDBConnect(application);
	jdbc3.close();
	%>

</body>
</html>

 

기존 방식은 접속할때마다 접속할 수 있는 입구를 만들고, 접속을 끊으면 입구를 없애는 방식이었다.

요청이 있을 때마다 입구를 만드는 방식.

 

 

🍀 커넥션 풀 방식

미리 입구를 만들어 놓는다. 용량 낭비가 조금 있지만 바로 들어와서 이용할 수 있다.

커넥션 풀 방식에서는 web.xml 역할을 하는 것이 server.xml (서술배포자로의 역할을 한다)

server.xml 수정 - 구문 추가

 <Resource auth="Container"
              driverClassName="oracle.jdbc.OracleDriver"
              type="javax.sql.DataSource" 
              initialSize="0" // 초기 사이즈 (몇개 만들건지)
              minIdle="5" 
              maxTotal="20" // 최대 개수
              maxIdle="20"
              maxWaitMillis="5000" // 대기시간 5초 
              url="jdbc:oracle:thin:@localhost:1521:xe" 
              name="dbcp_myoracle" // 이름 속성에 들어간 값이 정해진 건 아니지만 프로그램에서 이름을 가져다 쓴다. 
              username="musthave"
              password="1234" />

이 정보가 Pull 방식을 쓸 수 있게 해주는 매개변수같이 동작한다.

 

❗️필수 구성 항목

  • driverClassName="oracle.jdbc.OracleDriver"
  • type="javax.sql.DataSource"
  • url="jdbc:oracle:thin:@localhost:1521:xe"
  • name="dbcp_myoracle" // 이름 속성에 들어간 값이 정해진 건 아니지만 프로그램에서 이름을 가져다 쓴다.
  • username="musthave"
  • password="1234"

 

name="dbcp_myoracle" // 이름 속성에 들어간 값이 정해진 건 아니지만 프로그램에서 이름을 가져다 쓰기 때문에 어떤 값이 있는지는 알아야한다. 떄문에 의미있는 이름을 짓는 것이 좋다.

 

context.xml 수정 - 구문 추가

<ResourceLink global="dbcp_myoracle" name="dbcp_myoracle" 
                  type="javax.sql.DataSource"/>

여기까지하고 톰켓서버 restart

 

 

DBConnPool.java

package common;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class DBConnPool {
	public Connection con;
	public Statement stmt;
	public PreparedStatement psmt;
	public ResultSet rs;

	public DBConnPool() {

		// 커넥션 풀 방식

		try {
			// 기본 세팅
			Context initCtx = new InitialContext();
			Context ctx = (Context) initCtx.lookup("java:comp/env");
			DataSource source = (DataSource) ctx.lookup("dbcp_myoracle");

			con = source.getConnection(); // DB를 연결해주는 메서드

			System.out.println("DB 커넥션 풀 연결 성공");

		} catch (Exception e) {

		}
	}

	public void close() {

		try {
			if (con != null) {
				con.close();
			}
		} catch (Exception e) {

		}
	}
}

 

JDBCTest2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="common.JDBConnect"%>
<%@ page import= "common.DBConnPool" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h2>JDBCTest1</h2>

	<%
	JDBConnect jdbc1 = new JDBConnect();
	jdbc1.close();
	%>

	<h2>JDBCTest2</h2>

	<%
	String driver = application.getInitParameter("OracleDriver");
	String url = application.getInitParameter("OracleURL");
	String id = application.getInitParameter("OracleId");
	String pwd = application.getInitParameter("OraclePwd");

	JDBConnect jdbc2 = new JDBConnect(driver,url,id,pwd);
	jdbc2.close();
	%>
	
	<h2>JDBCTest3</h2>
	<%
	JDBConnect jdbc3 = new JDBConnect(application);
	jdbc3.close();
	%>
	
	<h2>JDBCTest4</h2>
	<%
	DBConnPool pool = new DBConnPool();
	pool.close();
	%>

</body>
</html>

 

연결 테스트를 해보면 연결이 된 것을 확인할 수 있다.

 

 

🍀 DB 데이터를 서버에서 집어넣어보기

 

ExeUpdate.jsp

<%@page import="java.sql.PreparedStatement"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="common.JDBConnect"%>
<%@ page import="java.sql.PreparedStatement"%> 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 회원추가 -->
	<h2>회원 추가 테스트</h2>

	<%
	JDBConnect jdbc = new JDBConnect();

	String id = "test1";
	String pass = "1111";
	String name = "테스트1회원";

	// varchar2 타입 문자 처리 -> '"내용"' 코드가 까다로워 이렇게 쓰지 않는다
	// String sql = "insert into member (id, pass, name) values ('" + id + "', '" + pass + "', '" + name + "')";

	// PreparedStatement 방식 -> 컬럼의 개수에 맞게 ? 를 넣어준다. 
	// PreparedStatement 쿼리문을 실행하게 하는 메소드, 유연성이 있다. 
	String sql = "insert into member (id, pass, name) values (?, ?, ?)";

	PreparedStatement psmt = jdbc.con.prepareStatement(sql);
	// psmt.setString(순서, 정해주고 싶은 값);
	psmt.setString(1, id);  
	psmt.setString(2, pass);
	psmt.setString(3, name);
	
	// PreparedStatement 로 쿼리문 실행
	// executeQuery() -> select
	// executeUpdate() -> Insert, update, delete
	// 				   -> 반환값을 가진다. 0 or 0 보다 큰 값
	
	int result = psmt.executeUpdate();
	
	if (result > 0) {
		out.print(result + "행이 입력되었습니다.");
	} else {
		out.print("입력 실패");
	}
	
	jdbc.close(); // 사용중인 객체 close()

%>

</body>
</html>

 

JDBConnect.java

package common;

import java.sql.Statement;

import jakarta.servlet.ServletContext;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBConnect {
	// Connection,
	// statement (쿼리문 쓸 때 필요한 객체, 많이 안쓴다.),
	// PreparedStatement (쿼리문 사용할 떄 필요한 객체 많이쓴다. 쿼리문을 쓸 때 융통성이 좋다.),
	// ResultSet (실행된 쿼리문의 결과를 받아올 떄 필요한 객체)

	public Connection con;
	public Statement stmt;
	public PreparedStatement psmt;
	public ResultSet rs;

	public JDBConnect() {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:XE";

		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, "musthave", "1234");

			System.out.println("DB 연결 성공 (기본 생성자)");

		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}

	// 두번째 생성자 방식 - 매개변수로 개인 정보를 숨김
	public JDBConnect(String driver, String url, String id, String pwd) {
		try {
			// JDBC 드라이버 로드
			Class.forName(driver);

			// DB에 연결
			con = DriverManager.getConnection(url, id, pwd);

			System.out.println("DB 연결 성공(인수 생성자 1)");

		} catch (SQLException e) {
			e.printStackTrace();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}
	
	public JDBConnect(ServletContext application) {
		String driver = application.getInitParameter("OracleDriver"); 
		
		try {
			Class.forName(driver);
			
			String url = application.getInitParameter("OracleURL");
			String id = application.getInitParameter("OracleId");
			String pwd = application.getInitParameter("OraclePwd");
			
			con = DriverManager.getConnection(url, id, pwd);
			
			System.out.println("DB 연결 성공(인수 생성자 2)");
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void close() {

		try {
			if (stmt != null) {
				stmt.close();
			}
			if (rs != null) {
				rs.close();
			}
			if (psmt != null) {
				psmt.close();
			}
			if (con != null) {
				con.close();
			}
		} catch (Exception e) {

		}
	}
}

다른 객체들을 사용할때도 다 null 이 아니면 close() 될 수 있도록 수정했다.

 

DB에도 데이터가 잘 들어간 것을 확인할 수 있다.

 

 

Insert, update, delete 비슷한 방식 처리

PreparedStatement 사용

 

select는 다른 방식

PreparedStatement 사용이 일반적이지만,

여기 예시에서는 Statement를 사용해보겠다.

 

 

🌀 select 해보기

 

ExeQuery.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="common.JDBConnect"%>
<%@ page import="java.sql.Statement"%>
<%@ page import="java.sql.ResultSet"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h2>회원 목록 조회 테스트</h2>
	<%
	JDBConnect jdbc = new JDBConnect();

	String sql = "select * from member";

	Statement stmt = jdbc.con.createStatement();

	// Statement 로 쿼리문 실행
	// executeQuery() -> select
	// executeUpdate() -> Insert, update, delete
	// 				   -> 반환값을 가진다. 0 or 0 보다 큰 값

	// 실행할 때 쿼리실행문을 넣는다.
	// ResultSet 래코드의 개수만큼 참조 -> 그 안에는 컬럼 단위 
	// next() 메서드가 주소값을 참조하며 이동해 레코드를 읽어주는 역할 
	// 참조 가능한 레코드가 있을 땐 next() -> true 반환 
	// 없다면 flase 반환 
	// 그렇다면 false를 반환할때까지 while 문으로 돌리기
	ResultSet rs = stmt.executeQuery(sql);

	while (rs.next()) {
		String id = rs.getString("id");
		String pw = rs.getString("pass");
		String name = rs.getString("name");
		// java.sql.Date regidate = rs.getDate("regidate");
		String regidate = rs.getString("regidate");

		out.print(String.format("%s %s %s %s", id, pw, name, regidate) + "</br>");

	}

	jdbc.close();
	%>

</body>
</html>

 

  • executeQuery() -> select
  •                               → ResultSet : 조회된 결과

 

  • executeUpdate() -> Insert, update, delete
  •                                    -> 반환값을 가진다. 0 or 0 보다 큰 값

 

  • getInt(), getFloat(), getString(), getDate() 로 데이터를 받는다.

 

 

날짜 데이터 가져오는 방식)

날짜 연산이 필요할 땐 아래와 같이,

java.sql.Date regidate = rs.getDate("regidate");

그냥 날짜 데이터만 가지고 올 땐 아래와 같은 형식으로 사용한다.

String regidate = rs.getString("regidate");

 

 


 

🍀 회원가입 폼을 만들어서 실제 테이블에 저장해보기

 

 

🌀 회원가입 → 브라우저 화면에서 값을 입력해서 집어넣기

 

Member.jsp - 회원가입 페이지 만들기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>

<body>

<form action="MemberProcess.jsp" method = "post">

<label>아이디 : </label>
<input type = "text" name = "id">
<br>
<label>비밀번호 : </label>
<input type = "password" name = "pwd">
<br> 
<label>이름 : </label>
<input type = "text" name = "name">
<br>
<input type = "submit" value = "회원가입">

</form>

</body>
</html>

 

MemberProcess.jsp - 회원가입된 정보 DB에 집어 넣기

<%@page import="utils.JSFunction"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="common.JDBConnect"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
String id = request.getParameter("id");
String pass = request.getParameter("pwd");
String name = request.getParameter("name");

JDBConnect jdbc = new JDBConnect();

String sql = "insert into member (id, pass, name) values (?, ?, ?)";

PreparedStatement psmt = jdbc.con.prepareStatement(sql);

psmt.setString(1, id);
psmt.setString(2, pass);
psmt.setString(3, name);

int result = psmt.executeUpdate();

if (result > 0){
	JSFunction.alertLocation("데이터 삽입 성공", "MemberList.jsp", out);
}

%>

회원가입이 완료되어 데이터가 DB에 들어가고, MemberList.jsp 페이지로 넘어간 모습이다.

 

 

🌀 회원 목록 보기

 

MemberList.jsp

<%@page import="java.sql.ResultSet"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="common.JDBConnect"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>회원 목록 보기</h2>
<%
JDBConnect jdbc = new JDBConnect();

String sql = "select * from member"; 

PreparedStatement psmt = jdbc.con.prepareStatement(sql);
ResultSet rs = psmt.executeQuery();

while (rs.next()){
	String id = rs.getString("id");
	String pass = rs.getString("pass");
	String name = rs.getString("name");
	String regidate = rs.getString("regidate");
	
	out.print(String.format("%s %s %s %s", id, pass, name, regidate) + "</br>");
}
%>
</body>
</html>

데이터가 들어간 것을 확인할 수 있다.

+ Recent posts