본문 바로가기

프로그래밍 공부&정리/DataBase

Java에서의 프로시저 연동

** Java에서의 프로시저 연동

1. Procedure

- 프로그램에서는 한번에 수행되어야 하는 코드 블럭을 의미하는데, 함수나 메소드와 유사한 개념입니다.

- 데이터베이스에서는 자주 사용하는 SQL 구문을 하나의 이름으로 묶어서 사용할 수 있도록 해주는 개체로, 하번 호출되면 메모리에 상주합니다.

- 데이터베이스에서는 보안과 속도 때문에 사용합니다.

2. Oracle에서의 프로시저 생성과 실행

1) 생성

create or replace procedure 프로시저이름

(매개변수이름 자료형)

is

지역변수 선언

begin

수행할 SQL 구문;

end;

/

2) 실행

execute 프로시저이름(매개변수)

- 실습1

3. Java에서의 데이터베이스 연동

1) 프로젝트 build path에 데이터베이스 드라이버 파일을 추가

2) 사용할 데이터베이스 드라이버 클래스 로드

Class.forName("드라이버 클래스 이름");

3) Connection 객체를 생성

DriverManager.getConnection("데이터베이스 URL", "계정", "비밀번호");

4) Statement 객체를 생성

Connection객체.prepareStatement 또는 prepareCall;

5) sql에 물음표가 있으면 데이터 바인딩

Statement객체.set자료형(물음표번호, 실제데이터);

6) sql 실행

- select가 아닌 구문 : 정수로 받음

int 변수명 = Statement객체.executeUpdate();

- select 구문

ResultSet 변수명 = Statement객체.executeQuery();

7) 결과 사용

- select가 아닌 경우는 영향받은 행의 개수를 리턴하고

- select의 경우는 결과 셋입니다.

- next()와 get자료형(select절에서의 번호 또는 "컬럼이름")을 이용해서 결과를 사용합니다.

8) 사용한 객체 닫기

4. Java에서의 Oracle 프로시저 실행

1) PreparedStatement 대신에 CallableStatement 클래스 이용

- CallableStatement객체.prepareCall("{call 프로시저이름(매개변수만큼 ?)}"};

- 물음표에서 값 바인딩

- executeUpdate 나 executeQuery 호출


** 실습1 : dept 테이블

--dept 테이블에 데이터를 삽입하는 프로시저

create or replace procedure insertDeptProc

(vdeptno dept.deptno%type,

vdname dept.dname%type,

vloc dept.loc%type)

is

begin

 insert into dept(deptno, dname, loc) values(vdeptno, vdname, vloc);

end;

/

--만든 프로시저를 실행시키는 구문

execute insertDeptProc(13, '비서', '전주');

--dept 테이블 전체 조회

select * from dept;


--dept 테이블에 데이터를 삭제하는 프로시저: deptno를 매개변수로

create or replace procedure deletDeptProc

(vdeptno dept.deptno%type)

is

begin

delete from dept

where deptno = vdeptno;

end;

/


execute deletDeptProc(13);


select * from dept;


commit;

 


** 람다(lambda)식

- java에서 함수적 프로그래밍을 적용하기 위해 1.8버전에서 추가한 문법

- 람다는 이름없는 함수를 만들기 위한 문법입니다.

- java에서는 '하나의 추상 메소드 만을 가진 인터페이스'의 '익명객체'를 만들 때 사용할 수 있습니다.

- 람다 메소드 구현

(매개변수)->{

수행할 내용

return

}

-Thread 인터페이스 : Runnable 인터페이스

- 이 인터페이스는 public void run() 이라는 추상 메소드만을 소유하고 있습니다.

- 스레드를 만들기 위해서는 1. 인터페이스를 implements 하는 클래스를 만들고 인스턴스를 만들어서 사용하거나 2. anonymous class를 만들어서 사용하는 방법이 있습니다. 3. 추상 메소드가 1개라면 람다를 이용할 수 있습니다.


** 실습2 : 스레드 만들기 (별도의 클래스를 만들어서 사용하는 방법)

- 메인

package lambdaEx;


public class Main {


public static void main(String[] args) {

//별도의 클래스를 만들어서 이용 (재사용 할 경우 많이 사용)

RunnableImpl r = new RunnableImpl();

Thread th = new Thread(r);

th.start();

//2개 째

RunnableImpl r1 = new RunnableImpl();

Thread th1 = new Thread(r);

th1.start();

}


}


- RunnableImpl implement Runnable

package lambdaEx;


