(16)-23.10.16[JAVA]

DANA·2023년 10월 16일

KDT-구디아카데미

목록 보기
16/56
<예제1>
package com.step6;

import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import java.util.ArrayList;
import java.util.HashMap;

/*
 * 업무요청에 대한 결과가 조인이 불가피할 때 하나의 클래스로 제네릭을 사용할 수 없다
 * Map 인터페이스를 사용하는 것이 효과적임 - 키와 값으로 관리함
 * 키를 컬럼명으로 통일하면 일관성있는 변수명으로 접근이 가능함 - 속도도 빠름
 */
class Emp1{
	private int empno = 0;
	private String ename = null;
}
class Dept1{
	private String dname = null;
}

// 컬렉션 프레임워크란? 자료구조를 API로 구현한 것
// 이것들의 역할은 읽기와 쓰기, 추가로 검색기능지원
public class AddList {

	public static void main(String[] args) {
		JButton jbtnSelect = new JButton();
		// 선언부와 생성부의 이름이 다르면 다형성을 누릴 수 있다.
		// 다형성에 대한 전제조건이다.
		// 인터페이스, 추상클래스 변수명 = new 구현체클래스();
		// 재사용성을 높인다. 이식성을 좋게 함. 유연하다
		// 기존의 코드를 변경해야 한다 - 있는 걸 바꾼다 - 사이드이펙트(부수효과) 발생함
		// 이식성, 재사용성 - 객체지향 언어가 추구하는 방향성
		// 전역변수 -  클래스 중심의 코딩을 전개하기 - 중요함 - 유지됨 - 람다식과 같은 함수형에서는 사용하지 않는다 - 왜냐면 사이드이펙트
		// 지역변수 - 처리하면 그 메소드 안에서만 유지됨 - 다른 사이드이펙트 발생하지 않음.
		// 안전함 - 람다식이라는 함수형 프로그래밍 지원 가능한 이유
		// 상속받거나 구현체 클래스를 선언할 때 하위클래스를 상속받는 게 더 많은 변수와 메소드를 사용할 수 있다
		List<JButton> li = new ArrayList<>();
		// List 인터페이스의 구현체 클래스가 ArrayList이다.
		// 인터페이스는 단독으로 인스턴스화를 할 수 없다.
		List<Map<String,Object>>list = new ArrayList<>(); // []형식을 가짐(Gson. lib 데이터 수집, 형전환, 변환) - JSON 
		Map<String,Object>map = new HashMap<>();
		map.put("empno",7782);
		map.put("ename","CLARK");
		map.put("dname","ACCOUNTING");
		list.add(map);
	}
}

<예제2-1>
// 다형성 활용하는 방법
package com.step6;

public class Super1 {
int a=1;
void methodA() {
	System.out.println("methodA 호출");
	
}
}
<예제2-2>
package com.step6;
// 다형성
// 같은 메소드를 호출했는데 그 결과가 달라진다
// me.methodB(), sup1.methodB()
public class Me extends Super1 {
	public void methodC() {
		System.out.println("methodC()호출");
	}
	public static void main(String[] args) {
		Me me = new Me();
		Super1 sup1 = new Me(); // 선언부와 생성부의 이름이 다른 것에 대해 얘기하고 있음(다형성)
		// 이게 가능하지만, 가능하다고 해서 methodC를 호출할 수 있는 건 아니다. 불가함
		Super1 sup11 = new Super1();
		System.out.println(me.a);
		me.methodA();
		sup1.methodA();
		// 1. 상위 클래스 타입의 인스턴스 변수로 하위 클래스에 정의된 메소드를 호출불가함
		sup1.methodC(); // 에러
		sup11.methodC(); // 에러
		me.methodC();
	}
}
// 1. sup1으로 methodC 호출할 수 있을까? - 없다
// me로 methodC 호출할 수 있을까?
<예제2-3>
package com.step6;

public class Super2 extends Super1 {
	int b = 2;
	void methodB() {
		// 내 안에 선언된 변수가 아니어도 부모가 가진 변수는 호출할 수 있다
		System.out.println(a);
		System.out.println("methodB() 호출");
	}
	// super2 클래스를 상속받는 클래스에서는 methodB와 methodC를 
	public void methodC() {
		System.out.println("methodC()호출");
	}
}

