2010년 7월 30일 금요일

Spring에서 파일을 포함한 Form 을 전송하고 업로드 하기


1. 먼저 form 태그에 다음의 프로퍼티를 추가한다.

 

enctype="multipart/form-data"

인코딩 타입이 Multipart 인 경우 파라미터나 업로드한 파일을 구할려면 전송 데이터를 알맞게 처리해 주어야 한다. 스프링은 Multipart 지원 기능을 제공하고 있기 때문에, 이 기능을 이용하면 추가적인 처리 없이 Multipart 형식으로 전송된 파라미터와 파일 정보를 쉽게 구할 수 있다.

 

2. MultipartResolver 설정

 

<bean id="multipartResolver"

 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

</bean>

Multipart 지원 기능을 사용하려면 먼저 MultipartResolver를 스프링 설정파일에 등록해 주어야 한다. MultipartResolever 는 Multipart 형식으로 데이터가 전송된 경우, 해당 데이터를 스프링 MVC 에서 사용할 수 있도록 변환해준다.

 

라이브러리에 다음을 추가한다.

 

commons-fileupload / commons-fileupload

commons-io            / commons-io            <- 1.4 version

 

2.1. MultipartResolver의 Property

 Property  Type  Descript
 maxUploadSize  long  최대 업로드 가능한 바이트 크기. -1 은 체한이 없음을 의미한다, Default 는 -1
 maxInMemorySize  int  디스크에 임시 파일을 생성하기 전에 메모리에 보관할 수 있는 최대 바이트 크기, 기본값은 10240 바이트이다.
 defaultEncoding  String  요청을 파싱할 때 사용할 캐릭터 인코딩. 지정하지 않을 경우 HttpServletRequest.setCharacterEncoding() 메서드로 지정한 캐릭터 셋이 사용된다. 아무 값도 없을 경우 ISO-8859-1을 사용한다.

 

 

3. Controller 에서 데이터 받아오기.

 

컨트롤러의 파라미터에 값을 받아 넣을 때 다음의 소스를 입력한다.

@RequestParam("[inputName]") MultipartFile [paramName]

 

다음은 MultipartFile 인터페이스가 제공하는 주요 메서드 이다.

 

 Method  Descript
 String    getName()  파라미터의 이름을 구한다.
 String    getOriginalFilename()  업로드 한 파일의 이름을 구한다.
 boolean isEmpty()  업로드 한 파일이 존재하지 않는 경우 true를 리턴한다.
 long      getSize()  업로드 한 파일의 크기를 구한다.
 byte[]   getBytes() throws IOException  업로드 한 파일의 데이터를 구한다.
 InputStream getInputStream() throws IOException

 업로드 한 파일 데이터를 읽어오는 InputStream을 구한다,

 InputStream의 사용이 끝나면 알맞게 종료해 주어야 한다.

 void      transferTo(File dest) throws IOException  업로드 한 파일 데이터를 지정한 파일에 저장한다.

 

if (multipartFile.isEmpty)) {

//업로드 한 파일데이터를 구하는 가장 단순한 방법은 MultipartFile.getBytes() 메서드를 이용하는 것이다. 바이트 배열을 구한 뒤에 파일이나 DB 등에 저장하면 된다.

   byte[] fileData = multipartFile.getByte();

   ...

}

 

if (multipartFile.isEmpty)) {

//업로드 한 파일 데이터를 특정 파일로 저장하고 싶다면 MultipartFile.transferTo() 메서드를 사용하는 것이 편리하다.

   File file = new File(fileName);

   multipartFile.transferto(file);

   ...

}

 

 

 

Validation Check

Validation Check 는 Data의 검증을 뜻한다.

 

Validation Check의 방법에는 크게 3가지 가 있는데

 

    1. Client-Side VC : UI에서 JS를 이용해 체크한다.
    2. Server-Side VC : Java 에서 체크한다.
    3. Database Constraint VC : Key, check, Default 등으로 체크 한다.

위 세가지중 하나라도 배제한다면 잘못된 프로그래밍 습관을 가진것이다.

2010년 7월 29일 목요일

Integer 타입에서 자주 쓰는 API

1. 숫자를 문자로 변환하기.