public class RunnableImpl implements Runnable {


@Override

public void run() {

//1초마다 쉬면 토마토 게임 하기 10회

int i=0;

while(i<10) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if(i%2 == 0) {

System.out.println("토");

}else{

System.out.println("마");

}

i=i+1;

}

}


}



** 실습3 : 스레드만들기(클래스를 만들지 않고 Thread 객체를 만들어서 사용)

- anonymous class 만들기 : 인스턴스는 있는데 클래스가 없다.

- 메인

package lambdaEx;


public class Main {


public static void main(String[] args) {

//익명 클래스 이용하기 : 클래스를 안 만드는 만큼 메모리 사용을 줄일 수는 있지만 재사용하기에는 불편.

Runnable r = new Runnable() {


@Override

public void run() {

// 1초마다 쉬면 토마토 게임 하기 10회

int i = 0;

while (i < 10) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if (i % 2 == 0) {

System.out.println("토");

} else {

System.out.println("마");

}

i = i + 1;

}

}

};

Thread th = new Thread(r);

th.start();


}


}

 


** 실습4 : 스레드만들기(람다를 이용한 스레드-매개변수x)

- Runnable 인터페이스에는 메소드가 1개만 존재합니다.

- 1개의 메소드만 소유한 인터페이스를 상속받고자 하는 경우에는 람다를 이용할 수 있습니다.

()->{

내용

}

- 메소드 이름을 기재하지 않기 때문에 인터페이스에 메소드가 1개만 존재해야 합니다.

-메인

package lambdaEx;


public class Main {


public static void main(String[] args) {

// 익명 클래스 이용하기 : 클래스를 안 만드는 만큼 메모리 사용을 줄일 수는 있지만 재사용하기에는 불편.

Runnable r = () ->{


// 1초마다 쉬면 토마토 게임 하기 10회

int i = 0;

while (i < 10) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if (i % 2 == 0) {

System.out.println("토");

} else {

System.out.println("마");

}

i = i + 1;

}

};

Thread th = new Thread(r);

th.start();

}


}

 


** 실습5 : 스레드만들기(람다이용-매개변수 있는 메소드 구현)

- 매개변수의 자료형은 기재할 필요가 없습니다.

- 매개변수가 하나일 때는 ()를 생략해도 됩니다.

- 아래와 같은 인터페이스가 있을 경우

interface T{

public void method(int n)

}

- 메인

package lambdaEx;



interface T{

public void method(int n);


}



public class LamdaMain {


public static void main(String[] args) {

// 위와 같은 인터페이스 T를 구현해서 사용해야 하는 경우

T t = n ->{

System.out.println("n:"+n);

};

t.method(10);


}


}

 


** 실습6 : 스레드만들기(람다이용-return 타입이 있는 메소드)

- 메소드 내에서 타입에 해당하는 데이터만 리턴하면 됩니다.

- 아래와 같은 인터페이스가 있을 경우

interface V{

public int add(int n1, int n2);

}

- 메인

package lambdaEx;


interface V{

public int add(int n1, int n2);

}



public class LamdaMain {


public static void main(String[] args) {

//인터페이스 V를 구현해서 사용해야 하는 경우

V v = (n1, n2) ->{

return n1+n2;

};

System.out.println(v.add(100, 300));


}


}

 


** 직접 인터페이스를 만들어서 람다를 사용할 일은 거의 없습니다.

- 스트림 API를 사용할 때 스트림 API의 많은 메소드들이 이미 만들어져 있는 인터페이스의 객체를 매개변수로 대입해야 동작하는 경우가 많습니다.

- 이 때 익명 클래스를 사용하는 것보다는 람다 형식을 사용하는 것을 권장합니다.

- 안드로이드 스튜디오에서는 메소드가 1개 뿐인 인터페이스의 익명 클래스를 코드 최적화를 위해서 람다 코드로 변경을 합니다.


** 표준 API 람다 인터페이스

 Consumer 인터페이스

 매개변수는 있고 리턴 값은 없는 메소드 소유

 Supplier 인터페이스

 매개변수는 없고 리턴 값만 있는 메소드 소유

Function 인터페이스 

 매개변수도 있고 리턴 값도 있는 메소드 소유 - 가공해서 리턴

Operator 인터페이스

 매개변수가 있고 리턴 값도 있는 메소드 소유 - 연산해서 리턴

 Predicate 인터페이스

 매개변수가 있고 리턴 값이 boolean인 메소드 소유 - 필터링 할 때 사용


** Stream API