<예제2-4>
package com.step6;

public class Me2 extends Super2 {
	@Override
	public void methodC() {
		System.out.println("Me2: methodC()호출");
	}
	
	public static void main(String[] args) {
		Me2 me = new Me2();
		Super2 sup1 = new Me2(); 
		Super2 sup11 = new Super2();
		System.out.println(me.a);
		// Me2타입은 Super2만 상속받았지만, 그 전에 Super1을 상속받고 있으므로 Super1에서 정의된 메소드 호출은 합법이다
		me.methodA();
		sup1.methodA();
		// 상위 클래스 타입의 인스턴스 변수로 하위 클래스에 정의된 메소드를 호출불가함
		// 만일 오버라이드 관계에 있어도 불가능한 것일까?
		sup1.methodC(); // sup1은 Super2타입인데 생성된 객체는 Me2타입이다. 그래서 헷갈린다 
		sup11.methodC(); // sup11은 Super2의 정의된 메소드가 호출됨
		me.methodC(); // Me2가 출력될 것이다
	}
}

JSON(제이슨, JavaScript Object Notation)은 속성-값 쌍(attribute–value pairs), 배열 자료형(array data types) 또는 기타 모든 시리얼화 가능한 값(serializable value) 또는 키-값 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다.
JSON의 공식 인터넷 미디어 타입은 application/json이며, JSON의 파일 확장자는 .json이다.

<오라클 예제1>
SELECT
컬럼명1, 컬럼명2,...
FROM 집합이름1, 집합이름2,....
WHERE 집합이름1.컬럼명 = 집합이름2.컬럼명

SELECT
e.empno, e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno;

-- 오라클 컬럼은 자바에서 변수이다.
-- 기본키는 not null제약조건이다. unique(유일무이)하다, 식별자 역할함, 인덱스를 제공함 - 검색 속도빠름
-- 메모장에 저장하는 것과는 뭔가 달라야 함
-- dept집합과 1:n관계형태에 있는 emp집합은 dept집합의 deptno를 받아서 태어난 집합임
-- 부서집합의 deptno은 emp집합으로 가서 외래키가 되었다.

SELECT empno FROM emp;

API

JDBC API 연동하기 - 원시적인 방법 - 생산성이 떨어짐, 코드양이 늘어남(오타)
반복되는 코드의 양이 점점 늘어난다 - 일괄처리가 불가능해진다
학습목표 - List, Map 활용 연습 + CRUD 포함 - 웹개발 게시판 수준을 8시간 이내에 처리 가능한가

ORM 솔루션 - iBatis -> MyBatis -> 전체 코딩량이 30%이상 줄어듦

Spring - JPA API - Hibernate사용함 - sql문이 없다

sql은 없지만 클래스 설계를 해야 한다
업무적인 depth가 깊어지면 조인대상 테이블이 4~5개 이상이다.
무한 루프(반복) - 재귀호출

<예제1-2. JSON>
package com.step6;

import java.util.List;
import java.util.Map;

import javax.swing.JButton;

import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.HashMap;

/*
 * 업무요청에 대한 결과가 조인이 불가피할 때 하나의 클래스로 제네릭을 사용할 수 없다
 * Map 인터페이스를 사용하는 것이 효과적임 - 키와 값으로 관리함
 * 키를 컬럼명으로 통일하면 일관성있는 변수명으로 접근이 가능함 - 속도도 빠름
 */
class Emp1{
	private int empno = 0;
	private String ename = null;
}
class Dept1{
	private String dname = null;
}

// 컬렉션 프레임워크란? 자료구조를 API로 구현한 것
// 이것들의 역할은 읽기와 쓰기, 추가로 검색기능지원
public class AddList {