입력되거나 변수에서 초기화 또는 대입된 숫자를 문자로 바꿀 수 있다.

  1. 문자변수 = Integer.toString(숫자 또는 숫자변수) // 숫자 또는 숫자변수를 문자변수에 형을 변환해서 저장한다.

Spring 타입에서 자주 쓰는 API

1. String 을 숫자로 변환하기.

int num = Integer.parseInt(문자);

 

숫자를 문자로 변환하거나, nextLine() 으로 입력받은 문자를 숫자로 변환하고자 할때 사용된다.

즉, 문자 부분에 들어갈 수 있는 것은 두가지가 있다.

순수한 문자열 또는 Scanner 가 있다.

 

2. 문자열 비교하기.

Scanner 로 입력받은 문자열은 단순한 문자열로는 비교할 수 없다.

하여 Scanner 로 입력받은  문자열은 String 타입의 특정 메서드를 사용하는데

종류는 크게 3가지가 있다.

  1. String.compareTo(문자)  // 문자와 문자사이에 존재하는 문자의 개수를 리턴한다. 즉, 반환값이 0이라면 같은 문자열이다.

  2. String.equals(문자) // 문자와 문자를 순수히 비교한다. 같다면 true, 틀리면 false 를 반환한다.

  3. String.equalsIgnoreCase(문자) // 문자와 문자를 비교하는데 대소문자 구분을 하지 않는다. 다시말하면 equals 는 대소문자를 구분한다.

 

3. 문자 추출하기

문자열은 앞의 문자와 뒤의 문자를 비교할 수 있다. 또한, 시작 위치를 지정하고 추출할 길이를 추출하면 해당 길이만큼의 문자를 추출해낼 수 있다.

  1. String.startsWith(문자) // String 이 문자로 시작하는지 판단한다. 참이라면 true, 거짓이면 false 를 반환한다.

  2. String.endsWidth(문자) // String 이 문자로 끝나는지 판단한다. 참이라면 true, 거짓이면 false 를 반환한다.

  3. String.subString(시작위치, 마지막위치) // String 에서 시작위치부터 마지막 위치까지의 문자열을 반환한다.

  3. 예제 abcdefg.subString(0, 3) =>> abc

Toad 단축키

toad사용법

 SQL EDITOR상에서의 편리한 단축키

ESC: 열린 윈도우 닫기
F1: 모든 단축키를 보여준다.
F2: FULL SCREEN
F4: Table, View, Proc, Funct, Package를 DESC(테이블명에 커서를 둔 상태에서 해야함)
F6: SQL Editor와 결과창간의 전환
F7: 화면을 모두 CLEAR
F8: 실행했던 SQL들의 HISTORY
F9: 모든 쿼리 실행(Ctrl+Enter는 현재 쿼리만 실행)
Ctrl+F9: 실제 쿼리를 실행하지 않고 validate함
Ctrl+. : table Completion (매칭되는 테이블목록 출력)
Ctrl+T : Columns Dropdown (해당테이블의 컬럼목록 표시)
Alt+Up : History Up (리눅스 bash의 UP키와 같다.)
Alt+Down: History Down (리눅스 bash의 DOWN키와 같다.)
Ctrl+Tab: MDI Child윈도간 전환

그냥 'desc 테이블명' 을 치면, 팝업윈도로 해당 테이블의 컬럼목록윈도가 표시된다.
이때, 해당 컬럼을 double-click하면 SQL Editor로 반영된다.

"테이블명."까지 입력하고 좀 있으면, 해당 테이블의 컬럼목록이 표시된다.
마치 프로그래밍툴에서 클래스내 멤버들의 목록을 표시하듯이..
Ctrl+T는 출력된 목록을 취소했을 경우, 다시 불러낼때 쓰인다.

test, member 2개의 테이블이 있다고 하자.
select * from t까지 입력하고 Ctrl+.를 치면 select * from test로 테이블명을 완성시켜준다.
system계정에서는 안되더군.. 일반계정만 가능했다.

SQL문을 실행시

Ctrl+Enter
현재 커서의 SQL문 실행
여러개의 SQL문이 있을때, SQL문들을 개행문자로 분리해주면 된다.
해당 커서에서 개행문자가 있는 곳까지만 하나의 SQL문으로 간주한다.

