---
title: "Java 정리 34"
date: "2019-01-03"
tags: ["Java"]
status: archived
verified: false
---

---

## 람다식

* jdk 1.8부터 제공하는 문법
* **interface를 편하게 사용할 수 있는 기능**
     * 구현클래스를 만들지 않고 사용하게 해줌
* **함수형 인터페이스만 사용가능**
     * **추상 메서드가 반드시 하나인 인터페이스(SAM, Single Abstract Method)**
* 간단한 body(한줄 코드)는 &#123; &#125;를 생략가능
     * 간단한 body에서는 return 생략
* 매개변수가 존재한다면 그대로 정의
     * 매개변수명은 달라도 상관없다.
     * 매개변수 데이터형을 생략가능

```java
// () - abstract method header, 식 - abstract method body
() -> 식;
```

```java
// @FunctionalInterface : 
// jdk 1.8부터 제공, 인터페이스의 추상 method가 하나인지 체크
@FunctionalInterface // Lambda식으로 편하게 사용할 수 있다.
public interface Test {
    public String getName();
}
```

```java
Test t = () -> "공선의";

System.out.println(t.getName()); // "공선의" 출력
```

```java
@FunctionalInterface
public interface Test2 {
    public void setTest(int i, int j);
}
```

```java
// 추상 method가 매개변수를 가지고 있다면 람다식에 매개변수를 정의
// 람다식에 기술되는 매개변수명은 추상 method의 매개변수명과 같을 필요는 없다.
// (i, j) 같이 매개변수 데이터형을 생략가능(타입추론)
Test2 t2 = (int i, int j) -> System.out.println(i+j);

t2.setTest(10,20); // 30이 console에 찍힌다.
```

* 구현하는 추상 메소드가 복잡하면 \&#123;\&#125;를 사용 
  
```java
@FunctionalInterface
public interface Test3 { 
     public void temp(int i); 
}
```

```java
Test3 t3 = (i) -> {
    for(int j=0; j<i; j++) {
        System.out.print(j+" ");
    }
};

t3.temp(5);    // 0 1 2 3 4 찍힘
```

* **람다식 활용예**

```java
// ()가 run()과 동일
Thread t = new Thread( () -> {  /*Override하는 run method 코드*/ } );

t.start(); // start()호출하면 위에 run()을 구현한 람다식 내용이 수행됨
```

```java
@FunctionalInterface
public interface TestLambda {
     public String today();
}
```

```java
public class UseLambda {
     public static void main(String[] args) {
           
           // TestLambda tl = () -> new Date().toString(); // return 생략가능
           // TestLambda tl = () -> { return new Date().toString(); };
           // return 기술시 중괄호 필요({})
           // abstract method 내의 코드가 복잡(여러줄)한  경우에는 {}를 반드시 기술
           TestLambda tl = () -> {
                SimpleDateFormat sdf = new  SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.format(new Date());
           };

           System.out.println(tl.today());
     }
}
```

```java
public class UseLambda3 {
     
     public static void main(String[] args) {
           
           Thread t = new Thread(() -> {
                for(int i=0; i<1000; i++) {
                     System.out.println(i);
                }
           });
           
           t.start();
     }
}
```

---

## JDBC

![01](/md/legacy-assets/java/34/01.webp)

* **JDBC (Java DataBase Connectivity)**
  * 사용자는 프로그램의 사용방법만 알면 DB 쿼리문을 몰라도 됨
  * **Java와 DBMS를 연동하는 기술**
* 저수준 API 제공
* **Driver Loading 방식**
     * Driver가 제공된다면 모든 RDBMS와 연동할 수 있다.
     * Driver는 DB제조사(Vendor)에서 제작 제공
     * Type1 Driver만 Sun사에서 제작하여 제공
* **java.sql 패키지**에서 관련 클래스, interface를 제공
* **Driver는 외부 jar파일**
     * 오라클 설치했던 곳을 찾아보면 driver들이 존재
     * **ext 폴더에 넣어 사용**
          * path를 설정하지 않아도 사용 가능
          * 간편하나 필요없는 jar까지 로딩하여 실행(무거워짐)
               * 권장하지 않는 방법
     * **class path 설정하여 사용**
          * CUI로 자바개발시
     * **build path 설정하여 사용**
          * eclipse 사용시

![02](/md/legacy-assets/java/34/02.webp)

---

## JDBC 드라이버 종류