	public static void main(String[] args) {
		JButton jbtnSelect = new JButton();
		// 선언부와 생성부의 이름이 다르면 다형성을 누릴 수 있다.
		// 다형성에 대한 전제조건이다.
		// 인터페이스, 추상클래스 변수명 = new 구현체클래스();
		// 재사용성을 높인다. 이식성을 좋게 함. 유연하다
		// 기존의 코드를 변경해야 한다 - 있는 걸 바꾼다 - 사이드이펙트(부수효과) 발생함
		// 이식성, 재사용성 - 객체지향 언어가 추구하는 방향성
		// 전역변수 -  클래스 중심의 코딩을 전개하기 - 중요함 - 유지됨 - 람다식과 같은 함수형에서는 사용하지 않는다 - 왜냐면 사이드이펙트
		// 지역변수 - 처리하면 그 메소드 안에서만 유지됨 - 다른 사이드이펙트 발생하지 않음.
		// 안전함 - 람다식이라는 함수형 프로그래밍 지원 가능한 이유
		// 상속받거나 구현체 클래스를 선언할 때 하위클래스를 상속받는 게 더 많은 변수와 메소드를 사용할 수 있다
		List<JButton> li = new ArrayList<>();
		// List 인터페이스의 구현체 클래스가 ArrayList이다.
		// 인터페이스는 단독으로 인스턴스화를 할 수 없다.
		// List는 row를 관리한다.
		// 제네릭 타입에는 테이블 구조에서 컬럼에 해당하는 값을 관리한다.
		// VO 패턴과 Map 타입을 사용할 수 있는데 VO타입에는 타입이 정확해서 형전환이 필요없지만
		// Map은 객체 타입으로 받기 때문에 그 값을 가지고 연산을 할 때는 형전환을 해야함(CastingException이 다수 발생가능함)
		// 제네릭 타입에는 멀티 타입을 적을 수 없어서 2개 이상의 집합을 조인했을 경우 VO타입보다는 Map을 사용하는 것이
		// 복잡도를 줄일 수 있다
		List<Map<String,Object>>list = new ArrayList<>(); // []형식을 가짐(Gson. lib 데이터 수집, 형전환, 변환) - JSON 
		Map<String,Object>map = new HashMap<>();
		map.put("empno",7782);
		map.put("ename","CLARK");
		map.put("dname","ACCOUNTING");
		list.add(map);
		System.out.println(list);
		Gson g = new Gson();
		String temp = g.toJson(list);
		System.out.println(temp);
	}
}

<자바 API를 활용하여 오라클 서버(동기화, 데이터영속성 보장)와 통신하기>
java.sql. : 커넥션 풀을 사용하지 않고...
javax.sql.
: 엔터프라이즈 서버(중간에 미들웨어 관리:EJB기술-Spring 경량서비스)가 제공하는 커넥션 풀을 사용할 때 쓰는 패키지

DB 연동하는 4단계
1. 물리적으로 떨어져 있는 서버와 연결통로를 확보하기
(전처리 부분: 각 벤더가 제공하는 드라이버 클래스를 로딩하기) - ojdbc6.jar 배포 - 운영서버에 배포시 첨부해야 함
서버의 ip주소, port, scott, tiger - 상수로 처리해서 캡슐화 해서 사용

java.sql.connection(Interface)

  1. DML문(SELECT, INSERT, UPDATE, DELETE) - 데이터 조작어
    SELECT - 단순 검색 - 물리적인 테이블에 값을 변경하지 않음 - commit, rollback 대상이 아님
    INSERT, UPDATE, DELETE는 commit과 rollback의 대상임 - 물리적인 변화가 있다
    DELETE - row가 전체 삭제 됨 - 컬럼명에 해당하는 셀만 삭제하는 것 불가함
    INSERT는 없던 row를 새로 추가함 - add

sql문을 자바로 작성하여 오라클 서버에 전달하고 그 처리를 요청함

SELECT문 - executeQuery():ResultSet(Interface-커서를 조작하는 데 필요한 메소드를 정의하고 있음)
INSERT, UPDATE, DELETE - executeUpdate():int - PreparedStatement(Interface) - 전령역할

Connection con = DriverManager.getConnection(URL, "Scott", "tiger");

PreparedStatement pstmt = con.PreparedStatement("sql문");

ResultSet rs = pstmt.executeQuery();

while(rs.next()){
Map or VO 담기 - 한 개 로우만 담을 수 있다
list.add(Map or VO)
}