F9
SQL Editor의 SQL문 실행하여 Grid에 출력.
여러 SQL문들을 개행문자로 구분하지 않는다는 것을 제외하면, 위의 Ctrl+Enter와 동일하다.
에디터내의 모든 SQL문은 하나로 취급하므로, 여러 개의 SQL문이 있으면 실행할 SQL문만 Selection하여 실행(F9)해준다.

F5
SQL Editor내의 모든 SQL문 실행. 여러개의 SQL문들을 모두 실행하여 SQL*PLUS와 같이 출력해준다.
이것은 출력이 Grid로 표시되지 않고 Editor윈도에 표시되므로, SQL*PLUS의 출력과 같이,
다른 편집기로의 복사/붙여넣기 할때 사용하면 유용하다.

Oracle 페이징 쿼리

페이징 기법이란

데이터가 100건이 있다고 가정한다면, 한페이지당 10개씩 보여줄수 있게하는 기법을 말합니다.

1페이지에는 0~10까지. 2페이지에는 11~20 까지.. 10페이지에는 91~100 까지의 레코드를 보여주는 것을 말합니다.

 

아래는 페이징 기법을 구현할 수 있는 쿼리문입니다.

 

 

오라클에서 paging을 처리하기 위해서는 오라클에서 제공되는 rownum을 사용하게 됩니다.

하지만 rownum을 잘못알고 사용을 하게 되면 저처럼 삽질을 계속 하게 된다는 ^^;;

예를들면...
  SELECT *
  FROM (
            select board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE ROWNUM >= 1 AND ROWNUM <= 10

  이렇게 쿼리문을 날리면 데이터가 나옵니다.

  하지만 ..

  SELECT *
  FROM (
            select board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE ROWNUM >= 11 AND ROWNUM <= 20

   이렇게 쿼리문을 날렸을때 그냥 보기에는 나올것 같습니다. 하지만 아무런 데이터가
   나오지를 않습니다.^^; 아주 황당합니다.

그래서 많이쓰는 방법으로... 첫번째..

  SELECT *
  FROM (
            select rownum as rnum, board_seq, board_name, insert_date
            from t_board
            order by insert_date desc
            )
   WHERE rnum>= 11 AND rnum <= 20

  서브쿼리에서 rownum을 구해 동일한 방법으로 where 조건을 주면 아주 잘 나옵니다.

또다른 방법.. 두번째..

  row_number() over(정렬을 위한 order by) 를 사용하면 됩니다.

  SELECT *
  FROM (
            select row_number() over(order by insert_date desc) as rnum, board_seq,
                     board_name, insert_date
            from t_board
            )
   WHERE rnum>= 11 AND rnum <= 20

첫번째 방법과 두번째 방법을 했을경우 결과는 동일합니다.

차이점이 있다면 두번째 방법에서 row_nuber() over()를 이용해서 over()안에 있는
order by 순으로 rownum을 새롭게 구하는것입니다.

* 참고 : row_number()는 오라클 8.1.6.0.0 이상에서 사용이 가능합니다.

EOF, BOF(RecordSet)

EOF, BOF란?

EOF는 End Of File의 약자로 커서가 레코드의 제일 마지막에 위치해있는것을 말합니다.

이때 레코드의 마지막에 커서가 위치해있다면 True를 반환하게 되며, 그렇지 않을경우는 False를 반환하게됩니다.

 

 Field Field Field EOF
 Record  Record  Record  False
 Record  Record  Record  False
       True

 

위의 표처럼 필드내에 레코드가 있다면 EOF는 False를 반환하게 됩니다.

반면, 필드내에 레코드가 없다면 True를 반환하게 됩니다.

 

데이터베이스는 모든 필드마다 여분의 셀(cell)을 두고 있습니다.

레코드가 앞으로 얼마나 더 추가가 될지 모르기때문에 그에 대비하여 여분의 레코드를 두게 되는데

커서가 여기에 위치할경우 EOF = True 를 반환하게 됩니다.

 

BOF는 어떻게 될까요?

BOF는 Begin Of File의 약자로 커서가 레코드의 제일 첫 행에 위치해있을 경우를 말합니다.

커서가 제일 첫 행에 위치할경우 True를 반환하고, 그렇지 않을 경우 False를 반환합니다.

 

1.

 Field Field Field BOF
 Record  Record  Record False
 Record  Record  Record
       

 

2.

 Field Field Field EOF



True