* **Type1 Drvier** 
  * **Windows OS에서 DB와 연결한 객체를 사용하는 것**
  * DB와 연결한 객체 : **ODBC(Open DataBase Connectivity)**
  * JDBC-ODBC bridge driver
  * Windows 전용
  * 속도가 가장 느리지만 연결이 편하다

![03](/md/legacy-assets/java/34/03.webp)

* **Type2 Native API Driver**
  * **DB와 Java가 각각 독립적인 프로토콜을 가진 Driver**
    * 구현하는 언어가 다를 수 있다
  * **OCI(Fat Driver)** : DBMS 모든 기능 사용가능

![04](/md/legacy-assets/java/34/04.webp)

* **Type 3 Middleware Driver**
  * 분산시스템
  * 미들웨어는 장비, OS 등이 가능

![05](/md/legacy-assets/java/34/05.webp)

* **Type 4 Net Protocol Pure Java Driver**
  * **순수 자바 드라이버**
  * **Thin Driver** : DBMS의 모든 기능을 사용할 순 없음
    * 대표적으로 프로시저 호출가능, 다만 만들 순 없음

![06](/md/legacy-assets/java/34/06.webp)

---

## Oracle JDBC Driver 설정

![07](/md/legacy-assets/java/34/07.webp)

* 오라클 설치된 경로에서 ojdbc5.jar, ojdbc6.jar를 복사
  * java jdk 버전에 따라 다른 driver를 사용

![08](/md/legacy-assets/java/34/08.webp)

* 사용할 Driver Class는 oracle.jdbc.OracleDriver
* 세 가지 방법으로 설치가능
* **첫번째 java jdk jre lib ext에 복붙하는 방법**
    * ext에 외부 jar파일을 많이 넣으면 JVM이 무거워짐
    * JDBC 사용 안하는 프로젝트들도 해당 jar를 갖고 실행됨
    * 권장안하는 방법

![09](/md/legacy-assets/java/34/09.webp)

* **두번째 eclipse에서 프로젝트 build path 설정하는 방법**
  * 프로젝트 선택, Add External JARs로 ojdbc6.jar 선택, Apply
  * Package Explorer에서 Referenced Libraries로 추가된 ojdbc6.jar 확인 가능
  * 다만 eclipse에서만 설정이 됨, cmd로 컴파일된 class파일 실행 시 에러발생

![10](/md/legacy-assets/java/34/10.webp)

![12](/md/legacy-assets/java/34/12.webp)

* **마지막 방법 배치파일로 classPath 설정하기**
  * **eclipse의 build path = classpath**
  * path구분자로 세미콜론사용
  * "."을 사용하여 JVM이 실행되는 하위패키지내 클래스를 인식하게 함

```bash
## env.bat에 다음 classpath내용 추가
rem path - 특정프로그램(javac.exe, java.exe)를 설치된 경로에 상관없이 사용하기위한 path
rem xxx_home - 프로그램끼리 경로를 참조하기 위해 설정하는 path
rem classpath - 특정 class, library, Framework 등을 경로에 상관없이 사용하기위해 설정하는 path

set dev_home=C:\Users\owner\youngRepositories\SSangYoung\dev
set java_home=%dev_home%\Java\jdk1.8.0_191
set eclipse_home=%dev_home%\eclipse

set path=%java_home%\bin;%eclipse_home%

rem classpath를 설정하면 설정된 클래스만 인식하게된다.
rem JVM이 실행되는 하위패키지내 클래스를 인식하게 할때에는 "."을 사용한다.
set classpath=.;%dev_home%\drivers\ojdbc6.jar
```

![11](/md/legacy-assets/java/34/11.webp)

---

## JDBC에 사용되는 클래스와 인터페이스

* **class**
  * **Class, DriverManager**
    * **Class** : JVM 외부의 클래스(Driver)를 객체로 만들어 JVM에 올려 놓는 일
    * **DriverManager** : 로딩된 드라이버를 사용하여 DB와 연결한 후 연결객체를 반환하는 일
* **interface**
  * **Connection, Statement, PreparedStatement, CallableStatement, ResultSet**
    * **Connection** : 연결관리, Transaction 처리, 쿼리문 생성 객체 얻는일
    * **Statement, PreparedStatement, CallableStatement** : 쿼리문을 실행하여 결과를 얻는 일
         * **Statement, PreparedStatement** : 쿼리 실행
         * **CallableStatement** : Procedure 실행
    * **ResultSet** : cursor의 제어권을 받아 여러행을 조회