<예제>
package com.step6;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
/*
 * SELECT empno FROM emp; 
    FROM emp
   WHERE empno =:x; -- 파라미터자리
   업무에 따라 집합 이름과 컬럼명만 바뀐다. 나머지는 다 그대로이다. - syntax - 문법
   
   1. parsing한다.
   2. DBMS에게 실행계획을 받아낸다.
   3. 옵티마이저가 실행계획에 따라 처리하기
   4. open..커서 갖다대고, 그 위치에 데이터 있으면 메모리 올리는 작업(fetch)-그리고 close
 */
public class Annoymous1 extends JFrame implements ActionListener {
	JButton jbtn = new JButton("조회");
	public Annoymous1() {
		jbtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				System.out.println("조회");
			} // end of actionPerformed
	});
		this.add("North",jbtn);
		this.setSize(500, 400);
		this.setVisible(true);
	}

	public static void main(String[] args) {
		new Annoymous1();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	}

}

오라클 서버에서 응답으로 오는 정보를 취득하려면 이종간이므로 오라클에서 제공하는 기능들을 추상화 해야 한다
확장성, 유지보수
구현하는 메소드가 존재함(메소드 오버라이딩)

사용한 자원은 반드시 명시적으로 반납하라 - 자바 튜닝팀 요구사항

공통코드 - 반복되는 코드를 줄임
이유는 MyBatis로 처리한다

계속해서 반복되는 코드를 찾아본다 - 개선 의지
1. 드라이버 클래스 반복이다. - insert, update, delete, select
: 저 DML에서 바뀌는 건 DML만 변경되고 컬럼명 변경됨
: 상세조회라면 WHERE empno=7566
클래스 이름: oracle.jdbc.driver.OracleDriver

<예제1-DB연동>
package com.util;

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

