Archive

JSP - 오라클 데이터베이스 연동

|

JSP - 오라클 데이터베이스 연동


JSP에서 오라클 데이터베이스와 연동을 해보자

우선 실습을 위해 TEMPMEMBER 테이블을 만들었다.

이 테이블은 ID, 비번, 이름, 회원번호, 이멜, 전번, 우편, 주소, 직업 등의 필드를 가진다.

오라클 JDBC는 WebContent/WEB-INF/lib 안에 모셔둔다. 외부 라이브러리는 모두 이 곳에 위치하게 된다.

  1. JDBC를 이용하여 데이터 가져오기

    • 이 방법은 가장 기초적이면서도 꼭 알아야하는 방법이다
    • java.sql.*을 import 시킨다
    <%
    	Class.forName("oracle.jdbc.driver.OracleDriver");
    	Connection conn = null;
    	Statement stmt = null;
    	ResultSet rs = null;
    	String id = "";
    	String passwd = "";
    	<!-- ...생략 -->
    	int counter = 0;
       	
    	try {
    		conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521/XEPDB1", "mytest", "mytest");
    		stmt = conn.createStatement();
    		rs = stmt.executeQuery("SELECT * FROM TEMPMEMBER");
    %>
    <!-- HTML 시작 -->
    <%
    		if(rs!=null) {
    			while(rs.next()) {
    				id= rs.getString("id");
    				passwd = rs.getString("passwd");
    				<!-- ...생략 -->
    %>
    			<tr>
    				<td><%= id %></td>
    				<td><%= passwd %></td>
    				<!-- ...생략 -->
    			</tr>
    <%
    				counter++;
    			}//end while
    		}// end if
    %>
    </table><br>
    <%
    	} catch(SQLException se) {
    		System.out.println("sql exception");
    	} catch(Exception e) {
    		System.out.println("exception");
    	} 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(Exception e){}
    	}
    %>
    
    • Java에서 연동했던 방법과 크게 다르지 않다. 다만, 표현하고자 하는 데이터를 XML 태그 안에 집어넣는다는것 뿐?


  2. Connection Pool을 이용하여 데이터 가져오기

    • 데이터베이스와 연결된 커넥션을 미리 만들어서 저장해두었다가 필요시 꺼내쓰고 다시 반환하는 것을 커넥션 풀이라고 한다
    • 커넥션 풀을 이용하면 데이터베이스 부하를 줄이고 동시접속자를 유동적으로 처리할 수 있다는 장점이 있다
    • 커넥션을 저장할 수 있는 두 개의 Vector를 생성한다. (혹은 ArrayList)
    • Free 벡터는 커넥션풀 클래스의 객체가 생성될 때 미리 생성된 커넥션을 저장하는 저장소이다
    • used 벡터는 실제 미들웨어에서 DBMS와 연결할 때 사용하는 커넥션 저장소이다
    • Free에서 커넥션 객체를 꺼내 used에 저장하고 실제 앱과 연결 후 다시 반납하는 구조이다

    커넥션풀


    //Connection Pool Class
       
    import java.sql.*;
    import java.util.*;
       
    public class ConnectionPool {
    	// DB 드라이버 불러오기
    	static {
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    		} catch(ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    	}
       	
    	// 초기 커넥션 저장
    	private ArrayList<Connection> free;
    	private ArrayList<Connection> used; // 사용중인 커넥션 저장
    	private String url = "jdbc:oracle:thin:@localhost:1521/XEPDB1";
    	private String user = "mytest";
    	private String passwd = "mytest";
    	private int initialCons = 10; // 초기 커넥션 수
    	private int maxCons = 20; // 최대 커넥션 수
    	private int numCons = 0; // 총 커넥션 수
    	private static ConnectionPool cp;
       		
    	private ConnectionPool() throws SQLException {
    		// 초기 커넥션 수만큼 ArrayList 생성
    		free = new ArrayList<Connection>(initialCons);
    		used = new ArrayList<Connection>(initialCons);
       		
    		// 초기 커넥션 수만큼 커넥션 생성
    		while(numCons < initialCons) {
    			addConnection();
    		}
    	}
           
        // 객체 생성 후 ConnectionPool 리턴
    	public static ConnectionPool getInstance() {
    		try {
    			if(cp == null) {
    				synchronized(ConnectionPool.class) {
    					cp = new ConnectionPool();
    				}
    			}
    		} catch(SQLException e) {
    			e.printStackTrace();
    		}
    		return cp;
    	}
       	
    	// free에 커넥션 객체를 저장
    	private void addConnection() throws SQLException {
    		free.add(getNewConnection());
    	}
       	
    	// 새로운 커넥션 생성
    	private Connection getNewConnection() throws SQLException {
    		Connection con = null;
    		try {
    			con = DriverManager.getConnection(url, user, passwd);
    		} catch(SQLException e) {
    			e.printStackTrace();
    		}
    		System.out.println("About to connect to"+ con);
    		++numCons; // 커넥션 생성될 때마다 커넥선 수 증가
    		return con;
    	}
       	
    	// free에 있는 커넥션을 used로 옮기는 작업
    	public synchronized Connection getConnection() throws SQLException {
    		// free에 커넥션이 없으면 maxCons만큼 커넥션 생성
    		if(free.isEmpty()) {
    			while(numCons < maxCons) {
    				addConnection();
    			}
    		}
    		Connection _con;
    		_con = free.get(free.size() -1);
    		free.remove(_con);
    		used.add(_con);
    		return _con;
    	}
       	
    	// used에 있는 커넥션을 free로 반납
    	public synchronized void releaseConnection(Connection _con) throws SQLException {
    		boolean flag = false;
    		if(used.contains(_con)) {
    			used.remove(_con);
    			numCons--;
    			flag = true;
    		} else {
    			throw new SQLException("ConnectionPool 없음");
    		}
    		try {
    			if(flag) {
    				free.add(_con);
    				numCons++;
    			} else {
    				_con.close();
    			}
    		} catch(SQLException e) {
    			try {
    				_con.close();
    			} catch(SQLException e2) {
    				e2.printStackTrace();
    			}
    		}
    	}	
    }
    
    • JSP에서 ConnectionPool class 사용
    <%
    	ConnectionPool pool = ConnectionPool.getInstance();
    	Connection conn = null;
    	Statement stmt = null;
    	ResultSet rs = null;
    	String id = "";
    	String passwd = "";
    	<!-- ...생략 -->
    	int counter = 0;
       	
    	try {
    		conn = pool.getConnection();
    		stmt = conn.createStatement();
    		rs = stmt.executeQuery("SELECT * FROM TEMPMEMBER");
    %>
    <!-- HTML 시작 -->
    <%
    		if(rs!=null) {
    			while(rs.next()) {
    				id= rs.getString("id");
    				passwd = rs.getString("passwd");
    				<!-- ...생략 -->
    %>
    			<tr>
    				<td><%= id %></td>
    				<td><%= passwd %></td>
                    <!-- ...생략 -->
    			</tr>
    <%
    				counter++;
    			}//end while
    		}// end if
    %>
    </table><br>
    <%
    	} catch(SQLException se) {
    		System.out.println("sql exception");
    	} catch(Exception e) {
    		System.out.println("exception");
    	} finally {
    		if(rs != null) try {rs.close();}catch(SQLException e){}
    		if(stmt != null) try {stmt.close();}catch(SQLException e){}
    		if(conn != null) try {pool.releaseConnection(conn);}catch(Exception e){}
    	}
    %>
    
    • 1번 방법과 크게 다르지 않은데, 연결과 반납을 ConnectionPool 클래스의 메소드를 이용한다는 점이 다르다.


  3. JavaBeans를 이용하여 데이터 가져오기

    • VO와 DAO를 만들어 JSP에서 사용하는 방법
    package jdbc;
       
    public class TempMemberVO {
    	private String id;
    	private String passwd;
    	//... 생략
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getPasswd() {
    		return passwd;
    	}
    	public void setPasswd(String passwd) {
    		this.passwd = passwd;
    	}
        //... 생략
    }
    
    public class TempMemberDAO {
    	private final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";
    	private final String JDBC_URL = "jdbc:oracle:thin:@localhost:1521/XEPDB1";
    	private final String USER = "mytest";
    	private final String PASSWD = "mytest";
       	
    	public TempMemberDAO() {
    		try {
    				Class.forName(JDBC_DRIVER);
    		} catch(Exception e) {
    				System.out.println("ERROR : JDBC 드라이버 로딩 실패");
    		}
    	}
       	
    	// DB에서 데이터 받아서 벡터에 저장
    	public Vector<TempMemberVO> getMemberList() {
    		Connection conn = null;
    		Statement stmt = null;
    		ResultSet rs = null;
    		Vector<TempMemberVO> vecList = new Vector<TempMemberVO>();
    		try {
    			conn = DriverManager.getConnection(JDBC_URL, USER, PASSWD);
    			String query = "select * from tempmember";
    			stmt = conn.createStatement();
    			rs = stmt.executeQuery(query);
    			while(rs.next()) {
    				TempMemberVO vo = new TempMemberVO();
    				vo.setId(rs.getString("id"));
    				vo.setPasswd(rs.getString("passwd"));
    				<!-- ...생략 -->
    				vecList.add(vo);
    			}
    		} catch(Exception e) {
    			System.out.println("Exception" + e);
    		} 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(Exception e){}
    		}
    		return vecList;
    	}
    }
    
    • JSP에서 사용
    <jsp:useBean id="dao" class="jdbc.TempMemberDAO" scope="page" />
    <%
    	Vector<TempMemberVO> vlist = dao.getMemberList();
    	int counter = vlist.size();
    	for(int i=0; i<vlist.size(); i++) {
    		TempMemberVO vo = vlist.elementAt(i);
    %>
    	<tr>
    		<td><%= vo.getId() %></td>
    		<td><%= vo.getPasswd() %></td>
    		<td><%= vo.getName() %></td>
    		<td><%= vo.getMem_num1() %></td>
    		<td><%= vo.getMem_num2() %></td>
    		<td><%= vo.getEmail() %></td>
    		<td><%= vo.getPhone() %></td>
    		<td><%= vo.getZipcode() %>/<%= vo.getAddress() %></td>
    		<td><%= vo.getJob() %></td>
    	</tr>
    <%
    	}
    %>
    </table>
    


  4. Connection Pool과 JavaBeans 모두 적용하는 방법

    • 2번과 3번의 방법을 혼용하여 사용
    • 3번의 DAO에서 연결,반납하는 방법을 커넥션 풀 객체를 생성하고 커넥션 풀의 메소드를 이용
    public class TempMemberDAO {
    	private ConnectionPool pool = null;
       	
    	public TempMemberDAO() {
    		try {
    			pool = ConnectionPool.getInstance();
    		} catch(Exception e) {
    			System.out.println("ERROR : 커넥션 얻어오기 실패");
    		}
    	}
       	
    	// DB에서 데이터 받아서 벡터에 저장
    	public Vector<TempMemberVO> getMemberList() {
    		Connection conn = null;
    		Statement stmt = null;
    		ResultSet rs = null;
    		Vector<TempMemberVO> vecList = new Vector<TempMemberVO>();
    		try {
    			conn = pool.getConnection();
    			String query = "select * from tempmember";
    			stmt = conn.createStatement();
    			rs = stmt.executeQuery(query);
    			while(rs.next()) {
    				TempMemberVO vo = new TempMemberVO();
    				vo.setId(rs.getString("id"));
    				vo.setPasswd(rs.getString("passwd"));
    				vo.setName(rs.getString("name"));
    				vo.setMem_num1(rs.getString("mem_num1"));
    				vo.setMem_num2(rs.getString("mem_num2"));
    				vo.setEmail(rs.getString("e_mail"));
    				vo.setPhone(rs.getString("phone"));
    				vo.setZipcode(rs.getString("zipcode"));
    				vo.setAddress(rs.getString("address"));
    				vo.setJob(rs.getString("job"));
    				vecList.add(vo);
    			}
    		} catch(Exception e) {
    			System.out.println("Exception" + e);
    		} finally {
    			if(rs != null) try {rs.close();}catch(SQLException e){}
    			if(stmt != null) try {stmt.close();}catch(SQLException e){}
    			if(conn != null) try {pool.releaseConnection(conn);}catch(Exception e) {}
    		}
    		return vecList;
    	}
    }
    
    • JSP에서 사용하는 방법은 3번의 방법과 동일하다


  5. WAS에서 제공하는 DBCP 이용하여 데이터 가져오기

    • 아파치에서 제공하는 Connection Pool인 DBCP를 이용하여 오라클과 연동한다
    • www.apache.org의 common에서 collections, dbcp, pool 라이브러리를 다운받아 jar파일을 WEB-INF/lib 폴더에 넣는다
    • META-INF에 context.xml 파일을 추가하여 다음 속성을 기입한다
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    	<Resource name="jdbc/myOracle" 
                  auth="Container" 
                  driverClassName="oracle.jdbc.driver.OracleDriver" 
                  type="javax.sql.DataSource" 
                  url="jdbc:oracle:thin:@localhost:1521/XEPDB1" 
                  username="mytest" 
                  password="mytest" 
                  maxTotal="8" 
                  maxIdle="10" 
                  maxWaitMillis="-1" />
    </Context>
    

    속성

    자료 출처 : https://devbox.tistory.com/entry/JSP-%EC%BB%A4%EB%84%A5%EC%85%98-%ED%92%80-1

    • DD (web.xml)에 다음을 추가한다
      <resource-ref>
      	<description>ConnectionPool</description>
      	<res-ref-name>jdbc/myOracle</res-ref-name>
      	<res-type>javax.sql.DataSource</res-type>
      	<res-auth>Container</res-auth>
      </resource-ref>
    
    • JSP 컨테이너에서 이 환경설정을 사용해서 드라이버에 연결한다
    // import 주의
    import javax.naming.*;
    import javax.sql.*;
       
    public class TempMemberDAO {
    	private Connection getConnection() {
    		Connection conn = null;
    		try {
    			Context init = new InitialContext();
    			DataSource ds = (DataSource) init.lookup("java:comp/env/jdbc/myOracle");
    			conn = ds.getConnection();
    		} catch(NamingException ne) {
    			ne.printStackTrace();
    		} catch(SQLException se) {
    			se.printStackTrace();
    		}
    		return conn;
    	}
        	// DB에서 데이터 받아서 벡터에 저장
    	public Vector<TempMemberVO> getMemberList() {
    		Connection conn = null;
    		Statement stmt = null;
    		ResultSet rs = null;
    		Vector<TempMemberVO> vecList = new Vector<TempMemberVO>();
    		try {
    			conn = getConnection();
    			String query = "select * from tempmember";
    			stmt = conn.createStatement();
    			rs = stmt.executeQuery(query);
    			while(rs.next()) {
    				TempMemberVO vo = new TempMemberVO();
    				vo.setId(rs.getString("id"));
    				vo.setPasswd(rs.getString("passwd"));
    				vo.setName(rs.getString("name"));
    				vecList.add(vo);
    			}
    		} catch(Exception e) {
    			System.out.println("Exception" + e);
    		} 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(Exception e){}
    		}
    		return vecList;
    	}
    }
    
    • 커넥션 객체는 외부 API를 이용해서 생성되고 나머지 로직은 이전 예제와 같다
    • 실행 모습

    실행



참고 자료


KG 아이티뱅크 강의 자료

처음해보는 JSP&Servlet 웹 프로그래밍