---

## JDBC 코딩 순서

1. JVM에 드라이버 로딩
2. DBMS 연결 얻기
3. 쿼리문 생성 객체 얻기
4. 쿼리 수행 후 결과 얻기
5. 연결 끊기

![14](/md/legacy-assets/java/34/14.webp)

* **먼저 Driver Loading**
  
```java
// ojdbc6.jar안에 들어있는 OracleDriver를 로딩
Class.forName("oracle.jdbc.OracleDriver");
```

* **로딩된 드라이버를 사용하여 Connection 얻기**

```java
String url = "jdbc:oracle:thin:ipaddress:port:sid";
// port 1521, sid는 orcl로 oracle설치시 설정했었음
String id = "scott";    // DBO(DataBase Owner)의 id
String pw = "tiger";  // DBO의 pw
// DB를 가지고 있는 계정으로 접근하여 DB를 사용하는 것(DBA 아님)

Connection con = DriverManager.getConnection(url, id, pw);
```

* **쿼리문 생성객체 얻기**

```java
Statement stmt = con.createStatement();
```

* **쿼리문 실행후 결과 얻기**
  * DB 변경 : CREATE, DROP, TRUNCATE, ALTER, GRANT, REVOKE, COMMIT, ROLLBACK, INSERT, UPDATE, DELETE
  * DB 변경 X : SELECT
    * CREATE, DROP, TRUNCATE, ALTER, GRANT, REVOKE, COMMIT, ROLLBACK들은 반환형이 boolean
       * execute()
    * INSERT, UPDATE, DELETE들은 반환형이 int
       * excuteUpdate() 
    * SELECT 반환형은 ResultSet
       * executeQuery()

```java
String sql = "INSERT INTO 테이블명 VALUES('1','2''3')";

int cnt = stmt.executeUpdate(sql);
if (cnt == 1) {
    System.out.println("추가 성공");
}
```


* **연결 끊기**
  * 가장 중요
  * finally에서 끊어준다

```java
if (stmt != null) { stmt.close(); }
if (con != null) { con.close(); }
```

```java
// JDBC(Java DataBase Connectivity)를 사용하여 DBMS의  Connection을 얻기
public class UseConnection {
     public UseConnection() throws SQLException {
           // 1. Driver Loading
           try {
                Class.forName("oracle.jdbc.OracleDriver");
                System.out.println("드라이버 로딩 성공");
           } catch (ClassNotFoundException cnfe) {
                cnfe.printStackTrace();
           }
           
           // 2. 로딩된 드라이버를 사용하여 DB연동 Connection  얻기
           String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
           String id = "scott";
           String pw = "tiger";
           
           Connection con = null;
           Statement stmt = null;
           try {
                con = DriverManager.getConnection(url, id, pw);
                System.out.println("DB 연결 얻기 성공 : " +  con);
                
                // 3. 쿼리문 생성객체 얻기
                stmt = con.createStatement();
                
                // 4. 쿼리문 실행 후 결과 얻기
                String insertQuery = "INSERT INTO  CP_EMP2(empno,ename,hiredate,sal) "
                           +  "VALUES(1234,'공선의',SYSDATE,3000)";
                int cnt = stmt.executeUpdate(insertQuery);
                System.out.println(cnt+"건 추가 성공");
                
           } finally { // 5. 연결 끊기(중요) finally로 끊는다.
                if (stmt != null) {
                     stmt.close();
                }
                if (con != null) {
                     con.close();
                }
           }
     }
     
     public static void main(String[] args) {
           try {
                new UseConnection();
           } catch (SQLException e) {
                e.printStackTrace();
           }
     }
}
```

![13](/md/legacy-assets/java/34/13.webp)

---

## Quantum Database Utility 이클립스 플러그인 설치

* SourceForge에서 Quantum Database Utility 다운로드 후 압축풀기
  * https://sourceforge.net/projects/quantum/
  * 이클립스 설치된 폴더와 동일한 폴더들 존재, 그대로 덮어쓰기, 재시작
  * Perspective보면 Quantum DB가 추가되어 있음

![15](/md/legacy-assets/java/34/15.webp)

* 다른 DB Client 프로그램을 번갈아가며 안써도 되어 생산성 향상에 좋다.

![16](/md/legacy-assets/java/34/16.webp)