public class DBConnectionMgr {
	// null로 초기화하는 이유는 null 체크를 해서 null일 때만 새로 인스턴스화 하고
	// null 아니면 그냥 계속 사용하자
	static DBConnectionMgr dbMgr = null; // 왜 static인가요? - 싱글톤 패턴으로 흉내내보기
	Connection con = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	public static final String _DRIVER = "oracle.jdbc.driver.OracleDriver";
	public static final String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl11";
	public static final String user = "scott";
	public static final String pw = "tiger";
	// Calendar 클래스처럼 메소드를 통해서 객체 주입 받기
	public static DBConnectionMgr getInstance() { // 공유- 하나이다-복제본을 만들지 않겠습니다
		// 메소드를 통해서 객체생성을 하므로 if문 사용해서 조건별 객체생성이 가능해짐
		if(dbMgr==null)dbMgr = new DBConnectionMgr();
		return dbMgr;
	}
	// 리턴 타입으로 연결통로를 확보한 con을 얻는다
	// Connection(url, 계정 정보 일치 - 인증실패, 에러 코드) -> PrepareStatement(쿼리문 전달, 처리 요청함  ->
	// 앞에 객체가 주입되지 않으면 나머지 뒤에는 모두 null인 상태에 놓인다.
	public Connection getConnection()
	{
		// 예외처리시 try..catch블록을 사용하는데 멀티 블록이 가능함 : 단 하위에서 상위클래스로 처리함
		try {
			// 각 제조사의 드라이버 클래스를 로딩하기 - ojdbc6.jar - 문자열로써 객체 주입 받아낸다 - 인터페이스가 필요함
			// 그 인터페이스를 제조사가 제공해야 한다 - 노출시 - 핵심기술 유출
			Class.forName("oracle.jdbc.driver.OracleDriver"); // java reflection api 공부 - F/W 만들 수 있다
			// 물리적으로 떨어져있는 오라클 서버와 연결통로 확보
			// getConnection메소드의 원형도 static 붙어있다 - 하나다
			con = DriverManager.getConnection(url,user,pw);
		} catch(ClassNotFoundException ce) {
			System.out.println("ojdbc6.jar를 설정하지 않았다. 그래서 클래스를 못찾는다.");
		} catch (Exception e) {//비번이 틀린경우,
			e.printStackTrace();
		}
		return con;
	}
	//위 코드에서 22번과 24번 호출시 에러가 없다면 catch블록은 경유하지 않는다.
	public static void freeConnection(ResultSet rs, PreparedStatement pstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(PreparedStatement pstmt, Connection con){
		try {
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(ResultSet rs, CallableStatement cstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(CallableStatement cstmt, Connection con){
		try {
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
<예제1-2>
package com.util;

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

public class DBConnectionMgr {
	// null로 초기화하는 이유는 null 체크를 해서 null일 때만 새로 인스턴스화 하고
	// null 아니면 그냥 계속 사용하자
	static DBConnectionMgr dbMgr = null; // 왜 static인가요? - 싱글톤 패턴으로 흉내내보기
	Connection con = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	public static final String _DRIVER = "oracle.jdbc.driver.OracleDriver";
	public static final String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl11";
	public static final String user = "scott";
	public static final String pw = "tiger";
	// Calendar 클래스처럼 메소드를 통해서 객체 주입 받기
	public static DBConnectionMgr getInstance() { // 공유- 하나이다-복제본을 만들지 않겠습니다
		// 메소드를 통해서 객체생성을 하므로 if문 사용해서 조건별 객체생성이 가능해짐
		if(dbMgr==null)dbMgr = new DBConnectionMgr();
		return dbMgr;
	}
	// 리턴 타입으로 연결통로를 확보한 con을 얻는다
	// Connection(url, 계정 정보 일치 - 인증실패, 에러 코드) -> PrepareStatement(쿼리문 전달, 처리 요청함  ->
	// 앞에 객체가 주입되지 않으면 나머지 뒤에는 모두 null인 상태에 놓인다.
	public Connection getConnection()
	{
		// 예외처리시 try..catch블록을 사용하는데 멀티 블록이 가능함 : 단 하위에서 상위클래스로 처리함
		try {
			// 각 제조사의 드라이버 클래스를 로딩하기 - ojdbc6.jar - 문자열로써 객체 주입 받아낸다 - 인터페이스가 필요함
			// 그 인터페이스를 제조사가 제공해야 한다 - 노출시 - 핵심기술 유출
			Class.forName("oracle.jdbc.driver.OracleDriver"); // java reflection api 공부 - F/W 만들 수 있다
			// 물리적으로 떨어져있는 오라클 서버와 연결통로 확보 // ClassNotFoundException
			// getConnection메소드의 원형도 static 붙어있다 - 하나다. 복제 허용 안함 - 하나로 사용하고 반납하고 또 사용한다
			// getConnection메소드 호출 때문에 예외처리를 하였다. - try, catch블록
			// 이유는 URL이 존재하지 않을 경우 - 런타임에러(실행에러임) - 논리의 오류(비교연산자) - 사이드이펙트(부작용)
			// 사이드 이펙트가 발생하지 않도록 (예방코드) - 신뢰도 - 지역변수 좋다 - 람다식, arrow function
			con = DriverManager.getConnection(url,user,pw); // 파라미터가 3개다
		} catch(ClassNotFoundException ce) {
			System.out.println("ojdbc6.jar를 설정하지 않았다. 그래서 클래스를 못찾는다.");
		} catch (Exception e) {//비번이 틀린경우,
			e.printStackTrace();
		}
		return con;
	}
	//위 코드에서 22번과 24번 호출시 에러가 없다면 catch블록은 경유하지 않는다.
	public static void freeConnection(ResultSet rs, PreparedStatement pstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(PreparedStatement pstmt, Connection con){
		try {
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(ResultSet rs, CallableStatement cstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(CallableStatement cstmt, Connection con){
		try {
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
<예제1-3>
// DB 단위테스트
package com.step5;

public class DBTest {

	public static void main(String[] args) {
		DeptManager3 dm = new DeptManager3();
		dm.getDTOList();
	}

}

<SQL문>
SELECT empno, ename
FROM emp
WHERE empno =:x;

create table member1(
m_id varchar2(10) constraints member1_pk primary key,
m_pw varchar2(10) not null,
m_name varchar2(30)
);

insert into member1 values('kiwi','123','키위');

commit;

SELECT
m_name
FROM member1
WHERE m_id =:id
AND m_pw =:pw;

PrepareStatement pstmt = con.prepareStatement("select문");
--? 자리를 치환할 수 있다

0개의 댓글