ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JDBC-22.06.21
    웹프로그래밍 2022. 6. 22. 00:17
    728x90

    DB에 대한 종속성을 없애야함 

    1. 어떤 DB여도 사용할 수 있게 추상화된 인터페이스 필요하다.

    2. 명령어 서로 다름(DB마다) 쿼리 객체 필요 일관된 인터페이스 필요하다.

    3. 쿼리 실행 방법론 인터페이스 필요

    이모든게 rt.jar안에  java- sql에 존재한다.

     

     

    드라이버 구현체는 제조사가 지원해준다.  => Facade객체(실객체가 따로있고 실객체에 명령을 전달해주는 객체. ex리모콘)

    pom.xml 추가하기 (벤더가 제공하는 드라이버 빌드패스에 추가)

    프로시저: 반환값 존재 x 

     

    JavaDataBaseConnectivity - JDBC Driver

    JDBC 단계
    1. 벤더가 제공하는 드라이버를 빌드패스에 추가(pom.xml)
    2. 드라이버 로딩

    3. Connection 수립
    4. Query 객체 생성
    Statement : 기본 쿼리 객체로 모든 쿼리 객체의 상위.
    PreparedStatement(선컴파일된 쿼리 객체) : 쿼리 객체 생성시 미리 고정된 쿼리문에 의해 컴파일된 쿼리 객체가 생성.
    CallableStatement : procedure/function 등 일련의 명령 집합객체를 실행할때.
    5. Query 실행
    ResultSet executeQuery : SELECT
    (rowcount) int executeUpdate : INSERT/UPDATE/DELETE
    6. 자원 해제(close)

     


    SELECT *
    FROM DATABASE_PROPERTIES;

    <DataBasePropertyVO>

    package kr.or.ddit.vo;
    
    import java.io.Serializable;
    
    public class DataBasePropertyVO implements Serializable{
    	// carmel 방식 변환
    	private String propertyName;
    	private String propertyValue;
    	private String description;
    	
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((description == null) ? 0 : description.hashCode());
    		result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
    		result = prime * result + ((propertyValue == null) ? 0 : propertyValue.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		DataBasePropertyVO other = (DataBasePropertyVO) obj;
    		if (description == null) {
    			if (other.description != null)
    				return false;
    		} else if (!description.equals(other.description))
    			return false;
    		if (propertyName == null) {
    			if (other.propertyName != null)
    				return false;
    		} else if (!propertyName.equals(other.propertyName))
    			return false;
    		if (propertyValue == null) {
    			if (other.propertyValue != null)
    				return false;
    		} else if (!propertyValue.equals(other.propertyValue))
    			return false;
    		return true;
    	}
    	
    	public String getPropertyName() {
    		return propertyName;
    	}
    	public void setPropertyName(String propertyName) {
    		this.propertyName = propertyName;
    	}
    	public String getPropertyValue() {
    		return propertyValue;
    	}
    	public void setPropertyValue(String propertyValue) {
    		this.propertyValue = propertyValue;
    	}
    	public String getDescription() {
    		return description;
    	}
    	public void setDescription(String description) {
    		this.description = description;
    	}
    	
    	@Override
    	public String toString() {
    		return "DataBasePropertyVO [propertyName=" + propertyName + ", propertyValue=" + propertyValue
    				+ ", description=" + description + "]";
    	}
    }

    <11/jdbcDesc.jsp>

    <%@page import="java.util.List"%>
    <%@page import="java.util.ArrayList"%>
    <%@page import="kr.or.ddit.vo.DataBasePropertyVO"%>
    <%@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"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>11/jdbcDesc.jsp</title>
    </head>
    <body>
    <h4>JavaDataBaseConnectivity - JDBC Driver</h4>
    <pre>
    	JDBC 단계
    	1. 벤더가 제공하는 드라이버를 빌드패스에 추가(pom.xml)
    	2. 드라이버 로딩
    	
    	3. Connection 수립
    	4. Query 객체 생성
    		Statement : 기본 쿼리 객체로 모든 쿼리 객체의 상위.
    		PreparedStatement(선컴파일된 쿼리 객체) : 쿼리 객체 생성시 미리 고정된 쿼리문에 의해 컴파일된 쿼리 객체가 생성.
    		CallableStatement : procedure/function 등 일련의 명령 집합객체를 실행할때.
    	5. Query 실행
    		ResultSet executeQuery : SELECT
    		(rowcount) int executeUpdate : INSERT/UPDATE/DELETE
    	6. 자원 해제(close)
    		
    
    	<%
    		Class.forName("oracle.jdbc.driver.OracleDriver");
    		String url = "jdbc:oracle:thin:@localhost:1521:xe";
    		String user = "LAI";
    		String password = "java";
    		// try with resource 구문
    		List<DataBasePropertyVO> dataList = new ArrayList<>();
    		try(
    			// Closable 객체 선언
    			Connection conn = DriverManager.getConnection(url, user, password);
    			Statement stmt = conn.createStatement();
    		){
    			String sql = "SELECT PROPERTY_NAME, PROPERTY_VALUE, DESCRIPTION FROM DATABASE_PROPERTIES";
    			ResultSet rs = stmt.executeQuery(sql);
    			while(rs.next()){
    				DataBasePropertyVO vo = new DataBasePropertyVO();
    				dataList.add(vo);
    				vo.setPropertyName(rs.getString("PROPERTY_NAME"));
    				vo.setPropertyValue(rs.getString("PROPERTY_VALUE"));
    				vo.setDescription(rs.getString("DESCRIPTION"));
    			}		
    		}catch(SQLException e){
    			throw new RuntimeException(e);
    		}
    	%>
    </pre>
    <table>
    <%
    	for(DataBasePropertyVO tmp : dataList){
    	%>
    	<tr>
    		<td><%=tmp.getPropertyName()%></td>
    		<td><%=tmp.getPropertyValue()%></td>
    		<td><%=tmp.getDescription()%></td>
    	</tr>
    	<%	
    	}
    %>
    </table>
    </body>
    </html>

     

    문제점

    -드라이버 로딩은 한번만 하면 되는데 지금 코드로는 해당jsp를 실행할때 마다 저장하려고함

    - 계정정보는 변경될 수 있음 그래서 변경될 수 있는  코드가 존재

    -모델 1구조이다...

    바꿔보자 


    static : 딱한번 실행되는 코드 

    refactoring작업 

    Factory method[Object] pattern:  하나의 객체에 대한 생성을 또 다른 객체가 전담하는 구조

    package kr.or.ddit.db;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    /**
     * Factory method[Object] pattern
     * : 하나의 객체에 대한 생성을 또 다른 객체가 전담하는 구조
     *
     */
    
    public class ConnectionFactory {
    	static{
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    		} catch (ClassNotFoundException e) {
    			throw new RuntimeException(e);
    		}
    	}
    	
    	public static Connection getConnection() throws SQLException { // 예외 이메소드의 호출자가 가져감 
    		String url = "jdbc:oracle:thin:@localhost:1521:xe";
    		String user = "LAI";
    		String password = "java";
    		Connection conn = DriverManager.getConnection(url, user, password);
    		return conn;
    	}
    }
    <%@page import="kr.or.ddit.db.ConnectionFactory"%>
    <%@page import="java.util.List"%>
    <%@page import="java.util.ArrayList"%>
    <%@page import="kr.or.ddit.vo.DataBasePropertyVO"%>
    <%@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"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>11/jdbcDesc.jsp</title>
    </head>
    <body>
    <h4>JavaDataBaseConnectivity - JDBC Driver</h4>
    <pre>
    	<%
    		
    		
    		// try with resource 구문
    		List<DataBasePropertyVO> dataList = new ArrayList<>();
    		try(
    			// Closable 객체 선언
    			Connection conn =ConnectionFactory.getConnection();
    			Statement stmt = conn.createStatement();
    		){
    			String sql = "SELECT PROPERTY_NAME, PROPERTY_VALUE, DESCRIPTION FROM DATABASE_PROPERTIES";
    			ResultSet rs = stmt.executeQuery(sql);
    			while(rs.next()){
    				DataBasePropertyVO vo = new DataBasePropertyVO();
    				dataList.add(vo);
    				vo.setPropertyName(rs.getString("PROPERTY_NAME"));
    				vo.setPropertyValue(rs.getString("PROPERTY_VALUE"));
    				vo.setDescription(rs.getString("DESCRIPTION"));
    			}		
    		}catch(SQLException e){
    			throw new RuntimeException(e);
    		}
    	%>
    </pre>
    <table>
    <%
    	for(DataBasePropertyVO tmp : dataList){
    	%>
    	<tr>
    		<td><%=tmp.getPropertyName()%></td>
    		<td><%=tmp.getPropertyValue()%></td>
    		<td><%=tmp.getDescription()%></td>
    	</tr>
    	<%	
    	}
    %>
    </table>
    </body>
    </html>


    properties파일을 이용한 설정을 외부로 분리

      자꾸 바뀌는 코드 자바코드에 있는것은 안좋아 별개의 외부의 설정파일 뺴는것이 좋음

     

    1. 클래스패스

    2.클래스패스리소스

    bin 실제클래스패스 클래스로더가 관리


    languageLap 

    <sampe.properties>

    prop1=value1
    prop2=한글값

    <message_en.properties>

    prop1=value1
    prop2=English

    <message_ko.properties>

    prop1=value1
    prop2=한글값

    <PropertiesFileRead.java>

    package kr.or.ddit.properties;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.Locale;
    import java.util.Map.Entry;
    import java.util.Properties;
    import java.util.ResourceBundle;
    
    public class PropertiesFileRead {
    	public static void main(String[] args) {
    //		useProperties(); //sample.properties실행할때
    		useResourceBundle();
    	}
    
    	private static void useResourceBundle() {
    		
    		String baseName ="kr.or.ddit.properties.message";
    		ResourceBundle bundle =ResourceBundle.getBundle(baseName);
    		Enumeration<String> keys = bundle.getKeys();
    		while(keys.hasMoreElements()) {
    			String key =(String)keys.nextElement();
    			String value =bundle.getString(key);
    			System.out.printf("%s:%s \n",key,value);
    		}
    		
    	}
    
    	private static void useProperties() {
    		String cpPath ="kr/or/ddit/properties/sample.properties";
    	   	ClassLoader loader = Thread.currentThread().getContextClassLoader();
    	   	try (
    	   	InputStream is = loader.getResourceAsStream(cpPath);
    	   	){
    	   		Properties properties = new Properties(); //property정보를 컬렉션처럼 관리 map과 동일
    	   		properties.load(is);  //사이즈0이었던것이 받아오게됨
    	   		
    	   		for(Entry<Object, Object> entry :properties.entrySet()) {
    	   			System.out.printf("%s: %s \n", entry.getKey(), entry.getValue());
    	   		}
    	   	}catch (IOException e) {
    			throw new RuntimeException(e);
    		}
    	}
    }

     


    dbInfo.properties파일 따로 만들어서 해보기 

    =>properties파일을 이용한 설정을 외부로 분리

    <%@page import="kr.or.ddit.db.ConnectionFactory"%>
    <%@page import="java.util.List"%>
    <%@page import="java.util.ArrayList"%>
    <%@page import="kr.or.ddit.vo.DataBasePropertyVO"%>
    <%@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"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>11/jdbcDesc.jsp</title>
    </head>
    <body>
    <h4>JavaDataBaseConnectivity - JDBC Driver</h4>
    <pre>
    	JDBC 단계
    	1. 벤더가 제공하는 드라이버를 빌드패스에 추가(pom.xml)
    	2. 드라이버 로딩
    	
    	3. Connection 수립
    	4. Query 객체 생성
    		Statement : 기본 쿼리 객체로 모든 쿼리 객체의 상위.
    		PreparedStatement(선컴파일된 쿼리 객체) : 쿼리 객체 생성시 미리 고정된 쿼리문에 의해 컴파일된 쿼리 객체가 생성.
    		CallableStatement : procedure/function 등 일련의 명령 집합객체를 실행할때.
    	5. Query 실행
    		ResultSet executeQuery : SELECT
    		(rowcount) int executeUpdate : INSERT/UPDATE/DELETE
    	6. 자원 해제(close)
    		
    
    	<%	
    		// try with resource 구문
    		List<DataBasePropertyVO> dataList = new ArrayList<>();
    		try(
    			// Closable 객체 선언
    			Connection conn =ConnectionFactory.getConnection();
    			Statement stmt = conn.createStatement();
    		){
    			String sql = "SELECT PROPERTY_NAME, PROPERTY_VALUE, DESCRIPTION FROM DATABASE_PROPERTIES";
    			ResultSet rs = stmt.executeQuery(sql);
    			while(rs.next()){
    				DataBasePropertyVO vo = new DataBasePropertyVO();
    				dataList.add(vo);
    				vo.setPropertyName(rs.getString("PROPERTY_NAME"));
    				vo.setPropertyValue(rs.getString("PROPERTY_VALUE"));
    				vo.setDescription(rs.getString("DESCRIPTION"));
    			}		
    		}catch(SQLException e){
    			throw new RuntimeException(e);
    		}
    	%>
    </pre>
    <table>
    <%
    	for(DataBasePropertyVO tmp : dataList){
    	%>
    	<tr>
    		<td><%=tmp.getPropertyName()%></td>
    		<td><%=tmp.getPropertyValue()%></td>
    		<td><%=tmp.getDescription()%></td>
    	</tr>
    	<%	
    	}
    %>
    </table>
    </body>
    </html>
    package kr.or.ddit.db;
    
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    
    /**
     * Factory method[Object] pattern
     *    : 하나의 객체에 대한 생성을 또다른 객체가 전담하는 구조
     *
     */
    public class ConnectionFactory {
       private static String url;
       private static String user;
       private static String password;
       static { 스태틱 코드블럭. 1번 단계에서 딱 한번 실행됨
    
          String dbInfoPath = "kr/or/ddit/db/dbInfo.properties";
          try(
                InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(dbInfoPath);
          ) {
    //         Class.forName("oracle.jdbc.driver.OracleDriver");
             Properties dbInfo = new Properties();  //map처럼 키와 벨류 처럼 사용됨 
             dbInfo.load(is);  property는 load()라는 메소드를 쓰는것 
             url = dbInfo.getProperty("url");
             user = dbInfo.getProperty("user");
             password = dbInfo.getProperty("password");
             Class.forName(dbInfo.getProperty("driverClassName"));
          } catch (Exception e) {
             throw new RuntimeException(e);
          }
       }
       
       public static Connection getConnection() throws SQLException {
        
          Connection conn = DriverManager.getConnection(url, user, password);
          return conn;
       }
    }

    driverClassName=oracle.jdbc.driver.OracleDriver
    url:jdbc:oracle:thin:@localhost:1521:xe
    user=LAI
    password=java

    SOLID 원칙 적용 S는 단일 책임의 원칙

    모델2구조확장해서 mvc패턴으로 만들자

    -부가설명

    서블릿 (컨트롤러)

    jsp (뷰)

    모델이 없다, 모델 레이어를 분리하면  Servlet이자 컨트롤러의 책임이 분리됨.

     

    실행코드캡슐화

    1. 데이터 보호

    2. 실행코드를 감추기위한 -> 인터페이스 구조를 통해서 구현

     

     

    인터페이스를 분리함으로써 다형성을 구현할 수 있다.

     

    최종적으로 모델2구조, 레이어는 5개

     

    728x90

    '웹프로그래밍' 카테고리의 다른 글

    회원등록, DB -22.06.23  (0) 2022.06.23
    로그인처리, 템플릿맛보기-0622  (0) 2022.06.22
    기본객체2, scope-0621  (0) 2022.06.21
    ServletContext,File explorer -22.06.20  (0) 2022.06.21
    로그인,기본객체 -22.06.16~06.17  (0) 2022.06.17
Designed by Tistory.