- 컬렉션(배열, List, Set, 다른 언어에서는 문자열과 Map도 컬렉션으로 취급)의 데이터를 접근하는 로직과 작업을 수행하는 로직을 하나의 구문으로 처리할 수 있도록 해주는 API로 1.8버전에서 추가된 API

- 작업을 처리하는 로직은 람다를 이용해서 대입하는 것을 권장

- 컬렉션의 데이터를 반복문을 이용해서 접근하는 것보다 간결하게 작성할 수 있고 병렬처리(동시에 작업을 수행하는 것)가 쉽습니다.

1. 스트림의 특징

- 컬렉션의 모든 데이터를 접근하는 방법이 동일합니다.

- 반복문을 메소드의 내부에 숨기기 때문에 반복문을 잘못 작성하는 경우가 없습니다.

- 원본 데이터를 변경하지 않습니다.

- 1회용이라서 한 번 사용하고 나면 다시 사용할 때는 재생성해야 합니다.

2. 스트림 생성

- List 나 Set은 stream() 이나 parellelStream() 이라는 인스턴스 메소드로 생성 가능

- 배열은 Arrays.stream 이라는 메소드의 매개변수로 배열을 대입해서 생성

- 실습7 : 배열과 List를 가지고 스트림 생성하기

package streamAPIEx;


import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;


public class StreamMain0 {


public static void main(String[] args) {

//문자열 배열을 생성

String [] ar = {"카드캡터채리","원피스","명탐정코난","천사소녀네티"};

//문자열 리스트를 생성

List<String> list = new ArrayList<>();

list.add("나루토");

list.add("심슨네 가족들");

list.add("천재소년 지미");

list.add("스폰지밥");

//문자열 배열을 가지고 스트림 만들기

Stream<String> stream = Arrays.stream(ar);

//작업 수행

stream.forEach(cartoon ->{System.out.println(cartoon);});

//List를 가지고 스트림 만들기

stream = list.stream();

stream.forEach(cartoon -> {System.out.println(cartoon);});

}


}

 

3. 중간처리 메소드

- 스트림의 데이터를 변경하거나 조건에 맞는 데이터만 골라내기 위한 작업

 skip(정수)

 정수 만큼 넘어가기

 limit(정수)

 정수 만큼만 가져오기

 distinct()

 동일한 데이터를 제거하고 가져오는데 equals 메소드를 이용합니다.

 filter()

 매개변수가 1개이고 boolean을 리턴하는 람다 식을 대입하면 람다 식이 true를 리턴하는 데이터만 가져옵니다.

- 중간처리 메소드는 여러개 사용할 수 있음.

- 메인

package streamAPIEx;


import java.util.ArrayList;

import java.util.List;

import java.util.stream.Stream;


public class StreamMain1 {


public static void main(String[] args) {

List<String> list = new ArrayList<>();

list.add("떡볶이");

list.add("카레덮밥");

list.add("평양냉면");

list.add("버섯전골");

list.add("떡볶이");

list.add("매운갈비찜");

list.add("갈비탕");

list.add("알탕");

list.add("삼겹살");

list.add("곱창");

list.add("삼겹살");

list.add("라멘");

list.add("평양냉면");

list.add("소고기 타다키");

list.add("고로케");

list.add("갈비탕");

list.add("떡볶이");

//ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

//스트림 변환

Stream<String> stream = list.stream();

//모든데이터를 출력

//stream.forEach(food -> {System.out.println(food);});

//중복을 제거

//stream.distinct().skip(2).limit(3).forEach(food -> {System.out.println(food);});


//라로 시작하는 데이터만 찾아서 출력

//return 문장 하나 밖에 없을 때는 return 이라는 단어를 생략가능

//수행되는 코드가 한 줄 일 때는 {} 생략 가능

//stream.filter(food ->food.startsWith("라")).forEach(food ->System.out.println(food));

stream.filter(food ->food.length() == 3).distinct().forEach(food ->System.out.println(food));



}


}

 

- mapTo자료형(클래스이름::getter메소드) : 인스턴스의 getter 메소드의 값으로 인스턴스가 대체

- 예시

String msg = "Hello";

mapToString(String::toUpperCase): toUpperCase 메소드의 값으로 변경


'프로그래밍 공부&정리 > DataBase' 카테고리의 다른 글

Oracle(MySQL)을 이용한 회원관리  (0) 2018.09.08
[0904]MySQL  (0) 2018.09.04
[0904] 데이터베이스(MySQL)  (0) 2018.09.04
3장. 오라클 주요 함수  (0) 2018.09.03
2장. SQL의 기본  (0) 2018.08.24