finerss's world!

Oracle 날짜함수

공부2011. 8. 8. 16:30

날짜함수

1)오라클의 날짜 형식

우선은 날짜 함수를 들어가기전에 오라클의 날짜 형식이 어떻게 구성되나 알아보도록 하겠습니다.
오라클은 날짜를 아래와 같이 내부적인 숫자 형식으로 관리됩니다.

Centry.year.month.day.hours.minutes.seconds

기본적으로 입력되는 형식 및 display 형식은 \'\'\'\'DD-MON-YY\'\'\'\' 이며,
유효날짜는 January 1,4712 B.C ~ December 31,4712 A.D 사이입니다.
머 여러분들이 사용하시기엔 무리없는 (^^;) 날짜겠져..

또한 오라클에서는 현재 날짜와 시간을 리턴해주는 날짜 함수가 있습니다.
아마 앞으로도 자주 사용하시겠지만, SYSDATE 란 함수입니다.
이함수를 DUAL (저번 강의때 설명했던걸로 기억나는데요, 잘 모르시는 분은 이전강의를 참고해주세요..^^)
을 사용하면 현재의 날짜를 확인하실 수 있습니다.

SQL> SELECT SYSDATE FROM DUAL;

SYSDATE
--------
03/11/27

2) 날짜와 숫자의 계산
위에서 날짜는 숫자 형식으로 관리 된다고 했죠? 그래서 날짜와 날짜끼리
날짜와 숫자끼리의 연산이 가능합니다.
그 연산된 결과는 아래와 같습니다.

2-1) 날짜 - 날짜 = 숫자
날짜에서 날짜를 빼면 그 날짜사이의 일 수가 나옵니다.
오랜만에 emp table을 함 예로들어볼께요?
emp Table의 입사일을 기준으로 사람들이 입사한 기간이 얼마나 되나 함 알아볼까요?

SQL> SELECT ENAME, HIREDATE, SYSDATE - HIREDATE
2 FROM EMP;

ENAME HIREDATE SYSDATE-HIREDATE
---------- -------- ----------------
SMITH 80/12/17 8380.01446
ALLEN 81/02/20 8315.01446
WARD 81/02/22 8313.01446
JONES 81/04/02 8274.01446
MARTIN 81/09/28 8095.01446
BLAKE 81/05/01 8245.01446
CLARK 81/06/09 8206.01446
SCOTT 87/04/19 6066.01446
KING 81/11/17 8045.01446
TURNER 81/09/08 8115.01446
ADAMS 87/05/23 6032.01446
JAMES 81/12/03 8029.01446
FORD 81/12/03 8029.01446
MILLER 82/01/23 7978.01446

위의 결과에서와 같이 SMITH와 같은 경우는 입사한지 현재일 기준으로 8380일이 지났음을 알수 있습니다.

2-2) 날짜 + 날짜 => 에러 발생
날짜와 날짜끼리는 더하기가 안됩니다.

SQL> SELECT ENAME, HIREDATE, SYSDATE + HIREDATE
2 FROM EMP;
SELECT ENAME, HIREDATE, SYSDATE + HIREDATE
*
1행에 오류:
ORA-00975: 날짜와 날짜의 가산은 할 수 없습니다

2-3) 날짜 + 숫자 = 날짜
날짜에 숫자를 더하면 해당 날짜에 숫자만큼의 기간이 더해집니다. (2003/11/27일에 테스트한것입니다.)

SQL> SELECT SYSDATE + 2 FROM DUAL;

SYSDATE+2
--------
03/11/29

2-4) 날짜 - 숫자 = 날짜
날짜에 숫자를 빼면 해당 숫자만큼의 기간이 빼져서 나오게 됩니다.
SQL> SELECT SYSDATE + 2 FROM DUAL;

SYSDATE-2
--------
03/11/25



그러면 본격적으로 날짜 함수에 대해서 들어가 볼까요?

2) 날짜 함수
가) ADD_MONTHS : 주어진 일자에 개월 단위의 가감을 원할때 사용합니다.

EMP 테이블에서 SIMTH 직원의 입사일을 가지고 예를 들어보겠습니다.
입사일을 두달씩 더하고 빼보겠습니다.

1 SELECT ENAME, HIREDATE,
2 ADD_MONTHS(HIREDATE, 2),
3 ADD_MONTHS(HIREDATE, -2)
4 FROM
5 EMP
6 WHERE
7* ENAME = \'\'\'\'SMITH\'\'\'\'
SQL> /

ENAME HIREDATE ADD_MONT ADD_MONT
---------- -------- -------- --------
SMITH 80/12/17 81/02/17 80/10/17

결과를 보시면 알지만 SMITH 직원의 입사일은 80년 12월 17일 이지만 ADD_MONTHS 함수를 이용하여 2달을 더하면
81년 2월 17일 두달을 빼면 80년 10월 17일이 나옴을 확인할 수 있습니다.

나) MONTHS_BETWEEN : 주어진 두개의 일자 간격이 몇 개월인지를 보여줍니다.

EMP 테이블에서 입사일자가 현재 일자로부터 몇개월이 됐는지 알아보겠습니다.

SQL> SELECT ENAME, HIREDATE, SYSDATE, MONTHS_BETWEEN(SYSDATE, HIREDATE)
2 FROM EMP;

ENAME HIREDATE SYSDATE MONTHS_BETWEEN(SYSDATE,HIREDATE)
---------- -------- -------- --------------------------------
SMITH 80/12/17 03/12/10 275.806019
ALLEN 81/02/20 03/12/10 273.709244
WARD 81/02/22 03/12/10 273.644728
JONES 81/04/02 03/12/10 272.289889
MARTIN 81/09/28 03/12/10 266.45118
BLAKE 81/05/01 03/12/10 271.322148
CLARK 81/06/09 03/12/10 270.064083
SCOTT 87/04/19 03/12/10 199.741502
KING 81/11/17 03/12/10 264.806019
TURNER 81/09/08 03/12/10 267.096341
ADAMS 87/05/23 03/12/10 198.61247

ENAME HIREDATE SYSDATE MONTHS_BETWEEN(SYSDATE,HIREDATE)
---------- -------- -------- --------------------------------
JAMES 81/12/03 03/12/10 264.257631
FORD 81/12/03 03/12/10 264.257631
MILLER 82/01/23 03/12/10 262.61247

다) LAST_DAY : 주어진 일자가 포함된 월의 말일을 알수 있습니다.

현재날짜를 (2003-12-10) 통해서 월말이 어떻게 되는지 확인해보도록 하겠습니다.

SQL> SELECT SYSDATE, LAST_DAY(SYSDATE) FROM DUAL;

SYSDATE LAST_DAY
-------- --------
03/12/10 03/12/31

말일이 12월 31일임을 알 수 있습니다.

라) SYSTIMESTAMP : DATABASE의 TIMEZONE을 포함한 시스템 날짜를 보여준다.

SQL> SELECT SYSTIMESTAMP FROM DUAL;

SYSTIMESTAMP
---------------------------------------------------------------------------
03/12/11 00:07:32.000001 +09:00

바) NEXT_DAY

SYNTAX : NEXT_DAY (DATE, CHAR)

DATE : 일자
CHAR : 요일을 말합니다.(월/화/수/목/금/토/일) 위에 월요일 이렇게 해도 상관없습니다.
이것은 DATABASE의 LANGUAGE 와 관련있습니다.
지금 제가 테스트 하는 것은 한글로 셋팅되어 있기 때문에 가능한거구여...
영문으로 셋팅되어 있으면.. MONDAY,TUESDAY.... 머 이렇게 되어야겠져..^^

NEXT_DAY는 입력한 DATE(일자) 다음 주 입력한 요일의 일자를 보여줍니다.

아래의 예를 보면 12월 10일 다음주 목요일의 날짜를 보여주는 것입니다.

설명하려니 좀 어렵네여..ㅋㅋ 아래의 예를 보면 쉽게 이해되실듯..ㅋㅋ

SQL> SELECT NEXT_DAY(SYSDATE,\'\'\'\'목요일\'\'\'\') FROM DUAL;

NEXT_DAY
--------
03/12/18

2. 변환함수
: 오라클에서는 문자와 숫자, 문자와 날짜간의 데이터형 변환을 위해 함수를 제공합니다.
숫자나 날짜가 문자로 변환되는데 필요한 함수가 TO_CHAR 이며,
문자가 숫자로 변형될때는 TO_NUMBER,
문자가 일자로 변형될 때 TO_DATE를 사용합니다.
그럼 예제를 통하여 자세히 알아보겠습니다.

1) TO_CHAR : 날짜를 문자로 바꾸어줍니다.

SYNTAX : TO_CHAR (DATE, FORMAT)

FORMAT은 DATE형을 문자로 바꿀때 쓰이는 변환 형식을 말합니다.
자주쓰이는 것에 대해서 예와 함께 설명하도록 하겠습니다.

가) YYYY 또는 SYYYY : 년도, S를 지정하면 기원전 년도에 - 가 붙음.

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'YYYY\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'SYYYY\'\'\'\')
2 FROM DUAL;

TO_CHAR(SYSDATE, \'\'\'\'YYYY\'\'\'\') TO_CHAR(SYSDATE, \'\'\'\'SYYYY\'\'\'\')
------------------------ ---------------------------
2003 2003

나) YYY, YY, Y : 년의 아래 3자리, 2자리, 1자리를 나타냅니다.
SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'YYY\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'YY\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'Y\'\'\'\')
2 FROM DUAL;

TO_ TO T
--- -- -
003 03 3

다) SYEAR, YEAR : 년도를 철자로 나타냅니다.

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'SYEAR\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'YEAR\'\'\'\') FROM DUAL;

TO_CHAR(SYSDATE,\'\'\'\'SYEAR\'\'\'\') TO_CHAR(SYSDATE,\'\'\'\'YEAR\'\'\'\')
--------------------------------- ---------------------------------
TWO THOUSAND THREE TWO THOUSAND THREE

라) Q : 입력일자의 분기를 나타냅니다.
SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'Q\'\'\'\') FROM DUAL;

T
-
4

마) MM : 월을 나타냅니다.
SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'MM\'\'\'\') FROM DUAL;

TO
--
12

바) MONTH, MON : 월의 명칭, 3문자의 단축형을 나타냅니다.
SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'MONTH\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'MON\'\'\'\') FROM DUAL;

TO_CHAR(S TO_
--------- ---
DECEMBER DEC

사) DDD, DD, D : 년, 월, 주의 몇번째 날인가를 보여줌

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'DDD\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'DD\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'D\'\'\'\') FROM DUAL;

TO_ TO T
--- -- -
345 11 5

아) DAY, DY : 요일 또는 3문자의 단축형

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'DAY\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'DY\'\'\'\') FROM DUAL;

TO_CHA TO
------ --
목요일 목

자) AM, PM : 오전 / 오후를 표시한다.

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'AM\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'PM\'\'\'\') FROM DUAL;

TO_C TO_C
---- ----
오전 오전

차) HH, HH12 : 시각 (1-12)

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'HH\'\'\'\'), TO_CHAR(SYSDATE, \'\'\'\'HH12\'\'\'\') FROM DUAL;

TO TO
-- --
12 12

카) HH24 : 시각 (0-23)

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'HH24\'\'\'\') FROM DUAL;

TO
--
00

타) MI : 분

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'MI\'\'\'\') FROM DUAL;

TO
--
34

하) SS : 초

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'SS\'\'\'\') FROM DUAL;

TO
--
57

물론 위의 포멧을 적절히 조합시킬 수 있습니다.
현재 시스템 날짜의 년월일 시분초 까지 한번 나타내도록 하겠습니다.

SQL> SELECT TO_CHAR(SYSDATE, \'\'\'\'YYYY/MM/DD HH24:MI:SS\'\'\'\') FROM DUAL;

TO_CHAR(SYSDATE,\'\'\'\'YY
-------------------
2003/12/11 00:36:27

2) TO_CHAR (NUMBER, FORMAT) : 숫자를 문자로 변환할때도 TO_CHAR 함수를 사용합니다.
숫자용 포멧은 아래와 같습니다.

가) 9 : 숫자 출력
나) 0 : 숫자 앞에 0 표시
다) . : 소수점 자리 표시
라) , : 지정한 위치에 , 표시
마) $ : 달러 표시
바) L : 국가별 화폐단위표시
사) MI : 오른쪽에 마이너스 표시


그럼 위의 포멧을 적용한 예를 살펴보겠습니다.

SQL> SELECT
2 TO_CHAR(1234,\'\'\'\'09,999\'\'\'\'),
3 TO_CHAR(1234.56,\'\'\'\'99,999.99\'\'\'\'),
4 TO_CHAR(1234,\'\'\'\'$99,999\'\'\'\'),
5 TO_CHAR(1234,\'\'\'\'L99,999\'\'\'\'),
6 TO_CHAR(-1234,\'\'\'\'99,999MI\'\'\'\')
7 FROM DUAL;

TO_CHAR TO_CHAR(12 TO_CHAR( TO_CHAR(1234,\'\'\'\'L99 TO_CHAR
------- ---------- -------- ----------------- -------
01,234 1,234.56 $1,234 ₩1,234 1,234-

3) TO_NUMBER(CHAR, FORMAT) : 숫자로 변환가능한 문자열을 숫자로 변환시켜줍니다.
FORMAT은 2) TO_CHAR (NUMBER, FORMAT)에서 사용했던 FORMART을 사용합니다.

SQL> SELECT
2 TO_NUMBER(\'\'\'\'1234\'\'\'\'),
3 TO_NUMBER(\'\'\'\'123,123\'\'\'\',\'\'\'\'999,999\'\'\'\')
4 FROM DUAL;

TO_NUMBER(\'\'\'\'1234\'\'\'\') TO_NUMBER(\'\'\'\'123,123\'\'\'\',\'\'\'\'999,999\'\'\'\')
----------------- ------------------------------
1234 123123
4) TO_DATE(CHAR, FROMAT) : 문자를 날짜로 변환시켜주며, DATE형의 문자형 변환시와 반대지만 사용형식은 동일합니다.

SQL> SELECT TO_DATE(\'\'\'\'2003/12/11 00:36:27\'\'\'\', \'\'\'\'YYYY/MM/DD HH24:MI:SS\'\'\'\') FROM DUAL;

TO_DATE(
--------
03/12/11


==================================================================================================


(1) 현재 날자에서 하루를 빼고 싶다고 하면

select to_char(sysdate - 1,'yyyy/mm/dd hh24:mi:ss') d1 from dual;

(2) 1시간을 빼고 싶으면
select to_char(sysdate - 1/24,'yyyy/mm/dd hh24:mi:ss') d1 from dual;

(3) 1분을 빼고 싶으면
select to_char(sysdate - 1/24/60,'yyyy/mm/dd hh24:mi:ss') d1 from dual;

(q) 1초를 빼고 싶은면 어떻게 할까요? ^^
select to_char(sysdate - 1/24/60/60,'yyyy/mm/dd hh24:mi:ss') d1 from dual;

select /* 오늘날짜 시분초 포함*/ to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') from dual

select /* 오늘날짜 00시 00분 00초 */ to_char(trunc(sysdate),'yyyy/mm/dd hh24:mi:ss') from dual

select /* 오늘날짜 00시 00분 00초 위와 동일*/ to_char(trunc(sysdate,'dd'),'yyyy/mm/dd hh24:mi:ss') from dual


select /* 이번달 1일 00시 00분 00초 */ to_char(trunc(sysdate,'mon'),'yyyy/mm/dd hh24:mi:ss') from dual


select /* 올해 1월 1일 00시 00분 00초 */ to_char(trunc(sysdate,'year'),'yyyy/mm/dd hh24:mi:ss') from dual

select /* 올해 1월 1일 00시 00분 00초 */ to_char(to_date('2002','yyyy'),'yyyy/mm/dd hh24:mi:ss') from dual

select /* 2월 1일 00시 00분 00초 */ to_char(to_date('200202','yyyymm'),'yyyy/mm/dd hh24:mi:ss') from dual


select /* 2월 2일 00시 00분 00초 */ to_char(to_date('20020202','yyyymmdd'),'yyyy/mm/dd hh24:mi:ss') from dual

select /* 2월 2일 00시 00분 01초 */ to_char(to_date('20020202','yyyymmdd')+1/68400,'yyyy/mm/dd hh24:mi:ss') from dual

select /* 2월 2일 00시 00분 00초 -> 한달뒤*/ to_char

'공부' 카테고리의 다른 글

오라클 힌트사용하기  (0) 2012.01.02
리눅스 기본명령어  (0) 2011.12.15
ORACLE에서 제공되는 내장함수  (0) 2011.08.08
스프링을 공부하기전에  (0) 2011.07.01
공부의 필요성을 느끼다...  (0) 2011.06.08


ORACLE에서 제공되는 내장함수

1. 숫자함수

ABS(n) : ABS함수는 절대값을 계산하는 함수입니다.

CEIL(n) : CEIL함수는 주어진 값보다는 크지만 가장 근접하는 최소값을 구하는 함수입니다.

EXP(n) : EXP함수는 주어진 값의 e의 승수를 나타냅니다. e 2.171828183..입니다.

FLOOR(n) : FLOOR함수는 주어진 값보다 작거나 같은 최대 정수값을 구하는 함수입니다. (CEIL 함수와 비교해 보세요. )

LN(n) : LN함수는 주어진 값의 자연로그 값을 반환합니다.

MOD(m, n) : MOD함수는 m n으로 나누어 남은 값을 반환한다. n 0일 경우 m을 반환합니다.

POWER(m, n) : POWER함수는 m n승 값을 계산합니다.

ROUND(n, [m]) : ROUND함수는 n값의 반올림을 하는 함수로 m은 소숫점 아래 자릿수를 나타낸다.

SIGN(n) : SIGN함수는 n<0일 경우 -1DFM N=0일 경우 0 N>0일 경우 1을 반환합니다.

SQRT(n) : SQRT함수는 n값의 루트값을 계산한다. n은 양수여야 합니다.

TRUNC(n, m) : TRUNC함수는 n값을 m 소숫점 자리로 반내림한 값을 반환합니다. (ROUND 함수와 비교해 보세요.)

2. 문자열 처리함수

CONCAT(char1, char2) : CONCAT 함수는 Concatenation의 약자로 두 문자를 결합하는 역할을 합니다. "||" 연산자와 같은 역할을 합니다.

INITCAP(char) : 주어진 문자열의 첫 번째 문자를 대문자로 변환시켜 줍니다.

LOWER(char) : 문자열을 소문자로 변환 시켜 줍니다.

UPPER(char) : 문자열을 대문자로 변환 시켜 줍니다.

LPAD(char1, n [,char2]) : 왼쪽에 문자열을 끼어 놓는 역할을 합니다. n은 반환되는 문자열의 전체 길이를 나타내며, char1의 문자열이 n보다 클 경우 char1 n개 문자열 만큼 반환합니다.

RPAD(char1, n [,char2]) : LPAD와 반대로 오른쪽에 문자열을 끼어 놓는 역할을 합니다.

SUBSTR(char, m ,[n]) : SUBSTR함수를 이용하여 m 번째 자리부터 길이가 n개인 문자열을 반환한 합니다. m이 음수일 경우에는 뒤에서 M번째 문자부터 반대 방향으로 n개의 문자를 반환합니다.

LENGTH(char1) : 문자열의 길이를 리턴 합니다.

REPLACE(char1, str1, str2) : REPLACE는 문자열의 특정 문자를 다른 문자로 변환 합니다.

INSTR : 문자열이 포함되어 있는지를 조사하여 문자열의 위치를 반환합니다. 지정한 문자열

이 발견되지 않으면 0이 반환 됩니다.

TRIM : 특정한 문자를 제거 합니다. 제거할 문자를 입력하지 않으면 기본적으로 공백이 제

거 됩니다. 리턴값의 데이터타입은 VARCHAR2 입니다.

-- 두개의 문자를 연결한다.

SQL>SELECT CONCAT('Oracle', ' Korea') NAME FROM dual;

-- 문자좌측에 *를 붙인다. 문자 길이는 10개로 제한

SQL>SELECT LPAD('JUNG-SICK', 10, '*') NAME FROM dual;

-- 문자우측에 *를 붙인다. 문자 길이는 11개로 제한

SQL>SELECT RPAD('JUNG-SICK', 11, '*') NAME FROM dual;

-- 앞에서부터, 뒤에서부터 예제

SQL>SELECT SUBSTR('JUNG-SICK', 3, 3) NAME FROM dual;

SQL>SELECT SUBSTR('JUNG-SICK', -3, 3) NAME FROM dual;

-- 문자의 길이를 구함

SQL>SELECT LENGTH('JUNG-SICK') TEST FROM dual;

-- 대소문자 구별합니다.

SQL>SELECT REPLACE('JACK and JUE','J','BL') "Changes" FROM dual;

SQL>SELECT REPLACE('JACK and JUE','j','BL') "Changes" FROM dual;

-- 지정한 문자 OK가 발견되지 않아서 0이 반환 됩니다.

SQL>SELECT INSTR('CORPORATE FLOOR','OK') "Instring" FROM dual;

-- OR이 있는 위치 2를 반환 합니다. 왼쪽부터 비교를 한다는 것을 알 수 있습니다.

SQL>SELECT INSTR('CORPORATE FLOOR','OR') "Instring" FROM dual;

-- 0을 제거 합니다.

SQL>SELECT TRIM(0 FROM 0009872348900) "TRIM Example" FROM dual;

-- 어떤 문자도 입력하지 않으면 기본적으로 공백이 제거 됩니다.

-- TRIM을 사용한 위에 예제와 사용하지 않은 아래 예제의 결과 값이 다르게 나오는 것을 알 수 있습니다.

-- NVL(a,b) 함수는 a NULL일 경우 b로 바꿔주는 함수입니다.

SQL>SELECT NVL(TRIM (' '),'공백') "TRIM Example" FROM dual;

3. 날짜 처리함수

LAST_DAY(d) : LAST_DAY함수는 달의 마지막 날의 날짜를 반환합니다.

ADD_MONTHS(a, b) : ADD_MONTHS 함수는 a의 날짜에 b의 달을 더한 값을 반환 합니다.

MONTH_BETWEEN(a1, a2) : MONTH_BETWEEN a1 a2 사이의 달의 수를 NUMBER

타입으로 반환 합니다.

ROUND(d[,F]) : ROUND 함수는 F에 지정된 단위로 반올림 합니다. F가 연도라면 연도 단

위로 반올림 합니다.

-- 오늘과 이달의 마지막날 반환

SQL>SELECT SYSDATE TODAY, LAST_DAY(SYSDATE) LASTDAY FROM dual;

-- 오늘에서 3개월을 더한 후, RRRR/MM/DD 형식으로 반환

SQL>SELECT TO_CAHR(ADD_MONTHS(SYSDATE,3),'YYYY/MM/DD') "date" FROM dual;

-- 두 날짜 사이의 개월수를 반환

SQL>SELECT MONTHS_BETWEEN(TO_DATE('2000/06/05') , TO_DATE('2000/09/23')) "Date" FROM dual;

-- '1998/09/11' 의 년도인 1998을 반환

SQL>SELECT ROUND(TO_DATE('1998/09/11'), 'YEAR') FROM dual;

4. 변환함수

TO_CHAR : TO_CHAR함수는 DATE, NUMBER형을 VARCHAR2형으로 바꿔줍니다.

TO_DATE : TO_DATE함수는 CHAR, VARCHAR2형을 DATE 타입으로 변환합니다.

TO_NUMBER : TO_NUMBER함수는 CHAR, VARCHAR2의 데이터 타입을 숫자형식으로 변환

합니다.

-- 오늘의 월만 반환

SQL>SELECT TO_CHAR(sysdate, 'MONTH') CHARTEST FROM dual;

-- 자형이 날짜형으로 변환

SQL>SELECT TO_DATE('2000/06/16','YYYY/MM/DD') FROM dual;

-- '1210616'의 문자열이 숫자형으로 변환

SQL>SELECT TO_NUMBER('1210616') FROM dual;

5. 기타함수

NVL

- NVL 함수는 NULL값을 다른 값으로 바꿀 때 쓰입니다.

- 모든 데이터 타입에 적용 가능합니다.

- 전환되는 값의 데이터 타입을 일치시켜야 합니다.

DECODE

- DECODE 함수는 데이터 들을 다른 값으로 바꾸어 줍니다.

- 형식 DECODE(VALUE, IF1, THEN1, IF2, THEN2...)

- VALUE 값이 IF1일경우에 THEN1값으로 바꾸어 주고 VALUE값이 IF2일경우에는 THEN2값으로 바꾸어 줍니다.

DUMP : DUMP는 바이트 크기와 해당 데이터 타입 코드를 반환합니다.

GREATEST : GREATEST함수는 검색값 중에서 가장 큰 값을 반환 합니다.

LEAST : LEAST함수는 GREATEST함수와 반대로 가장 작은 값을 반환합니다.

UID : 현재 사용자의 유일한 ID번호를 반환 합니다.

USER : 현재 오라클을 사용하는 사용자를 VARCHAR2형식으로 반환 합니다.

USERENV : USERENV 함수는 현재 세션의 환경 정보를 반환합니다.

- ENTRYID : 사용 가능한 Auditing entry Identifier를 반환합니다.

- LABEL : 현재 세션의 Label을 반환합니다.

- LANGUAGE : 현재 세션에서 사용중인 언어와 테리토리 값을 반환합니다.

- SESSIONID : Auditing(감사) Session ID를 반환 합니다.

- TERMINAL : 현재 세션 터미널의 OS ID를 반환 합니다.

VSIZE : 해당 문자의 BYTE수를 반환 합니다. 해당 문자가 NULL이면 NULL값이 반환 됩니

.

-- 컬럼 comm의 값이 NULL일 경우, 0을 반환합니다.

SQL>SELECT empno, NVL(comm, 0) FROM emp WHERE deptno = 30;

-- 컬럼 deptno의 값이 10이며 'ACCOUNTING'으로

-- 컬럼 deptno의 값이 20이며 'RESEARCH'으로

-- 컬럼 deptno의 값이 30이며 'SALES'으로

-- 컬럼 deptno의 값이 40이며 'OPERATIONS'으로

SQL>SELECT deptno, DECODE(deptno, 10 , 'ACCOUNTING', 20 , 'RESEARCH', 30 , 'SALES', 40 , 'OPERATIONS') FROM emp;

-- 만약에 16대신 8을 넣으면 8진수로, 10를 넣으면 10진수로 변환이 됩니다.

-- 16, 10, 8, 17이 올수 있는데요 17은 단일 문자열을 반환합니다.

-- 결과값 중, Len ename의 해당 byte수 입니다.

SQL>SELECT ename, DUMP(ename, 16) "16진수" FROM emp WHERE ename = 'ALLEN'

-- 가장 큰수/가장 작은수 반환

SQL>SELECT GREATEST(10, 100, 5, -7) FROM dual;

SQL>SELECT LEAST(10, 100, 5, -7) FROM dual;

-- 현재 사용자의 이름과 ID값을 반환

SQL> SELECT USER, UID FROM DUAL;

-- 현재 세션의 환경정보를 반환

SQL> SELECT USERENV('LANGUAGE') FROM dual;

-- 현재 문자의 byte 수를 반환

SQL> SELECT VSIZE(ename), ename FROM emp WHERE deptno = 30;

'공부' 카테고리의 다른 글

오라클 힌트사용하기  (0) 2012.01.02
리눅스 기본명령어  (0) 2011.12.15
Oracle 날짜함수  (0) 2011.08.08
스프링을 공부하기전에  (0) 2011.07.01
공부의 필요성을 느끼다...  (0) 2011.06.08

엔티티 빈

공부/Spring2011. 7. 26. 10:09

 

1. 엔티티 빈의 개요

1.1. 엔티티 빈이란?

데이터를 객체화하여 재사용이 가능한 컴포넌트를 말한다.

데이터를 객체화한다는 것은 개발자들이 데이터에 접근하고 변경하는 방법이 보다 단순하고 쉬워진다는 것을 의미한다. 객체화 된 데이터를 비즈니스 객체 또는 현실 세계의 객체 라고 하며 이 객체는 영속성을 가진 관계형 데이터베이스에 저장이 되며 데이터베이스에서 테이블의 한 레코드와 대응된다. 여기서 중요한것은 빈 인스턴스와 데이터베이스의 데이터가 동기화되어야 한다는 것이다. 즉 빈 인스턴스에서 새로운 변화가 일어날 때마다 데이터베이스도 같이 갱신이 되어야하는 것이다.

1.2. 엔티티 빈의 종류

- 컨테이너 관리 퍼시스턴스 (CMP)

- 빈 관리 퍼시스턴스 (BMP)

1.3. 엔티티 빈의 구성

- 홈 인터페이스

- 리모트 인터페이스

- 빈 클래스

- 프라이머리 키 클래스 (세션 빈 구성과 차이점)

2. CMP 와 BMP

2.1. CMP

CMP 는 퍼시스턴스를 EJB 컨테이너가 자동으로 관리하는 엔티티 빈을 말한다. 이것은 퍼시스턴스에 대한 책임은 EJB 컨테이너가 맡고 비즈니스 로직에 대한 책임은 개발자가 전담하는것이다.

CMP 에서는 EJB 컨테이너의 능력이 아주 중요하다. 빈 인스턴스가 어떻게 데이터베이스와 대응되는지 알아야 하고 그로부터 데이터베이스에 데이터를 추가, 변경, 삭제 하는 것을 자동 관리하는 역할도 해야 하기 때문이다.

2.2. BMP

CMP 와 달리 개발자가 직접 퍼시스턴스와 관련된 로직을 명시적으로 코딩해야 한다.

3. 엔티티 빈의 라이프 사이클

- 클라이언트 측면에서 본 엔티티 객체의 라이프 사이클

- 컨테이너 측면에서 본 엔티티 빈의 라이프 사이클

아래는 가이드 라인입니다

1.정의
* 서버 컴퓨터에서 실행되는 자바 컴포넌트 모델
즉, 자바로 만들어진 서버쪽 컴포넌트들로 기업용 애플리케이션을 만들 때 사용되는 표준 규칙

가. EJB는 스펙
나. EJB로 개발할 수 있는 app
클라이언트 部分, 서버콤포넌트部分

다. java bean

* 자바빈은 EJB가 나오기 훨씬 전에 만들어진, 주로 클라이언트에서 비주얼하게 다룰 수 있는 컴포넌트를
개발할 때 사용되는 모델

* 단지 자바빈즈의 컴포넌트 개념을 서버로 대폭 확장시켜 기업용 애플리케이션에 알맞게 만든 모델이므로
자바 빈즈라는 이름 앞에 엔터프라이즈를 덧붙여서 엔터프라이즈 자바빈즈가 된 것이다.

* 자바빈즈 모델은 트랜잭션, 보안등의 기업용 어플리케이션에 꼭 필요한 기능 스펙을 포함하고 있지 않다

라. EJB장점

* EJB 스펙대로 app를 구현하게 되면 시스템 레벨의 각종 기능들(보안, 트랜잭션, 안전성 등)이 자동으로 처리
되므로 개발자가 직접 해결할 필요가 없기 때문.
=> 트랜잭션, 보안, 패일오버등의 기능들이 app개발자가 아닌 app 서버(EJB 컨테이너) 차원에서 지원된다.
=> 개발자는 비즈니스 로직만 프로그래밍하면 되고,
그 결과 개발자가 모든것을 코딩했을 때보다 안정된 시스템이 개발된다

* 컴포넌트 방식으로 app를 개발할 수 있게 함으로서 코드의 쉬운 유지보수, 높은 확장성, 코드의 재사용성 등의 장점

2. EJB와 자바빈즈의 비교
* EJB와 자바빈즈는 둘다 자바의 컴포넌트 프로그래밍 모델.

* 자바빈즈:
(1) 비주얼하게 컴포넌트를 다룰 수 있게 하는데 초점이 맞추어 있다. 이벤트(event), 속성(property)등을 규정
(2) 개발자 도구에서 비주얼하게 수행되어질 수 있는 재사용 가능한 소프트웨어 컴포넌트

* EJB: 컴포넌트들이 서버의 EJB 컨테이너 안에 플러그인(plugin)되어 설치된 후
트랜잭션, 보안, 패일오버 등의 서비스를 하게 되는 프레임워크에 초점이 맞춰져 있다.


3. EJB Architecture

* Home Interface => Home객체 (Home Object)

import javax.ejb.*;
import java.rmi.RemoteException;

public interface Name_of_HomeInterface extends EJBHome
{
public Name_of_RemoteInterface create() throws RemoteException, CreateException;
}

클라이언트가 엔터프라이즈 빈을 사용할 수 있도록 생성(create)하거나
또는 사용하고자 하는 엔터프라이즈 빈이 존재한다면 그것을 찾는(find)메소드들,
즉 create, find관련 메소드들이 선언된다.

* Remote Interface => Ejb객체 (EJB Object)

import javax.ejb.*;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Name_of_RemoteInterface extends EJBObject
{
public Return_Type Method() throws java.rmi.RemoteException;
}

클라이언트가 호출할 수 있는 엔터프라이즈 빈의 메소드들이 선언된다.
클라이언트가 호출할 수 있는 이런 메소드들을 비즈니스 메소드라고 한다.

* 빈 클래스(bean class) => Bean Instance

(1) 리모트 인터페이스안에 선언된 메소드들고 똑같은 이름의 메소드들의 내부코드를 구현해야 한다.
(2) EJB 컨테이너 규약 메소드들을 추가로 작성해야한다.
이것은 클라이언트가 아닌 EJB 컨테이너가 특정한 순간에 호출하는 메소드들이라서
EJB 컨테이너 규약(contract) 메소드

* deploy descriptor
트랜잭션, 보안, 자원관리등을 설정한 xml파일

----------------------------------------------------------------------
<홈 인터페이스, 홈 인터페이스를 구현(implement)한 클래스, 홈 객체의 관계>

홈 인터페이스는 개발자가 작성하며,
이 인터페이스를 구현(implement)한 클래스는 EJB 컨테이너에 의해 자동으로 생성된다
이 클래스에서 실행시에 생성된 객체를 "홈 객체"라고 한다.

<리모트 인터페이스, 리모트 인터페이스를 구현(implement)한 클래스, EJB객체의 관계>

리모트 인터페이스는 개발자가 작성하며,
이 인터페이스를 구현(implement)한 클래스는 EJB컨테이너에 의해 자동으로 생성된다.
이 클래스에서 실행시에 생성된 객체를 "EJB 객체"라고 한다.

<빈 클래스, 빈 인스턴스의 관계>

EJB컨테이너 실행시에 "빈 클래스"에서 생성된 객체를 "빈 인스턴스"라고 한다.
----------------------------------------------------------------------

4. 엔터프라이즈 빈
* 클라이언트가 호출하여 사용할 수 있는 EJB 컴포넌트를 의미.

* 엔터프라이즈 빈은 단지 한 개의 클래스를 의미하는 것이 아니라 EJB 아키텍쳐 안에
포함되는 컴포넌트를 지칭하는 단어이며 여러개의 클래스와 인터페이스로 구성된다.

* 최소 구성요소
home interface
remote interface
bean class
deploy descriptor

(1) Entity Bean : 영구적으로 저장되어야 할 데이터를 의미(구체적으로 DB의 테이블을 상징)
Entity Bean의 Bean instance는 테이블의 한 레코드를 상징
반면 빈클래스는 테이블 자체를 상징

* 영속성(persistence)을 관리하는 방식에 따라 : CMP(Container Managed Persistence), BMP(Bean Managed Persistence)

① CMP(Container Managed Persistence) : EJB 컨테이너가 자동으로 DB를 관리

* DB관리를 위한 코드를 작성할 필요없음
* Deploy time에 DB종류(관계형, 객체지향등) 상관없이 유연하게 Entity Bean과 연결 가능
* Entity Bean과 DB연결 방식은 EJB컨테이너가 제공하는 툴에 제한됨
* EJB 컨테이너에 의해 SQL문장이 생성되기 때문에 데이터 베이스의 세밀한 관리가 불가능
* 성능이 BMP방식보다 떨어질 수 있다.

② BMP(Bean Managed Persistence) : 빈 자체가 DB를 관리

* DB관리를 위한 코드 작성해야함
* DB관리방식이 Deploy Time에 바뀌지 않음
* 객체와 DB를 연결하는 방식을 빈 개발자가 자유롭게 만듬
* SQL 문장을 자유롭게 사용하여 세밀한 DB관리가 가능
* 개발자의 능력에 따라 CMP방식보다 좋을 수 있다.

(2) Session Bean : 비즈니스 프로세스, 즉 어떤 업무나 일 자체를 상징하는 컴포넌트

* 상태를 관리하는 방식에 따라 : stateful session bean(상태유지 세션빈), stateless session bean(무상태 세션빈)

① stateful session bean(상태유지 세션빈)
* HDD에 상태정보를 save, load하는 (activate/passivate)활성화/비활성화 과정이 수행된다

② stateless session bean(무상태 세션빈)
* activate/passivate과정이 없다

(3) 엔터프라이즈 빈 개발자가 할 일

가. 엔터프라이즈 빈의 종류 선택
나. 3 종류의 소스 코드 작성 및 컴파일
다. deployment
라. 테스트용 클라이언트 프로그램 개발
----------------------------------

가. 엔터프라이즈 빈의 종류 선택

① 개발할 엔터프라이즈 빈이 프로세스나 일의 과정이면 세션 빈,
② 데이터베이스의 데이터를 상징하면 엔티티빈
③ 세션빈으로 선택했다면 무상태 세션빈인지, 상태유지 세션빈인지 결정
④ 엔티티빈이면 BMP인지, CMP 엔티티 빈인지 선택
나. 3종류의 소스 코드 작성 및 컴파일

(A) 세션빈을 선택할 경우
(B) 엔티티빈을 선택할 경우
-------------------------

(A) 세션빈을 선택할 경우

[Home Interface]

① stateful session bean(상태유지 세션빈)

* 코드 템플릿 :
import javax.ejb.*;
import java.rmi.*;
public interface <BeanName>Home extends EJBHome
{
public <BeanName> create(<rmiParams>)
throws [businessException,...] CreateException, RemoteException;
}

* 상속 : javax.ejb.EJBHome을 상속받음

* create() 메소드 규칙 :
1) 한 개 이상의 create() 메소드들을 선언해야만 한다. 이때 파라미터가 존재 할 수 있다.
상태정보가 유지되어야 하기 때문에 초기화 데이터가 필요하며 따라서 파라미터가 존재할 수 있다.
무상태 세션빈과 다른 점은 create()메소드에 파라미터가 있어서(파라미터가 있을수도, 없을수도 있다)
EJB객체를 초기화 할 수 있으며 또한 개발자가 정의한 예외를 처리할 수 있다는 것이다.
2) create() 메소드의 반환 타입은 본 세션빈의 리모트 인터페이스 타입이다.
3) 반드시 "throw"를 사용하여 예외를 포함해야 한다.
이때 개발자가 정의한 비즈니스 예외처리를 할 수 있다.

* 빈 클래스와의 관계 :
홈 인터페이스의 모든 create() 메소드들은 빈 클래스에 똑같은 이름의 ejbCreate()들로
내부코드가 구현된다.(단, 반환값의 타입이 다르다)

* Example>
----------------------------------------------------
<Server Part>
import javax.ejb.*;
import java.rmi.*;
public interface CartHome extends EJBHome
{
Cart create(String customerName, String account)
throws RemoteException, CreateException, BadAccountException;
}

<Client Part>
// JNDI 컨텍스트 생성
Context initialContext = new InitialContext();

// JNDI로 홈객체의 레퍼런스를 얻음
CartHome cartHome = (CartHome)javax.rmi.PortableRemoteObject.
narrow(initialContext.lookup("java:comp/env/ejb/cart"), CartHome.class);

// EJB객체 생성
Cart cart = cartHome.create("John", "7506");
----------------------------------------------------

② stateless session bean(무상태 세션빈)

* 코드 템플릿 :
import javax.ejb.*;
import java.rmi.*;
public interface <BeanName>Home extends EJBHome
{
public <BeanName> create() throws CreateException, RemoteException;
}

* 상속 : javax.ejb.EJBHome을 상속받음

* create() 메소드 규칙 :
1) 단지 파라미터가 없는 한 개의 create()메소드를 선언해야만 한다
상태정보가 없으므로 초기화 데이터가 필요없기 때문에 create() 메소드의 파라미터가 없다
2) create() 메소드의 반환 타입은 본 세션 빈의 리모트 인터페이스 타입이다.
3) 반드시 'throws'를 사용하여 'CreateException' 예외를 포함해야 한다.
RemoteException이 포함된 것은 클라이언트가 RMI프로토콜로 엔터프라이즈 빈을 사용하기 때문이다.

* 빈 클래스와의 관계 :
홈 인터페이스의 모든 create() 메소드들은 빈 클래스에 똑같은 이름의 ejbCreate()들로
내부 코드가 구현된다.(단, 반환 값의 타입이 다르다)

* Example>
-----------------------------------------------------
<서버 부분>
import javax.ejb.*;
import java.rmi.*;
public interface CartHome extends EJBHome
{
Cart create() throws RemoteException, CreateException;
}

<클라이언트 部分>
Context initialContext = new InitialContext();

// JDNI로 홈객체의 레퍼런스를 얻음
CartHome cartHome = (CartHome)javax.rmi.PortableRemoteObject.
narrow(initialContext.lookup("java:comp/env/ejb/cart"), CartHome.class);

// EJB 객체 생성
Cart cart = CartHome.create();
-----------------------------------------------------


* 클라이언트 개발자는 홈 객체의 레퍼런스를 얻은 후에 다음과 같은 작업을 할 수 있다.

① 새로운 EJB객체 생성
② EJB 객체의 삭제
③ 세션 빈의 메타데이터를 얻는다. 이것은 주로 툴을 개발할 때 사용
④ 홈 객체를 가리키는 핸들을 얻는다.
핸들이란 네트워크로 떨어진 객체를 가리키는 레퍼런스를 추상화한 것이다.
이 핸들은 하드에 저장될 수 있으며 다른 컴퓨터로 네트워크를 통해 이동이 가능하다.

javax.ejb.EJBHome
{
EJBMetaData getEJBMetaData() 엔터프라이즈 빈의 메타데이터를 반환한다.
HomeHandle getHomeHandle() 홈 객체의 핸들을 반환한다.
void remove(Handle handle) 핸들이 가리키는 EJB객체를 삭제한다.
void remove(java.lang.Object primarykey) 엔티티 빈의 경우 프라이머리 키에 해당되는 EJB객체를 삭제
}
[Remote Interface]

* 세션 빈이 클라이언트에게 제공해야 하는 비즈니스 메소드를 선언한다.
* 클라이언트는 홈 객체를 통해 EJB객체를 생성하고
그 레퍼런스를 얻은 후 리모트 인터페이스에 선언된 메소드들을 호출할 수 있게 된다.
* 리모트 인터페이스를 구현(implement)한 클래스는 EJB컨테이너에 의해 자동으로 생성된다.
또한 적절한 실행시간에 그 클래스로부터 객체가 생성되는데 그 객체를 "EJB객체"라고 한다.
* 클라이언트가 비즈니스 메소드를 호출할 때 바로 이 객체의 비즈니스 메소드가 호출되며 이 안에서
빈 클래스의 객체인 빈 인스턴스의 해당 비즈니스 메소드를 호출한다.
* 실제로 비즈니스 메소드의 내부를 구현한 클래스는 빈 클래스이며 EJB 객체는 이 빈 클래스의 객체인
빈 인스턴스의 얼굴마담 역할을 한다.
이 EJB 객체는 RMI의 리모트 객체로서 스텁과 스켈레턴이 생성되어 클라이언트가 RMI 프로토콜로 접근하게 된다.

* 코드 템플릿 :
import javax.ejb.*;
import java.rmi.*;
public interface <BeanName> extends javax.ejb.EJBObject
{
public <rmiReturnType> <businessMethod> (<rmiParams>)
throws [<businessException>,...] RemoteException;
}

* 상속 : javax.ejb.EJBObject인터페이스를 상속받는다.

* 비즈니스 메소드 규칙 :
1) 모든 비즈니스 메소드들은 "throw"를 사용하여 RemoteException을 포함해야 한다.
클라이언트가 RMI 프로토콜로 엔터프라이즈 빈을 사용하기 때문
2) 어떤 비즈니스 메소드들은 개발자가 정의한 예외를 "throw"문에 포함할 수 있다.
3) 모든 비즈니스 메소드들의 파라미터와 반환 값의 타입은 반드시 RMI를 통해 이동될 수 있는 타입이어야한다.
즉, Serializable 인터페이스를 구현한 객체 또는 기본 데이터 타입 또는 리모트객체 중의 하나이어야 한다.

* 빈 클래스와의 관계 :
선언된 모든 비즈니스 메소드들은 빈 클래스에 똑같은 이름의 비즈니스 메소드들이 존재하며
그 안에 비즈니스 메소드의 내부 코드가 구현된다.

* Example>
------------------------------------------------
<Server Part>
import javax.ejb.*;
import java.rmi.*;
public interface Cart extends EJBObject
{
void addItem(int item) throws RemoteException
void purchase() throws RemoteException;
}

<Client Part>
Context initialContext = new InitialContext();

// JNDI로 홈객체의 레퍼런스를 얻음
CartHome cartHome = (CartHome) javax.rmi.PortableRemoteObject.
narrow(initialContext.lookup("java:comp/env/ejb/cart"), CartHome.class);

// EJB객체를 생성
Cart cart = cartHome.create("John", "7506");
cart.addItem(96);
cart.purchase();
------------------------------------------------


* 클라이언트 개발자는 EJB객체의 레퍼런스를 얻은 후에 다음과 같은 작업을 할 수 있다.

① 빈 인스턴스 비즈니스 메소드들의 간접적인 호출
② EJB 객체의 삭제
③ 세션 빈의 홈 객체를 얻는다
④ EJB 객체의 핸들을 얻는다
⑤ 현재의 EJB 객체와 다른 EJB 객체가 같은 객체인지 비교할 수 있다.

* javax.ejb.EJBObject는 여러 메소드들이 선언되어 있다.
따라서 클라이언트는 EJB 객체의 레퍼런스를 통해 비즈니스 메소드들을 호출하는 것 외에
다음과 같은 메소드들을 사용할 수 있다.

javax.ejb.EJBObject
{
public EJBHome getEJBHome() // 홈 객체를 반환한다.
public java.lang.Object getPrimaryKey() // 엔티티 빈일 경우 해당 프라이머리 키를 반환한다.
void remove() // EJB 객체를 제거한다.
public Handle getHandle() // EJB 객체의 핸들을 반환한다.
나중에 이 핸들을 사용하여 EJB 객체의 레퍼런스를 얻을 수 있다.
public boolean isIdentical(EJBObject obj)
// 현재 EJB 객체와 파라미터의 EJB 객체가 같은 객체인지 비교한다.
}

[빈 클래스]

* 빈 개발자는 두 가지 종류의 메소드를 구현해야 한다

① 리모트 인터페이스 비즈니스 메소드들과 똑같은 이름의 비즈니스 메소드
② EJB 컨테이너가 적정한 시점에 호출하는 EJB 컨테이너 규약 메소드
setSessionContext(), ejbCreate(), ejbRemove(), ejbActivate(), ejbPassivate()

* 빈 클래스 개발자는 홈 인터페이스에 선언된 모든 create() 메소드들을 ejbCreate()로 정의하며
또한 리모트 인터페이스 안에 선언된 모든 비즈니스 메소드들을 정의한다.
그리고 SessionBean 인터페이스 안에 선언된 4개의 메소드들의 내부를 구현해야 한다.

① stateless session bean

* 비즈니스 메소드 템플릿 :
import javax.ejb.*;
import java.rmi.*;
public class <BeanName>Bean implements SessionBean
{
public <rmiRV> <businessMethod> (<rmiParams>)
[ throws [<businessException>,...] RemoteException ]
{
/* 구현 */
}

// .. 다른 비즈니스 메소드들
}

* EJB 컨테이너 규약 메소드 템플릿 :

1) create 관련 메소드
import javax.ejb.*;
import java.rmi.*;
public class <BeanName>Bean implements SessionBean
{
public void ejbCreate() [ throws [CreateException][RemoteException] }
{
/* 구현 */
}

// 다른 ejbXXX 메소드와 비즈니스 메소드 구현
}

2) SessionBean 인터페이스에 선언된 컨테이너 규약 메소드의 구현
import javax.ejb.*;
import java.rmi.*;
public class <BeanName>Bean implements SessionBean
{
private SessionContext _context;
public void setSessionContext(SessionContext cxt)
{
_context = cxt;
}

public void ejbRemove(){ /* 구현 */ }
public void ejbActivate(){}
public void ejbPassivate(){}

//...
}

* 구현 여부 : 반드시 javax.ejb.SessionBean 인터페이스를 구현한다.

* 주의할 내용 :
1) 추상 클래스가 아닌, 객체를 생성할 수 있는 클래스를 정의해야 한다.
2) javax.ejb.SessionBean 인터페이스를 구현해야 한다.
즉, SessionBean 인터페이스 안에 선언된 메소드들을 모두 반드시 구현해야 한다.
이 안에 있는 메소드들이 EJB 컨테이너가 호출하는, EJB 컨테이너 규약 메소드들이다.
3) 리모트 인터페이스에 선언된 모든 비즈니스 메소드들과 똑같은 이름의 메소드들을 정의한다.
4) 홈 인터페이스의 create() 메소드와 대응되는 ejbCreate() 메소드를 정의한다.
보통 ejbCreate() 메소드의 내부는 비워둔다.
상태 정보가 유지될 필요가 없기 때문에 초기화할 필요가 없기 때문이다.
5) 무상태 세션 빈에서 ejbActivate(), ejbPassivate() 메소드의 내부는 일반적으로 비워두며
ejbCreate(), ejbRemove()에 초점을 맞춘다.

* 다른 인터페이스들과의 관계 :
1) 정의된 모든 비즈니스 메소드들은 리모트 인터페이스에 똑같은 이름의 메소드들로 선언되어 있어야 한다.
2) ejbCreate()에 해당하는 create() 메소드들이 홈 인터페이스에 선언되어 있어야 한다.

* Example>
import javax.ejb.*;
import java.rmi.*;
public class CartBean implements SessionObject
{
private SessionContext _context;

public void setSessionContext(SessionContext ctx)
{
_context = ctx;
}

public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}

void addItem(int item) { // 구현 }
throws RemoteException;

void purchase() { // 구현 }
throws RemoteException;
}

② stateful session bean

* 무상태 세션 빈과의 차이점은 "활성화/비활성화"시에 호출하는 ejbActivate(), ejbPassivate()
메소드에 현재 상태를 유지하기 위한 적절한 코드를 작성해야 한다는 것이다.

* EJB 컨테이너는 자원이 절약되어야 한다고, 즉 "비활성화"해야 한다고 판단하면 자주
사용되지 않는 빈 인스턴스를 선택한 후 하드디스크에 해당 정보를 저장한다.
이때 빈 인스턴스의 ejbPassivate() 메소드를 먼저 호출한다. 클라이언트가 절약된 빈 인스턴스를
사용하려고 한다면 빈 인스턴스를 활성화해서 메모리로 올려야 한다. 이때는 먼저
하드디스크에서 빈 인스턴스 정보를 메모리에 올리고 빈 인스턴스의 ejbActivate()메소드를 호출한다.
(엔티티 빈에서도 이런 "활성화/비활성화" 작업이 일어난다)

비활성화 : ejbPassivate() => 저장
활성화 : 디스크에서 로드 => ejbActivate()

* 비즈니스 메소드 템플릿 :
무상태 세션 빈의 경우와 동일함

* EJB 컨테이너 규약 메소드 템플릿 :

1) create 관련 메소드
import javax.ejb.*;
import java.rmi.*;
public class <BeanName>Bean implements SessionBean
{
public void ejbCreate(<rmiParams>)
[ throws [CreateException] [RemoteException] ]
{/* 구현 */}

// ...
}

2) SessionBean 인터페이스에 선언된 컨테이너 규약 메소드
무상태 세션 빈의 경우와 동일함

* 구현 여부 : 반드시 javax.ejb.SessionBean 인터페이스를 구현한다.

* 주의할 내용 :
1) 추상 클래스가 아닌, 객체를 생성할 수 있는 클래스를 정의해야 한다.
2) javax.ejb.SessionBean 인터페이스를 구현해야 한다.
즉, SessionBean 인터페이스 안에 선언된 메소드들을 모두 반드시 구현해야 한다.
이 안에 있는 메소드들이 EJB 컨테이너가 호출하는, EJB 컨테이너 규약 메소드들이다.
3) 리모트 인터페이스에 선언된 모든 비즈니스 메소드들과 똑같은 이름의 메소드들을 정의한다.
4) 홈 인터페이스에 선언된 create 메소드들에 대응되는 ejbCreate() 메소드들을 정의한다.
파라미터가 있는 경우 그 값에 따라 세션 빈의 상태 정보를 초기화한다.
5) "활성화/비활성화"가 일어날 때 상태 정보를 계속 유지하기 위해서
ejbActivate(), ejbPassivate() 메소드를 적절히 구현한다.

* 다른 인터페이스들과의 관계 :
무상태 세션 빈의 경우와 동일함

* Example>

import javax.ejb.*;
import java.rmi.*;
public class CartBean implements SessionBean
{
private SessionContext _context;

// 상태유지 정보
private String customerName, account;

public void setSessionContext(SessionContext ctx)
{
_context = ctx;
}
public void ejbCreate(String customerName, String account)
{
this.customerName = customerName;
this.account = account;
}
public void ejbRemove() {}
public void ejbActivate()
{
// 활성화될 때 해야할 일을 구현
}

public void ejbPassivate()
{
// 비활성화 될 때 해야할 일을 구현
}

void addItem(int item) { // 구현 }
throws RemoteException;

void purchase() { // 구현 }
throws RemoteException;
}

* javax.ejb.SessionBean은 여러메소드들이 선언되어 있다. 그렇지만 이 메소드들을 클라이언트가
직접 호출하여 사용하는 것이 아니라 EJB 컨테이너가 자동으로 호출한다.
따라서 이런 메소드들은 EJB 컨테이너와 빈 개발자와의 일종의 약속이기 때문에 "EJB 컨테이너 규약 메소드"
라고 한다.(이런 메소드들은 이름이 ejbXXX() 등으로 시작한다)

- 클라이언트들은 비즈니스 메소드들을 EJB 객체를 통하여 간접적으로 호출할 수 있다. 클라이언트는
빈 클래스 및 인스턴스의 존재를 전혀 모르며 EJB 객체를 통하여 빈 인스턴스를 호출한다.

- 세션 빈 클래스를 작성할 때 빈 클래스 개발자는 실제 빈 인스턴스가 생성된 후에 EJB 컨테이너가
현재 어떤 정보를 가지고 동작하는지 알지 못한다. 이런 정보를 빈 클래스 안에서 사용하려고 한다면
EJB 컨테이너가 생성한 SessionContext 객체를 setSessionContext() 메소드로 받아서 속성으로
할당받은 다음 원하는 컨테이너 정보를 얻을 수 있다. SessionContext 객체가 제공하는 정보는
현재 빈 인스턴스와 연결되어 있는 EJB 객체의 레퍼런스이다.

javax.ejb.SessionBean
{
public void setSessionContext(SessionContext ctx) // SessionContext 객체를 넘겨받아서
빈 인스턴스의 속성에 할당한다.
컨테이너가 빈 인스턴스를 생성한 직후에 호출한다.
public void ejbRemove() // EJB 객체가 더 이상 사용되지 않을 때 컨테이너에 의해 호출
public void ejbActivate() // 빈 인스턴스가 "활성화"될 때 호출된다.
public void ejbPassivate() // 빈 인스턴스가 "비활성화"될 때 호출된다.
}
(B) 엔티티빈을 선택할 경우
* Home interface, Remote interface, Bean 클래스를 작성해야함(세션빈과 동일)
* Home interface에 findXXX()라는 메소드들을 추가로 선언해야함(세션빈과 차이)
(XXX는 개발자가 그 이름을 자유롭게 지정할 수 있다.)
* 엔티티 빈 클래스는 DB의 테이블을 상징하고, EJB 객체 및 빈 인스턴스는 테이블의 한 레코드를 상징한다.
* create()는 EJB 객체를 생성, 즉 테이블에 한 레코드를 추가하는 역할
* findXXX()들은 이미 존재하는 테이블 내의 특정 조건을 만족하는 레코드들,
즉 EJB객체들을 반환하는 역할을 한다
* findXXX()의 반환 타입은 엔티티 빈의 리모트 인터페이스이거나 Enumeration, Collection
등의 컬렉션 타입이어야 한다.
* 모든 엔티티 빈의 홈 인터페이스는 반드시 findByPrimaryKey() 메소드를 선언해야 한다.
findByPrimaryKey() 메소드의 파라미터는 테이블의 칼럼(column)에 해당되며 테이블의
프라이머리 키 역할을 해야 한다.
이 파라미터의 타입은 "프라이머리 키 클래스" 이며 String 또는 사용자가 정의한 클래스로서
테이블의 프라이머리 키를 상징한다.
* 프라이머리 키 클래스의 개념은 세션 빈에 없는 엔티티 빈만의 독특한 개념이다.
* 따라서 엔티티 빈을 개발할 때는 세션 빈과 달리 홈 인터페이스, 리모트 인터페이스, 빈 클래스외에
프라이머리 키 클래스를 정의해야 한다.
* CMP, BMP에 따라 코드 작성방식이 약간씩 달라진다.

[Home Interface]

* 엔티티 빈 클라이언트가 서버의 엔티티 빈을 사용하기 위해서는 홈 인터페이스의 create()메소드를
호출하여 EJB 객체를 생성해야 한다. 이 홈 인터페이스를 직접 구현(implement)한 클래스는
EJB 컨테이너에 의해서 자동으로 생성되고 적절한 시기에 그 클래스로부터 홈 객체가 생성된다.
생성된 홈 객체는 EJB 컨테이너 안에서 EJB 객체를 생성(create)하거나 찾는(find)공장(factory)역할을 한다

* 홈 인터페이스는 javax.ejb.EJBHome 인터페이스를 상속받은 인터페이스이다.
개발자는 단지 EJB 객체를 생성할 때 초기화해주는 create() 메소드들과
EJB 객체를 찾아서 반환하는 findXXX() 메소드들을 선언하기만 하면 된다.

* 코드 템플릿 : <PrimaryKey>는 프라이머리 클래스를 의미

1) create메소드 :
import javax.ejb.*;
import java.rmi.*;
public interface <BeanName>Home extends EJBHome
{
public <BenaName> create(<rmiParams>)
throws [<businessException>,...] CreateException, RemoteException;

// ...
}

2) findByPrimaryKey() 메소드 선언 :
import javax.ejb.*;
import java.rmi.*;
public interface <BeanName>Home extends EJBHome
{
public <BeanName> findByPrimaryKey(<PrimaryKey>)
throws [<businessException>, ...] FinderException, RemoteException;

// ...
}

3) findXXX() 메소드 선언 (옵션)

가. 한개의 EJB 객체 찾기
import javax.ejb.*;
import java.rmi.*;
public <BeanName> findXXX (<rmiParams>)
throws [<businessException>,]... FinderException, RemoteException;

나. 여러 개의 EJB 객체 찾기
import javax.ejb.*;
import java.rmi.*;
public Enumeration findXXX (<rmiParams>)
throws [<businessException>,]... FinderException, RemoteException;

* 상속 : 반드시 javax.ejb.EJBHome 인터페이스를 상속받는다.

* create() 메소드 규칙 : 상태 유지 세션 빈의 경우와 동일하다.

* find 관련 메소드 규칙 :

1) findByPrimaryKey()을 반드시 선언해야 한다.
반환 타입은 반드시 리모트 인터페이스어야 하며
"throw"는 FinderException과 RemoteException을 포함해야 한다.
단 1개의 파라미터를 정의해야 하며 그 타입은 테이터베이스 테이블의 프라이머리 키의
타입을 상징하는 프라이머리 키 클래스이다.

2) findXXX() 메소드의 반환타입은 리모트 인터페이스이거나 java.util.Enumeration,
java.util.Collection 타입이다. 반환타입이 Enumeration, Collection인 경우 포함된
원소들인 리모트 객체들을 추출하여 사용한다. Enumeration은 JDK1.1, Collection은 java2
에서 사용한다.

* 빈 클래스와의 관계 : 상태유지 세션 빈의 경우와 동일하다.

* Example>

<Server Side>
import javax.ejb.*;
import java.rmi.*;
public interface AccountHome extends EJBHome
{
public Account create(String firstName, String lastName, double initialBalance)
throws RemoteException, CreateException;

public Account create(String accountNumber, double initialBalance)
throws RemoteException, CreateException, LowInitialBalanceException;

public Account findByPrimaryKey(String AccountNumber)
throws RemoteException, FinderException;
}

<Client Side>
// JNDI로 홈 객체의 레퍼런스를 얻음.(세션빈과 동일)
AccountHome = ...;
Account account1 = accountHome.create("John", "Smith", 500.00);
Account account2 = accountHome.findByPrimaryKey("100-3450-3333");

int deposit = account1.deposit(1000);
balance = account1.balance();

* 만약 엔티티 빈이 상징하는 데이터베이스의 테이블의 프라이머리 키(Primary key)가 두개 이상이면
String이 아니라 그 프라이머리 키의 타입을 속성으로 한 프라이머리 키 클래스를 정의한다.
그리고 그 프라이머리 키 클래스를 findByPrimaryKey()의 파라미터의 타입으로 지정한다.
프라이머리 키 클래스는 반드시 디플로이먼트 디스크립터에 명시해야 하며
hashcode(), equals()등의 메소드들을 구현해야만 한다.

[리모트 인터페이스]

* 코드 템플릿 : 세션 빈의 경우와 동일
* 상속 : javax.ejb.EJBObject 인터페이스를 상속받는다.
* 비즈니스 메소드 타입 : 세션 빈의 경우와 동일
* 빈 클래스와의 관계 : 세션 빈의 경우와 동일
* Example>
<Server Side>
import javax.ejb.*;
import java.rmi.*;
public interface Account extends EJBObject
{
public double deposit(double amount)
throws ProcessingErrorException, RemoteException;
public double withdraw(double amount)
throws ProcessingErrorException, RemoteException;
public double balance()
throw RemoteException;
}

<Client Side>
// JNDI로 홈 객체의 레퍼런스를 얻음.(세션 빈과 동일)
AccountHome = ...;
Account account1 = accountHome.create("John", "Smith", 500.00);
Account account2 = accountHome.findByPrimaryKey("100-3450-3333");

int deposit = account1.deposit(1000);
balance = account1.balance();

[빈 클래스]

* 엔터프라이즈 빈의 핵심 클래스로서 EJB 개발자가 가장 신경써서 작성해야 하는 부분이다.
EJB 개발자는 2가지 종류의 메소드를 구현해야 한다.
1) 리모트 인터페이스의 비즈니스 메소드들과 똑같은 이름의 비즈니스 메소드
2) EJB 컨테이너가 때에 따라서 호출하는 EJB 컨테이너 규약 메소드
setEntityContext()
unsetEntityContext()
ejbCreate()
ejbRemove()
ejbActivate()
ejbPassivate()
ejbLoad()
ejbStore()

① CMP 엔티티 빈의 빈 클래스 작성요령

* 비즈니스 메소드 템플릿 :
import javax.ejb.*;
import java.rmi.*;
public class <BeanName>Bean implements EntityBean
{
public <Serializable type> <Attributes>;

// ...

public <rmiRV> <businessMethod>(<rmiParams>)
[throws [<businessException>,...] RemoteException]
{
/* 구현 */
}

// ...
}

* EJB 컨테이터 규약 메소드 템플릿
1) create 관련 메소드
가. create()
public class <BeanName>Bean implememts javax.ejb.EntityBean
{
public <PrimaryKey> ejbCreate (<rmiParams>)
throws [javax.ejb.CreateException,][java.rmi.RemoteException]
{
/* 구현 */
}

// ...
}

나. ejbPostCreate()
public void ejbPostCreate(<rmiParams>)
throws [javax.ejb.CreateException,] [java.rmi.RemoteException]
{
/* 구현 */
}

2) EntityBean 인터페이스에 선언되 컨테이너 규약 메소드
가. 일반 규약 메소드
public class <BeanName>Bean implements javax.ejb.EntityBean
{
private EntityContext _context;

public void setEntityContext(EntityContext ctx)
{
/* 컨텍스트 객체에 대한 레퍼런스를 유지한다 */
}
public void unsetEntityContext(EntityContext ctx)
{
/* 컨텍스트 객체에 대한 레퍼런스를 해제한다. */
}
public void ejbRemove(){ /* 구현 */ }
public void ejbActivate(){ /* 구현 */ }
public void ejbPassivate(){ /* 구현 */ }

// ...
}

3) "Load/Store"관련 메소드
public class <BeanName>Bean implements javax.ejb.EntityBean
{
// ...
public void ejbLoad() { /* 구현 */ }
public void ejbStore() { /* 구현 */ }
}

* 구현 여부 : 반드시 javax.ejb.EntityBean 인터페이스를 구현한다.

* 주의할 내용 :
1) 추상 클래스가 아닌, 객체를 생성할 수 있는 클래스를 정의해야 한다.
빈 클래스의 모든 속성은 엔티티 빈의 상태정보, 즉 데이터베이스 테이블의 칼럼을 상징한다.
따라서 public으로 선언되어야 하며 2차 저장소에 저장될 수 있도록 "Serializable"해야한다.

2) javax.ejb.EntityBean 인터페이스를 구현해야 한다.
즉, EntityBean 인터페이스 안에 선언된 메소드들을 모두 반드시 구현해야 한다.
이 안에 있는 메소드들이 EJB 컨테이너가 호출하는, EJB 컨테이너 규약 메소드들이다.

3) 리모트 인터페이스 선언된 모든 비즈니스 메소드들과 똑같은 이름의 메소드들을 정의한다.

4) 보통 ejbCreate() 메소드는 엔티티 빈의 상태정보를 초기화 하는 역할을 한다.
각 ejbCreate() 마다 ejbPostCreate()라는 메소드를 반드시 구현해야 하며
이 메소드는 ejbCreate() 메소드의 호출이 끝난 직후에 호출된다.

5) 엔티티 빈에서 setEntityContext()와 unsetEntityContext()를 구현한다.
ejbActivate(), ejbPassivate(), ejbRemove()도 구현한다.

* 다른 인터페이스들과의 관계 :
1) 정의된 모든 비즈니스 메소드들은 리모트 인터페이스에 똑같은 이름의 메소드들이 선언되어
있어야 한다.

2) ejbCreate()에 해당하는 create() 메소드들이 홈 인터페이스에 선언되어 있어야 한다.

* Example>
import java.util.*;
import javax.ejb.*;

public class ProductEJB implements EntityBean
{
public String productID;
public String description;
public double price;
private EntityContext context;

public void setPrice(doublc price)
{
this.price = price;
}
public double getPrice()
{
return price;
}
public String getDescription()
{
return description;
}

public String ejbCreate(String productID, String description, double price)
throws CreateException
{
if( productID == null )
{
throw new CreateException("The productID is required.");
}

this.productID = productID;
this.description = description;
this.price = price;

return null;
}

public void ejbPostCreate(String productID, String description, double balance){}

public void setEntityContext(EntityContext context)
{
this.context = context;
}

public void unsetEntityContext() {}

public void ejbActivate()
{
productID = (String)context.getPrimaryKey();
}

public void ejbPassivate()
{
productID = null;
description = null;
}

public void ejbRemove() {}
public void ejbLoad() {}
public void ejbStore() {}

}// ProductEJB

* CMP 엔티니 빈의 경우 ejbCreate() 메소드와 대응되는 ejbPostCreate()메소드와의 관계 :
EJB 컨테이너는 빈 인스턴스의 ejbCreate()를 호출한 후 데이터베이스의 레코드를 해당
파라미터로 초기화하며 그 후에 ejbPostCreate()를 호출한다.
이 모든 것을 EJB 컨테이너가 관리해준다.

* CMP 엔티티 빈 클래스에서는 홈 인터페이스에서 선언된 findXXX()를 개발자가 구현할 필요가 없다.
디플로이먼트할 때 EJB 컨테이너가 자동으로 findXXX() 메소드를 구현해주기 때문이다.

* EJB 컨테이너가 데이터베이스와의 일체화(synchronization)을 자동화하기 때문에
ejbLoad(), ejbStore()의 중요성은 낮아진다. EJB 컨테이너가 빈 인스턴스의 상태정보인
속성 값을 해당 데이터베이스에 저장하고 읽는 과정을 자동으로 관리해준다.

1) EJB 컨테이너가 빈 인스턴스의 상태 정보를 해당 데이터베이스에 반영해야 한다고 판단하면
먼저 빈 인스턴스의 ejbStore() 메소드를 호출한다.
2) 그리고 컨테이너가 자동으로 빈 인스턴스의 속성 값을 해당 데이터베이스에 쓴다.
3) 그리고 다시 데이터베이스의 값을 읽어서 빈 인스턴스의 속성 값으로 할당한다.
4) ejbLoad()메소드를 호출한다.

② BMP 엔티티 빈의 빈 클래스 작성요령

* BMP 엔티티 빈의 빈 클래스 작성 요력은 CMP 엔티티 빈과 비슷하다. CMP 엔티티 빈과의 차이점 :
1) 데이터베이스와의 일체화를 위한 코드를 개발자가 직접
ejbLoad(), ejbStore()에 작성해야 한다는 것이다.
2) 홈 인터페이스의 findXXX()메소드들을 빈 클래스 안에서 개발자가 직접 구현해야 한다는 것이다.
3) 트랜잭션 처리도 직접 코딩해야 한다.

* 비즈니스 메소드 템플릿 : CMP 엔티티 빈의 경우와 동일

* EJB 컨테이너 규약 메소드 템플릿 :
1) CMP 엔티티 빈의 1), 2), 3)과 동일
2) findXXX() 관련 메소드

public <PrimaryKey> ejbfindByPrimaryKey(<PrimaryKey>)
throws [javax.ejb.FinderException,][java.rmi.RemoteException]
{
/* 구현 */
}

public Enumeration ejbfindXXX(<rmiParams>)
throws [javax.ejb.FinderException,][java.rmi.RemoteException]
{
/* 구현 */
}

* 구현 여부 : 반드시 javax.ejb.EntityBean 인터페이스를 구현한다.

* 주의할 내용 :
1) 위의 CMP 엔티티 빈의 "주의할 내용" 중 1),2),3),4),5)는 동일함
2) 홈 인터페이스에 선언된 findXXX() 메소드에 대응되는 ejbfindXXX()의 내부코드를 정의한다.
여러개의 엔티티 객체를 반환할 경우 java.util.Enumeration, Collection이
반환타입으로 사용된다.
3) ejbLoad(), ejbStore()에 해당 데이터베이스 테이블과 일체화하는 코드를 작성하여 구현한다.

* 다른 인터페이스들과의 관계 :
1) 위의 CMP 엔티티 빈의 1), 2)는 동일
2) 빈 클래스에 정의된 findXXX() 메소드들은 홈 인터페이스에서 선언되어 있어야 한다.

* Example>
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;

public class AccountEJB implements EntityBean
{
private String id;
private String firstName;
private String lastName;
private double balance;
private EntityContext context;
private Connection con;
private String dbName = "java:comp/env/jdbc/AccountDB";

// 중간 생략

public void credit(double amount)
{
balance += amount;
}

public String ejbCreate(String id, String firstName, String lastName, double balance)
throws CreateException
{
if( balance < 0.00 )
{
throw new CreateException("A negative initial balance is not allowed.");
}

try
{
insertRow(id, firstName, lastName, balance);
}
catch(Exception ex)
{
throw new EJBException("ejbCreate: " + ex.getMessage());
}

this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.balance = balance;

return id;
}

public String ejbFindByPrimaryKey(String primaryKey) throws FinderException
{
boolean result;

try
{
result = selectByPrimaryKey(primaryKey);
}
catch(Exception ex)
{
throw new EJBException("ejbFindByPrimaryKey: " + ex.getMessage());
}

if( result )
{
return primaryKey;
}
else
{
throw new ObjectNotFoundException("Row for id " + primaryKey + " not found.");
}
}

// 중간 생략

public void ejbLoad()
{
try
{
// 데이터베이스 테이블에서 값을 읽는다.
loadRow();
}
catch(Exception ex)
{
throw new EJBException("ejbLoad: " + ex.getMessage());
}
}

// 클래스 속성정보를 DB에 쓴다.
public void ejbStore()
{
try
{
storeRow();
}
catch(Exception ex)
{
throw new EJBException("ejbLoad: " + ex.getMessage());
}
}

/*********** DB 연결코드 ***************/
private void makeConnection() throws NamingException, SQLException
{
InitialContext ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup(dbName);
con = ds.getConnection();
}

// 이하 생략

}// class AccountEJB

* javax.ejb.EntityBean은 여러 메소드들이 선언되어 있다.
그렇지만 이 메소드들은 클라이언트가 직접 호출하여 사용하는 것이 아니라
EJB 컨테이너가 자동으로 호출한다.
따라서 이런 메소드들은 EJB 컨테이너와 빈 개발자와의 일종의 약속이기 때문에
"EJB 컨테이너 규약 메소드" 라고 한다.

javax.ejb.EntityBean
{
public void setEntityContext(EntityContext ctx)
: EntityContext 객체를 넘겨받아서 빈 인스턴스의 속성에 할당한다.
컨테이너가 빈 인스턴스를 생성한 직후에 호출한다.

public void unsetEntityContext()
: EntityContext 객체의 레퍼런스를 해제한다.
컨테이너가 인스턴스를 제거하기 전에 호출한다.

public void ejbRemove() : 컨테이너가 EJB 객체를 제거하기 전에 호출한다.
public void ejbActivate() : 빈 인스턴스가 "활성화"될 때 호출된다.
public void ejbPassivate() : 빈 인스턴스가 "비활성화"될 때 호출된다.
public void ejbLoad() : 데이터베이스로부터 값을 읽어서 빈 인스턴스의
상태 정보인 속성 값으로 할당해야 할 경우
컨테이너가 호출한다.
public void ejbStore() : 빈 인스턴스의 상태 정보가 DB안으로 저장되어야 할경우
컨테이너가 호출한다.
}

* 세션 빈처럼 엔티티 빈 클래스를 작성할 때 빈 클래스 개발자는 실제 빈 인스턴스가 생성된 후에
EJB 컨테이너가 현재 어떤 정보를 가지고 동작하는지 알지 못한다.
이런 정보를 빈 클래스 안에서 사용하기 위해서는 EJB 컨테이너가 생성한 EntityContext 객체
를 setEntityContext() 메소드로 받아서 속성으로 할당받은 다음 해당 정보를 얻을 수 있다.
EntityContext 객체가 제공하는 정보는 현재 빈 인스턴스와 연결되어 있는 "EJB객체의
레퍼런스"와 현재 빈 인스턴스의 "프라이머리 키 클래스의 객체"이다.

다. deployment
* 개발된 엔터프라이즈 빈을 클라이언트가 사용하려면 먼저 EJB 컨테이너 안에 플러그인 되어야 한다.
이과정을 "디플로이먼트"라고 하며 컨테이너의 종류에 따라 그 방법이 다르다.

* 빈 개발자가 개발한 엔터프라이즈 빈이 다른 사람 및 다른 EJB 컨테이너에서 Deployment되어 사용될 수
있기 때문이다. 그렇게 하기 위해서는 빈 개발자가 만든 엔터프라이즈 빈을 디플로이먼트 하는 사람이
소스 코드를 수정하지 않고도 여러 옵션을 줄 수 있어야 한다.
(DB네트워크주소, DB의 JDBC드라이버, ...)

라. 테스트용 클라이언트 프로그램 개발
* Example>
Context initialContext = new InitialContext();

// JNDI로 홈 객체의 레퍼런스를 얻음
CartHome cartHome = (CartHome) javax.rmi.PortableRemoteObject.
narrow(initialContext.lookup("java:comp/env/ejb/cart"), CartHome.class);

Cart cart = cartHome.create("John", "7506");

// 비즈니스 메소드 호출
cart.addItem(96);
cart.purchase();

* JNDI로 홈 객체를 찾을 때 EJB 컨테이너 업체(웹로직, 웹스피어등)에서 제공하는 라이브러리를 사용한다.
자세한 것은 EJB 컨테이너 업체에서 제공하는 매뉴얼을 봐야 한다.

5. JNDI
* Example>

import javax.naming.*;
public static Context getInitialContext() throws NamingException
{
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
p.put(Context.PROVIDER_URL, "t3://localhost:7001");
return new InitialContext(p);
}

InitialContext ic = new InitialContext();
Object objref = ic.lookup("java:comp/env/ejb/Cart");
CartHome home = (CartHome)PortableRemoteObject.narrow(objref, CartHome.class);

* JNDI 주요 환경변수
------------------------------------------------------------------------------
환경 변수 상수 선언
------------------------------------------------------------------------------
java.naming.factory.initial Context.INITIAL_CONTEXT_FACTORY
컨텍스트 팩토리(Context Factory)의 클래스명으로 서비스 제공자에 의해 제공되는 이름

java.naming.factory.object Context.OBJECT_FACTORIES
디렉토리 서비스 안에 저장된 객체를 위해 클래스 팩토리처럼 행동하는 클래스명의 리스트

java.naming.provider.url Context.PROVIDER_URL
서비스 제공자의 구성 정보

java.naming.security.principal Context.SECURITY_PRINCIPAL
서비스 제공자를 사용하기 원하는 Principal의 ID

java.naming.security.credentials Context.SECURITY_CREDENTIALS
Principal의 패스워드
6. JDBC
* 데이터 소스와의 커넥션을 생성
* 질의 구분 및 수정 구분을 전송
* 결과 처리

* Example>
Connection con = DriverManager.getConnection("jdbc:myDriver:wombat", "myLogin", "myPassword");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM table1");
while( rs.next() )
{
int x = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
}

(1) JDBC 드라이버의 종류
가. JDBC-ODBC 브리지(bridge)드라이버
나. 데이터베이스 API(A Native-API partly-java) 드라이버
- JDBC API 호출을 특정 데이터베이스의 클라이언트 호출 API로 바꿔주는 드라이버이다.

다. 네트워크 프로토콜(A net-protocol all-java) 드라이버
- 클라이언트는 JDBC API 호출을 특정 데이터베이스의 프로토콜과 전혀 상관없는
독자적인 방식의 프로토콜로 바꾸어 서버로 전송한다.
- 이 드라이버는 보통 자바언어로 만들어진다.
- 서버에서는 미들웨어가 있어서, 그 프로토콜을 특정 데이터베이스의 API로 바꾸어서 처리한다.

라. 데이터베이스 프로토콜(A Native-protocol all-java) 드라이버
- JDBC API 호출을 서버의 특정 데이터베이스에 맞는 프로토콜로 변환시켜 서버로 전송하는 드라이버
- '나'의 드라이버와 비슷하나, 클라이언트의 API로 변환하는 것이 아니라 직접 서버의
데이터베이스로 요청 한다는 것이 다르다.
- 데이터베이스의 생산업체가 직접제공(특정 DB프로토콜로 직접 변환시켜야 하므로 해당 업체만이 만들 수 있기 때문)


(2) JDBC 2.0 API의 새로운 기능

가. 스크롤 가능한 ResultSet

ResultSet rs = stmt.executeQuery("SELECT * FROM committees");
while( rs.next() )
{}
...
rs.absolute(5); // 커서를 5번째 레코드로 이동한다.
...
rs.relative(-2); // 커서를 3번째 레코드로 이동한다.
...
rs.relative(4); // 커서를 7번째 레코드로 이동
...
rs.previous(); // 커서를 6번째 레코드로 이동
...
int rowNumber = rs.getRow(); // rowNumber는 6이 반환된다.

나. 일괄수정(Batch Updates)

con.setAutoCommit(false);
Statement stmt = con.createStatement();
stmt.addBatch("INSERT INTO employees VALUES(1000, '홍길동')");
stmt.addBatch("INSERT INTO employees VALUES(260, '구매부')");
stmt.addBatch("INSERT INTO employees VALUES(1000, '260')");
int [] updateCounts = stmt.executeBatch();

다. API를 통한 수정(Programmatic Updates)
* updateXXX(), getXXX(), setXXX()

* rs.absolute(4); //커서를 네번째 레코드로 옮김
rs.updateString("ADDRESS", "서울 서초구"); // ADDRESS필드를 "서울 서초구"로 변경
rs.updateFloat("AMOUNT", 10101.0f); // AMOUNT 필드를 10101.0f로 변경
rs.updateRow(); // 수정구문을 DB로 보냄

* rs.moveToInsertRow(); // 새로운 레코드를 삽입하기 위해 커서를 insert row라는 특수위치로 옮김
rs.updateObject(1, myArray); // 1번째 필드를 myArray를 값으로 가진다.
rs.updateInt(2, 3857); // 2번째 필드는 3857를 값으로 가진다.
rs.updateString(3, "Mysteries"); // 3번째 필드는 "Mysterious"를 값으로 가진다.
rs.insertRow(); // 데이터베이스로 전송
rs.first(); // 커서를 ResultSet으로 옮긴다.

* rs.first(); // 레코드를 삭제하기 위해서 삭제하고자 한느 레코드로 커서를 옮김
rs.deleteRow(); // 1번째 레코드를 삭제

라. 새로운 데이터 타입에 대한 지원

* JDBC 2.0 API는 새로운 SQL3 데이터 타입을 JDBC 인터페이스에 매핑하여 기본 데이터 타입처럼
쉽게 사용할 수 있는 기능을 제공한다.

* ResultSet rs = stmt.executeQuery("SELECT members FROM committees "
+ "WHERE comm_name = 'finance'");
rs.next();
Array financeMembers = rs.getArray("members");

financeMembers 변수는 회원들의 이름 데이터 자체를 포함하고 있는 것이 아니며,
단지 서버에 존재하는 이름 데이터에 대한 논리적 포인터를 값으로 가지고 있을 뿐이다.
이는 모든 이름들을 배열에 담아 클라이언트로 가져옴으로써 발생될 수 있는 오버해드 없이
financeMembers 변수를 마치 SQL ARRAY 자체를 사용하는 것처럼 조작할 수 있음을 띃나다.
데이터베이스에 이름의 배열을 저장하기 위해서는 PreparedStatement의 setArray 메소드를
통해서 financeMembers 변수를 넘겨주기만 하면 된다.

* BLOB, CLOB도 같은 방식으로 동작한다.

(3) JDBC 2.0 Standard Extension API
가. JNDI를 이용한 DataSource 인터페이스

* DataSource 인터페이스는 DriverManager 클래스를 대신해서 데이터 소스와의 커넥션을 생성하는데 사용될 수 있다.
* DataSource 인터페이스를 구현한 클래스를 사용한 코드는 더 포터블해지며, 유지보수는 더 쉬워진다.
* DataSource 에 대한 정보는 DataSource 객체에 프로퍼티 형식으로 저장된다.
* 특정 드라이버 업체명과 서버의 주소 등을 코드로 작성해야 하는 DriverManager클래스를 이용하는 클래스보다
DataSource 객체를 이용한 코드가 더 포터블하다.
* DataSource 가 다른 서버로 옮겨졌을 경우 관련된 프로퍼티만 수정하면 되므로 유지보수가 편리

* Example>
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/InventoryDB");
Connection con = ds.getConnection("myPassword", "myUserName");

나. Connection pooling
* DataSource.getConnection() 메소드에 의해 반환된 커넥션이 커넥션 풀링을 사용하는지의 여부는
전적으로 해당 DataSource의 구현에 달려있다. 해당 DataSource 클래스가 커넥션 풀링을 지원하는
middle tier서버와 함께 사용되도록 구현되었다면 DataSource 객체는 풀링을 지원하며
재사용되는 Connection 객체를 반환할 것이다.
* 풀링된 커넥션을 가져오는 코드가 동일한 것처럼, 풀링된 커넥션을 사용하는 코드도 다를 것이 없다.
단 한가지 차이점이라면 커넥션을 finally 블록에서 반드시 닫아야 한다.
이렇게 해야만 예외가 발생해도 커넥션은 닫혀지고 커넥션 풀로 돌아갈 수 있다.

}
finally
{
if( con != null )
try
{
con.close();
}
catch(SQLException)
{}
}

다. 분산 트랜잭션

라. RowSet

7. RMI
* 소켓 프로그래밍 :
- 데이터를 주고 받기 위해서는 저차원적인 일들(네트워크 연결, 소켓 생성등)까지 코딩 해야함

* RPC(Remote Procedure Call) :
- 네트워크로 연결된 다른 컴퓨터에 있는 함수를 마치 자신의 컴퓨터내에 있는 함수처럼 호출하고 그 결과값을 반환받음.

* RMI(Remote Method Invocation) :
- RPC는 함수를 호출하는 것이기 때문에 객체 지향 언어에서는 구현하기가 부적합.
(왜나하면 객체 지향 언어에서는 함수란 개념이 없고 객체의 메소드란 개념이 그것을 대체하기 때문)
- RPC의 장점을 십분 살려 분산 객체 APP을 쉽게 만들 수 있는 개념
- 분산객체APP : 네트워크로 연결된 컴퓨터들 안에 있는 객체들이 서로의 메소드를 호출하며 한 목표를 향해 동작하는
시스템을 의미

(1) RMI 및 자바 분산 객체 모델
* RMI의 구조는 3계층으로 나누어 구성된다.
stub / skeleton
---------------
Remote Reference Layer
----------------------
Transport

가. stub / skeleton
* stub : 리모트 객체를 나타내는 클라이언트 부분
* skeleton : 리모트 객체를 나타내는 서버쪽 부분

나. Remote Reference Layer
* 리모트 레퍼런스의 메타 정보를 전달
(Client의 stub과 Server의 skeleton과 독립적인 RMI메소드 호출에 관한 메타 정보를 전달하는 역할)

다. Transport
* 리모트 객체외의 네트워크 연결 및 관리와 추적 기능을 담당

(2) RMI의 구조
가. 파라미터와 반환값 처리
* 리모트 객체의 메소드의 반환값, 파라미터로 어떤 타입도 사용될 수 있다.
단, 객체가 사용될 경우, 반드시 java.io.Serializable 인터페이스를 구현한 것이어야 한다.

나. 예외 처리
* 리모트 객체의 메소드를 호출할 때 에러가 발생하면, 그 정보는 java.rmi.RemoteException클래스에 저장된다.

다. RMI를 구현하기 위한 클래스와 인터페이스
* 개발자는 java.rmi, java.rmi.server 패키지의 클래스와 인터페이스를 주로 사용한다.

① java.rmi.Remote interface
* 모든 리모트 인터페이스는 직접, 간접으로 반드시 java.rmi.Remote interface를 상속해야 한다.
* Remote interface는 어떤 메소드도 선언된 것이 없다.

public interface Remote{}

* Example>
public interface BankAccount extends Remote
{
public void deposit(float amount) throws java.rmi.RemoteException;
public void withdraw(float amount) throws OverdrawnException, java.rmi.RemoteException;
public float balance() throws java.rmi.RemoteException;
}

* 리모트 인터페이스의 모든 메소드는 반드시 throws문을 통해
java.rmi.RemoteException을 예외처리 해야함.
* 메소드의 반환값, 파라미터로 리모트 객체가 쓰일때, 그 타입은 리모트 인터페이스를 구현한
클래스 타입이 아니라 리모트 인터페이스 타입이어야 한다.

② java.rmi.RemoteException class
* RMI 실행중에 발생하는 모든 예외를 나타내는 클래스들의 최상위 클래스.
* RMI 기능을 사용하는 모든 메소드는 반드시 이 예외를 throws문으로 예외 처리할 수 있음을 선언해야함.

③ java.rmi.server.RemoteObject class
* 리모트 객체의 기능은 이 클래스와 또는 하위 클래스인 java.rmi.server.RemoteServer,
java.rmi.server.UnicastRemoteObject에 의해서 제공받는다.

* java.rmi.server.RemoteObject :
- 리모트 객체가 갖추어야 할 기본적인 메소드(hashcode().toString()등)를 정의한다.

* java.rmi.server.RemoteServer :
- 리모트 객체를 생성하고 등록할 수 있는 기능을 메소드로 정의한다.
- 추상클래스이므로 상속받은 하위 클래스들이 메소드를 구현한다.

* java.rmi.server.UnicastRemoteObject :
- 서버 프로세스가 동작할 때만 실행할 수 있는 싱글 리모트 객체
- 개발자 대부분은 이 클래스를 사용

④ 리모트 인터페이스를 구현하기 위한 규칙
㉠ java.rmi.server.UnicastRemoteObject를 상속받는다
RemoteServer, UnicastRemoteObject 클래스의 모든 속성과 메소드를 사용할 수 있다.

㉡ 1개 이상의 리모트 인터페이스를 구현 할 수 있다
㉢ 리모트 인터페이스를 구현한 다른 클래스를 상속받을 수 있다는 점
㉢ 리모트 인터페이스에 선언되어 있지 않은 메소드를 정의할 수 있는 점,
하지만 클라이언트는 호출할 수 없고, 로컬에서만 호출가능

* Example>
import java.rmi.*;
import java.rmi.server.*;
public class BankAccountImpl extends UnicastRemoteObject implements BankAccount
{
public void deposit (float amount) throws RemoteException(...}
public void withdraw (float amount) throws OverdrawnException, RemoteException{...}
public float balance() throws RemoteException{...}
}
(3) EJB에서의 RMI
* 엔터프라이즈 자바빈즈는 RMI/IDL CORBA 기술을 분산 객체 모델의 구현을 위해 기반 기술로 채택하고 있다.
* RMI-IIOP는 J2EE플랫폼의 구성요소로써 CORBA IDL(Inferface Definition Language)을 배우지 않고
자바 플랫폼에서 동작하는 CORBA 응용프로그램을 작성할 수 있는 기능을 제공하며
CORBA ORB의 모든 기능을 포함하고 있다.
* RMI는 EJB 아키텍처에서 통신의 근간을 이루고 있다.

8. EJB 아키텍처의 역할 분담
(1) 엔터프라이즈 빈 제공자(Enterprise Bean Provider)
(2) 애플리케이션 조립자(Application Assembler)
(3) 배치자(Deployer)
(4) EJB 서버 제공자(EJB Server Provider)
(5) EJB 컨테이너 제공자(EJB Container Provider)
(6) 시스템 관리자(System Administrator)
9. 세션 빈(Session Bean)
(1) 무상태 빈(stateless bean)의 내부동작 과정

------------------------------------------------------------
존재하지 않는 상태

1. newInstance()
2. setSessionContext(sc) ↓ ↑ ejbRemove()
3. ejbCreate()
메소드 준비 풀
------------------------------------------------------------

* 무상태 세션 빈은 상태관리가 필요없기 때문에 활성화/비활성화 상태를 갖지 않는다.
* 무상태 세션 빈의 생명주기
① EJB 컨테이너가 세션 빈 클래스의 객체인 빈 인스턴스를 생성
② 빈 인스턴스가 생성되면 컨테이너는 setSessionContext() 메소드를 호출한 후 ejbCreate()메소드를 호출한다.
이는 클라이언트의 create() 메소드 호출과는 상관없다.
③ 컨테이너가 더 이상 빈 인스턴스를 필요로 하지 않으면 EJB 컨테이너가 스스로 ejbRemove()메소드를 호출한다.
가. 풀에 빈 인스턴스를 할당하는 과정
* 클라이언트가 EJB 객체의 비즈니스 메소드를 호출할 때 빈 인스턴스가 생성되어 있지 않으면
EJB 컨테이너에 의해 새로운 빈 인스턴스가 생성되고 setSessionContext(), ejbCreate()가 호출된다.
* 이미 풀에 해당 인스턴스가 존재하면 두 메소드는 호출되지 않고, 이미 생성되어 풀에 있는 빈 인스턴스를 사용한다.

나. 클라이언트가 create() 메소드를 호출했을 때
* 클라이언트가 create() 메소드를 호출해도 실제 빈 인스턴스가 생성되거나 ejbCreate()가 호출되는 것이 아니라
EJB 객체를 생성하는 것이다.
* EJB 객체는 EJB 컨테이너에 의해 적당한 빈 인스턴스와 연결된다.
이때 EJB 컨테이너는 빈 인스턴스를 풀에서 꺼내거나 또는 새롭게 생성한다.

다. 클라이언트가 비즈니스 메소드들을 호출했을 때
* 클라이언트가 비즈니스 메소드를 호출하면 EJB 객체를 통하여 해당 빈 인스턴스의 비즈니스 메소드가 호출된다.

* 클라이언트에 의해 실행되는 모든 비즈니스 메소드는 다음의 순서로 동작한다.(웹로직인 경우)
① EJB 컨테이너가 빈 인스턴스를 풀에서 꺼낸다.
② 메소드는 빈 인스턴스에 의해 실행된다.
③ EJB 컨테이너가 빈 인스턴스를 풀로 반환한다.

라. 클라이언트가 remove() 메소드를 호출했을 때
* 클라이언트가 EJB 객체의 remove() 메소드를 호출해도 실제 풀에서 인스턴스가 삭제되지는 않는다.
* 일단 EJB 컨테이너에게 삭제한다는 메시지를 보내고 추후 적당한 시기에 삭제되는 것이다.
* 무상태 세션 빈은 하나의 빈 인스턴스가 여러 클라이언트에 의해 사용될 수 있으므로,
실제 풀에서 제거되지 않고 일단 풀에서 대기 하게 된다.
* 더이상 사용되지 않는 빈 인스턴스는 EJB 컨테이너가 자동으로 제거한다.
* remove()를 호출하면 클라이언트는 세션 빈을 더 이상 사용할 수 없다.

마. 풀에서 빈 인스턴스를 제거하는 과정
* EJB 컨테이너가 더 이상 빈 인스턴스가 필요하지 않거나, 유휴 대기시간을 초과하면
EJB 컨테이너가 스스로 ejbRemove()를 호출하여 풀에서 인스턴스를 제거한다.
(2) 상태유지 빈(stateful bean)

가. 풀에 빈 인스턴스를 할당하는 과정
* 무상태 세션 빈의 내용과 동일하나, 메소드 준비 풀이 상태유지 세션 빈에서는 메소드 준비 상태(활성화 상태)가 된다.
* 무상태 세션 빈과 달리, 상태유지 세션 빈은 클라이언트가 홈 객체의 create()를 호출하는 순간 빈 인스턴스가 생성된다.
왜냐하면 각 클라이언트마다 상태정보를 유지 하기 위해 해당 클라이언트를 전담하는 독립적인 빈 인스턴스가
각각 존재해야 하기 때문

나. 클라이언트가 create() 메소드를 호출했을 때
* 클라이언트가 상태유지 세션 빈의 create() 메소드를 호출하면 상태유지 세션 빈의 생명주기가 시작된다.

다. 클라이언트가 비즈니스 메소드들을 호출했을 때
* 상태 세션 빈의 인스턴스는 클라이언트에 종속되기 때문에 풀에서 빈 인스턴스를 가져오거나 반환할 필요가 없다.

라. 활성화/비활성화될 때
* 컨테이너에 의해 어떤 빈 인스턴스가 비활성화될 것인지 결정된다.
* 비활성화될 빈 인스턴스는 LRU(Least Recently Used)에 의해서 선택되어
컨테이너는 비활성화될 빈 인스턴스의 ejbPassivate() 메소드를 호출하고,
작업이 완료되면 컨테이너는 빈 인스턴스의 상태를 객체직렬화(serialization)를
통해 보조 기억 장치에 저장한다.
* 빈이 비활성화된 상태에서 클라이언트가 EJB 객체의 비즈니스 메소드를 호출하면
컨테이너는 빈 인스턴스를 활성화시킨다.
이때, 컨테이너는 보조 기억 장치에서 빈 인스턴스의 상태를 읽어오고
ejbActivate() 메소드를 호출하여 활성화 상태로 만든다.

마. 클라이언트가 remove() 메소드 호출 및 빈 인스턴스 제거할 때
* 클라이언트가 remove() 메소드를 호출하면 ejbRemove() 메소드가 호출되어 빈 인스턴스를 제거한다.
* 무상태 세션 빈은 클라이언트가 remove() 호출할 때 풀에 남아 다른 클라이언트의 호출에 대기하지만
상태유지 세션 빈은 각각의 클라이언트의 상태를 가지고 있기 때문에
상태유지 세션 빈의 생명주기는 여기서 종료된다.
10. 엔티티 빈(Entity Bean)
* 엔티티 빈은 데이터베이스와 같은 영속적인 저장 메커니즘에 저장되어 있는 비즈니스 객체를 나타낸다.
* 세션 빈이 EJB를 통해 구현하고자 하는 비즈니스 로직을 담고 있다면,
엔티티 빈은 이 비즈니스 로직의 구현에 필요한 각종 데이터들과 대응되는 데이터베이스에서
영속적으로 유지되어야 하는 정보(persistent information)들과의 연동을 담당하고 있다.

(1) CMP(Container Managed Persistence)
* EJB 컨테이너가 자동으로 영속성 관리
* DB내의 엔티티 빈 인스턴스와 관련된 데이터를 자동으로 추가/삭제/변경한다.

가. 장점
* 개발이 용이하고 코드의 크기가 줄어든다.
영속성에 대한 관리 자체를 EJB 컨테이너가 해결해 주기 때문에,
개발자는 비즈니스 로직에만 집중하여 개발할 수 있기 때문이다.
따라서, 개발자는 개발한 빈을 디플로이먼트할 때 엔티티 빈의 어떤 필드가 EJB 컨테이너에 의해 관리되고
데이터베이스에 대응되는지 지정해 주기만 하면 된다.
이와 같은 작업만 마치면, 컨테이너는 빈의 모든 영속성 작업에 필요한 코드를 자동으로 생성한다.

* 빈이 자신의 상태를 저장하는데 사용하는 데이터베이스와 독립된다는 것이다.
즉, CMP 기반 엔티티 빈은 관계형 또는 객체 지향 데이터베이스의 장점을 모두 이용할 수 있다.
또한, 이와 같은 특징 때문에 빈에 대한 응용프로그램간의 재사용성과 유연성이 높아질 수 있게 된다.

나. 단점
* 빈의 필드를 데이터베이스에 대응시킬 때 BMP에 비해 정교함이 떨어진다.
즉, 정교하게 CMP 엔티티 빈과 DB를 대응시키시 위해서는 훨씬 강력한 툴을 요구한다.
예를 들어, 특정 빈의 상태는 복잡한 관계형 DB의 join연산으로 정의될 수 있다.
또한, CICS나 IMS와 같은 기존의 시스템에 대응될 수도 있다.
실제 CMP 기반으로 엔티티 빈을 설계할 때는 여러 가지 제약사항이 뒤따른다.

다. 리모트 인터페이스
① 반드시 javax.ejb.EJBObject 인터페이스를 상속받아야 하며
② 엔티티 빈에 있는 모든 비즈니스 메소드는 반드시 리모트 인터페이스 내에 그 정의가 포함되어야 하고
빈 클래스의 비즈니스 메소드에 있는 대응되는 메소드와 메소드 형태(반환값 및 전달 파라미터)가 동일해야 한다.
③ 모든 비즈니스 메소드는 반드시 java.rmi.RemoteException을 throws절에 포함해야 하며 사용자가 정의하는
비즈니스 예외 클래스를 추가적으로 포함할 수 있다.
④ 리모트 인터페이스 내에 포함되는 모든 비즈니스 메소드의 전달 파라미터들과 반환 값은 반드시 유효한 RMI호환형
이어야 한다.

라. 홈 인터페이스
① 엔티티 빈의 생명주기에 관련된 메소드들을 제공한다.
EJB 시스템에서 EJB 객체를 생성하고, 찾고, 삭제하는데 사용된다.
② 홈 인터페이스는 한개 이상의 create 메소드(아예 정의되지 않을 수도 있음)와 하나 이상의 find 메소드를 정의한다.
③ EJB 홈 인터페이스는 반드시 javax.ejb.CreateException을 포함해야 하는데
CMP의 경우 컨테이너는 생성 과정에서 유발되는 통신 문제에 대해 일반적인 예외 처리가 필요한다.

public interface <홈 인터페이스 이름> extends javax.ejb.EJBHome
{
/**
* 0 또는 한개 이상의 create 메소드가 정의될 수 있다.
*/
public <리모트 인터페이스> create(<다양한 초기화 인자들...>)
throws [<사용자 정의 예외>,]...
java.rmi.RemoteException,
javax.ejb.CreateException;

/**
* 반드시 정의되어야 하는 findByPrimaryKey 메소드
*/
public <리모드 인터페이스> findByPrimaryKey(<프라이머리키 형 또는 프라이머리키 클래스의 인스턴스>)
throws [<사용자 정의 예외>,]...
java.rmi.RemoteException,
javax.ejb.FinderException;

/**
* 비즈니스 로직에 필요에 의해 부가적으로 정의될 수 있는 find 메소드들
*/
public <리모트 인터페이스형 or 집합형> findByRange(...)
throws ...;

...
}

④ 홈 인터페이스의 create 메소드는 다음과 같은 조건을 만족해야 한다.

* 엔티티 빈의 홈 인터페이스는 0 또는 한 개 이상의 create 메소드
(각각은 저마다의 방법으로 엔티티 객체를 생성한다.)를 정의할 수 있다.
일반적으로 create메소드들의 전달 파라미터는 생성된 엔티티 객체들의
상태(state)를 초기화하는데 사용된다.

* create 메소드의 반환 값은 엔티티 빈의 리모트 인터페이스이며 대응되는 빈 클래스에 위치한
ejbCreate메소드와 동일한 수, 형태의 전달 파라미터를 가져야 한다.

* 모든 create 메소드의 throws절은 java.rmi.RemoteException과 javax.ejb.CreateException을
포함하고 있다. 또한, 응용프로그램 차원에서 제공되는 예외들을 추가로 포함할 수 있다.

⑤ 홈 인터페이스의 find 메소드의 형태들은 반드시 다음과 같은 조건을 만족하도록 작성되어야 한다.

* 홈 인터페이스에 있는 모든 find 메소드는 빈 클래스에 있는 find 메소드와 대응된다.
홈 인터페이스에 정의된 find 메소드의 이름은 find로 시작되는 반면에
빈 클래스에 있는 것들이 이름은 ejbFind로 시작한다.
예를 들어, 홈 인터페이스에서 findInRange()라는 메소드를 선언했다면,
빈 클래스는 ejbFindInRange()라는 이름으로 메소드를 구현한다.

* 전달 파라미터의 개수와 형태는 빈 클래스에 있는 대응되는 메소드의 것들과 동일해야 한다.

* 반환 값은 엔티티 빈의 리모트 인터페이스형이거나 그런 형태들의 Enumeration type(나열형)이다.

* throws절의 예외들은 빈 클래스의 대응되는 메소드에 나타나 있는 것을 포함해야 한다.

* throws절은 javax.ejb.FinderException과 java.rmi.RemoteException을 담고 있다.

마. 컨테이너 관리 필드(Container managed field)

* 엔티티 빈이 CMP 기반이거나 BMP 기반이거나에 관계없이 리모트 인터페이스와 홈 인터페이스는 동일하다.
하지만 빈 클래스에 있는 코드는 당연히 CMP와 BMP가 서로 다르다.
CMP의 빈 클래스는 어떤 DB 접근/제어 코드도 가지고 있지 않다.
deploy tool이 deploy할 때 필요한 SQL 구문들을 자동으로 생성해 준다.
deploy tool이 DB에 저장되어야 하는 빈 인스턴스의 속성들을 알아야 한다.
이런 속성들을 컨테이너 관리 필드라고 한다.

* 컨테이너 관리 필드는 반드시 public으로 선언되어야 하며 임시적인 것이어서는 안된다.

* 직렬화(serializable) 클래스, 기본형 자료형(primitive type),
홈 인터페이스에 대한 레퍼런스 또는 리모트 인터페이스에 대한 레퍼런스 중 하나의 형태여야 한다.

* deploy tool을 사용할 때, 하나 이상의 컨테이너 관리 필드를
엔티티 빈의 프라이머리 키 필드로 반드시 선언해야 한다.

바. 빈 클래스 구현

* EntityBean 인터페이스를 구현한다.
* 클래스는 abstract나 final로 선언될 수 없고 반드시 public으로 선언되어야 한다.
* 한 개 이상의 ejbCreate와 ejbPostCreate 메소드를 구현한다.
* BMP 엔티티 빈일 경우에는 find 메소드를 구현해야 한다.
* 애플리케이션이 요구하는 비즈니스 메소드를 구현한다.
* 파라미터가 없는 생성자(empty constructor)를 가지고 있다.
* finalize 메소드를 구현하지 않는다.

사. EntityBean 인터페이스

아. ejbCreate()
* 클라이언트가 create()를 호출할 때, EJB 컨테이너가 호출하는 대응 되는 메소드

① 하는 일
* DB에 엔티티 상태를 삽입
* 빈 인스턴스 속성을 초기화 한다.
* primary key를 반환한다.

* ejbCreate()는 입력 전달 파라미터로 들어오는 컨테이너 관리 필드들을 초기화한다.
이 메소드는 반환 값으로 널(null)값을 가지는데 그 이유는 CMP기반의 경우
컨테이너가 반환 값을 무시하기 때문

public String/* <= */ ejbCreate(String productId, String description, double price)
{
if( productId = null )
{
throw new CreateExceptin("The productId is required");
}

this.productId = productId;
this.description = description;
this.price = price;

return null;// <= 리턴타입과 실제 리턴값이 다르다
}

② 작성 규칙
* 메소드의 접근 제어 지정자(access control modifier)는 반드시 public이어야 한다.
* 반환형은 반드시 프라이머리 키여야 한다.(BMP일 경우에만)
* 파라미터는 반드시 Java RMI에 적합한 형태여야 한다.
* 메소드 지정자(method modifier)는 final이나 static이 될 수 없다.

자. ejbPostCreate()
① 각각의 ejbCreate()에 대해, 빈 클래스에 ejbPostCreate()를 작성해야 하는데,
일반적으로 ejbPostCreate()는 내부가 비어있는 empty 메소드로 남아있다.

② EJB 컨테이너는 ejbCreate()를 호출한 바로 직후에 ejbPostCreate()를 호출한다.
ejbCreate()와는 다르게, ejbPostCreate()는 EntityContext 인터페이스의
getPrimaryKey()와 getEJBObject()를 호출할 수 있다.

③ 메소드 작성 규칙
* 전달 파라미터의 개수와 형태는 대응되는 ejbCreate()와 동일해야 한다.
* 메소드의 접근 제어 지정자(access control modifier)는 반드시 public이어야 한다.
* 메소드 지정자는 final이나 static이 되어서는 안된다.
* 메소드의 반환형은 반드시 void형이어야 한다.

차. ejbRemove()
* Client가 remove()를 호출하면, 컨테이너는 ejbRemove()를 호출한다.
* ejbRemove()의 실행이 완료되면, 컨테이너는 DB에서 해당 레코드(row)를 삭제한다.
즉, Client는 remove()를 호출하여 엔티티 빈을 삭제하게 되는 것이다.
만일 엔티티 빈이 삭제하기 전에 즉각적인 어떤 처리가 필요하다면 ejbRemove()에서 하면 된다.
* 만일 ejbRemove()가 시스템 문제에 부딪히면, javax.ejb.EJBException을 발생시킨다.
반면 애플리케이션 에러에 부딪히게 되면 javax.ejb.RemoveException을 발생시킨다.
또한 엔티티 빈은 직접적인 DB 삭제에 의해 직접적으로 삭제될 수 있다.
(SQL 스크립트가 직접적인 엔티티 빈의 상태를 저장하고 있는 레코드를 삭제하면,
그 엔티티 빈은 삭제되는 것이다.)

카. ejbLoad() / ejbStore()
* EJB 컨테이너가 엔티티 빈의 인스턴스 속성과 DB에 저장되어 있는 대응 값을 동기화 할 필요가 있다며,
EJB 컨테이너는 ejbLoad()와 ejbStore()를 호출하게 되며,
클라이언트에서 ejbLoad()나 ejbStore()를 직접적으로 호출하는 것은 불가능한다.

① ejbLoad() 호출순서
* DB에서 재설정하고자 하는 엔티티 빈에 해당하는 레코드를 가져온다.
* 가져온 레코드의 각 칼럼 값을 대응하는 각 컨테이너 관리 필드에 할당
* ejbLoad() 호출

② ejbStore() 호출순서
* ejbStore() 호출
* 컨테이너 관리 필드들의 값들을 읽어온다.
* 해당 엔티티 빈에 대응되는 DB 레코드의 각 칼럼값들을 읽어온 컨테이너 관리 필드 값들로 대체한다.

타. find()들
* CMP 기반의 엔티티 빈에서는 컨테이너가 홈 인터페이스에 정의된 find 메소드들을 자동으로 구현해주기
때문에 이 find()들을 개발자가 직접 구현할 필요가 없다.

파. Primary Key
* 프라이머리 키는 빈의 형태, 홈 인터페이스, 그리고 프라이머리 키가 사용되는
컨테이너 컨텍스트(container context)에 따라 엔티티 빈을 유일하게 구분하는 구분자이다.
* Primary Key가 기본형 타입(primitive type)일지라도 프라이머리 키 클래스를 구현해 놓으면
차후 애플리케이션의 확장이나 DB 및 테이블의 변동에서 오는 영향을 최소화시키고,
빈의 find 메소드들을 좀 더 유연하고 융통성 있게 만든다.
* Primary key 클래스 반환 값의 형태는 반드시 RMI-IIOP에 적합한 값의 형태이어야 한다.
* Primary Key 클래스는 클라이언트 프로그램의 프라이머리 키를 간단히 관리하기 위해
hashCode(), equals(Object other)를 제공해야 한다.

* Example>

import java.io.Serializable;
public class ProductPK implements java.io.Serializable
{
public String productId;

public ProductPK(){}

public ProductPK(String _Id)
{
productId = _Id;
}

public boolean equals(Object obj)
{
if( obj == null || !(obj instanceof ProductPK) )
{
return false;
}
else if( ((ProductPK)obj).productId.compareTo(productId) == 0 )
{
return true;
}
else
{
return false;
}
}

public String hashCode()
{
return productId;
}
}

하. 객체의 동일성 체크
① 클라이언트는 isIdentical()을 통해서 두개의 엔티티 빈에 대한 EJB 객체 레퍼런스(Object reference)가
동일한지 비교할 수 있다.

Account accta, acctb;
...
if( accta.isIdentical(acctb) )
{
System.out.println("identical");
}

② 또한, 두 엔티티 빈의 프라이머리 키를 비교하여 구분할 수도 있다.

String key1 = (String)accta.getPrimaryKey();
String key2 = (String)acctb.getPrimaryKey();
if( key1.compareTo(key2) == 0 )
{
System.out.println("equal");
}

③ 어떤 엔티티 빈을 다른 엔티티 빈에서 사용하고자 할 때
* 사용하고자 하는 엔티티 빈에 대한 레퍼런스를 사용할려는 빈에 전달하는 방법
즉, 엔티티 빈에 대한 객체 레퍼런스(Object reference)를 전달하는 방법.

public void setEntityContext(EntityContext ec)
{
this.context = ec;
}

...

public void passItOn(Inventory tally)
{
// EntityContext에 있는 getEJBObject()를 호출하여 EJB객체의 레퍼런스를 얻어오는 과정
tally.copyItems(context.getEJBObject());
}

가.가. 엔티티 빈의 생명주기

존재하지 않는 상태
newInstance() | |
setEntityContext()↓ ↑ unsetEntityContext()
| |
┌--------------- 풀링된 상태 <-------------┐
1. create() | | 1. remove()
2.ejbCreate() | ejbActivate() ↓ ↑ ejbPassivate() | 2. ejbRemove()
3.ejbPostCreate()| ejbLoad() ejbStore() |
| |
└--------------> 준비 상태 --------------┘

* 엔티티 빈의 생명주기는 응용프로그램에 의해 결정되는 것이 아니라 EJB 컨테이너에 의해 결정된다.
* EJB 컨테이너는 엔티티 빈 인스턴스를 생성하고 나서 빈 클래스에 있는 setEntityContext()를 호출한다.
* setEntityContext()는 entity Context를 빈에 전달한다.

[인스턴스化된 이후]
* 엔티티 빈은 가용 인스턴스 풀(a pool of available instances)에 들어가게 된다.
인스턴스 풀 상태에는 어떤 EJB 객체와도 연관되어 있지 않다.
풀에 있는 모든 인스턴스들은 다 동일하다.

[EJB 컨테이너가 인스턴스를 준비 상태로 이동]
* 비로소 인스턴스는 EJB 객체와 연동하게 되는 것이다.

[인스턴스가 준비 상태에서 풀링된 상태로 변하는 경우]
① 클라이언트가 remove()를 호출하는 경우로 이때 EJB 컨테이너는 ejbRemove()를 호출
② EJB 컨테이너가 ejbPassivate()를 호출하는 경우

[unsetEntityContext()]
* 풀링된 상태에서 인스턴스는 어떤 EJB 객체와도 연동하지 않음.

* 참고사항 1
BMP(Bean-Managed Persistence) 기반 엔티티 빈에서는
EJB 컨테이너가 인스턴스를 풀링된 상태에서 준비 상태로 이동시킬 때,
인스턴스는 프라이머리 키를 자동으로 설정하지 않는다.
따라서, ejbCreate()와 ejbActivate()는 반드시 프라이머리 키를 설정해주어야 한다.
만일 프라이머리 키가 틀릴 경우 ejbLoad(), ejbStore()는 인스턴스 변수들을 DB와 동기화시킬수 없다.

* 참고사항 2
풀링된 상태에서 인스턴스 변수들의 값들은 불필요하다.
따라서 이런 인스턴스 변수들을 ejbPassivate 메소드에서 널로 설정함으로써
가비지 컬렉션(garbage collection)당할수 있도록 만들수 있다.

(2) BMP(Bean Managed Persistence)
* CMP 엔티티 빈에서 컨테이너가 해주던 작업들을 개발자가 직접 명시적으로 해주어야 한다.
따라서 개발자는 DB에 접근하는 코드를 반드시 사용해야 하며 EJB 컨테이너는 언제 DB의
데이터를 추가/삭제/변경하는 것이 안전한지를 알려준다.

가. 장점
* 빈 인스턴스와 DB 사이의 상태를 관리할 때 보다 유연하다.
즉, 복잡한 join 연산이나 서로 다른 DB들의 연동 또는 기존 시스템과의 연동에서는
BMP 엔티티 빈이 훨씬 유용하게 적용될 수 있다.

나. 단점
* 빈을 설계하기가 CMP에 비해 훨씬 까다롭다.
즉, BMP 엔티티 빈을 설계하는 사람은 DB의 구조에 대한 이해와 지식이 필요하고
엔티티에 관련된 데이터를 생성하고 변경 및 제거하는 로직을 개발해야 한다.
또한, 개발자는 빈의 홈 인터페이스에 정의된 find 메소드들을 모두 구현해야 한다.
또 빈을 특정한 DB 타입이나 구조에 종속시킨다는 점이다.
이는 DB 또는 데이터 구조 내의 모든 변화가 빈 클래스의 구현에 영향을 미치는 것을 의미한다.
따라서 빈의 유연성이 나빠진다.

* CMP 기반의 빈 클래스에서는 리모트 인터페이스에서 선언된 모든 메소드들과 홈 인터페이스에서 선언되
일부 메소드들(생명주기에 관련된 메소드들)만을 구현했지만,
BMP 기반에서는 리모트 인터페이스와 홈 인터페이스에 선언된
find 메소드들을 포함한 모든 메소드들을 구현해야 한다.

* 홈 인터페이스에 정의된 모든 메소드들을 구현하기 위해서는 개발자가 직접 빈 클래스 내에
DB를 제어하기 위한 작업, 즉 각종 메소드들과 커넥션 및 SQL 구문을 실행하기 위한 작업을 해야 한다.

* ejbCreate()의 반환 값이 CMP에서는 널(null)값이었으나
BMP 엔티티 빈에서는 반드시 프라이머리 키 값이어야 한다.

다. BMP 엔티티 빈의 내부 동작 과정

[클라이언트가 create() 메소드를 호출했을 때]
* ejbCreate() 메소드가 새로운 엔티티를 DB에 생성한 후 null을 반환하지 않고
엔터프라이즈 빈의 프라이머리 키를 반환한다.

* 새롭게 생성된 엔티티를 DB에 생성할 때도 컨테이너가 아닌 빈 인스턴스에 의해 이루어짐.

11. 트랜잭션
(1) 트랜잭션 타입
가. 개발자가 직접 트랜잭션 관리 코드 작성(프로그래밍 트랜잭션 방식)
① 클라이언트에 의한 트랜잭션 관리
* javax.transaction.UserTransaction을 사용.
java.sqlConnection의 commit(), rollback()을 사용하면 안됨

② 엔터프라이즈 빈에 의한 트랜잭션 관리

* 엔티티 빈은 "컨테이너에 의한 트랜잭션 관리"가 기본적으로 수행된다.
세션 빈은 "엔터프라이즈 빈에 의한 트랜잭션 관리" 와 "컨테이너에 의한 트랜잭션 관리"
중 하나가 가능하며, 동시에 둘 다는 불가능하다.

* 트랜잭션 관리 코드는 JDBC와 JTA를 사용하는 2가지 경우로 나눠진다.
두개가 같은 효과를 내지만 JTA를 사용하는 것이 DB에 종속되지 않고
좀 더 유연하게 트랜잭션을 관리할 수 있기 때문에 낫다.

* JDBC를 사용하는 경우 DBMS 시스템의 트랜잭션 기능을 직접 사용하는 것이다.

* "엔터프라이즈 빈에 의한 트랜잭션 관리"에서는
EJBContext의 getRollbackOnly()와 setRollbackOnly()를 사용해서는 안된다.
이 메소드는 "컨테이너에 의한 트랜잭션 관리"인 경우에만 사용될 수 있다.

㉠ 상태유지 세션 빈
* EJB 빈 메소드가 끝날 때 반드시 트랜잭션을 커미트하거나 롤백할 필요가 없다.
따라서 상태유지 세션 빈의 경우 한 트랜잭션이 여러 개의 메소드에 걸칠 수 있다.

㉡ 무상태 세션 빈
* 트랜잭션 아래에서 실행되는 비즈니스 메소드는 반드시 메소드의 실행이 끝나기 전에
commit(), rollback()해야한다.

나. deploy descriptor에 트랜잭션 타입 지정(선언 트랜잭션 방식)
* 빈 개발자가 트랜잭션 관리코드를 소스 코드 내에 포함하지 않는다.
디플로이먼트할 때 트랜잭션 속성을 지정한다.

* 트랜잭션 처리가 필요한 엔터프라이즈 빈의 특정 메소드들마다 각각 6개의 트랜잭션 속성 중 하나를
만족하도록 디플로이먼트 디스크립터에 지정하여 디플로이먼트 한다.
그러먼, EJB 컨테이너가 특정 메소드가 호출될 때, 해당 트랜잭션 속성대로 트랜잭션이 보장되도록
자동으로 처리한다.

* NotSupported, Required, Supports, RequiresNew, Mandatory, Never

* 디플로이먼트할 때 디플로이먼트 디스크립터의 각종 정보(트랜잭션, 보안, 자원관리 등)에 따라
리모트 인터페이스를 구현(implement)한 클래스가 자동으로 생성된다.
그리고 이 클래스로부터 생성된 객체가 EJB 객체이다.
리모트 인터페이스를 구현(implement)한 클래스 안에 디플로이먼트 디스크립터에 지정한
트랜잭션 속성에 대응되는 트랜잭션 코드가 자동으로 생성되는 것이다.

* 다음과 같은 메소드들은 컨테이너가 관리하는 트랜잭션을 방해하기 때문에 빈 클래스 안에서 사용할 수 없다.

- java.sql.Connection의 commit(), setAutoCommit(), rollback()
- javax.ejb.EJBContext의 getUserTransaction()
- javax.transaction.UserTransaction의 모든 메소드

① NotSupported
* EJB 컨테이너는 명시적으로 트랜잭션을 지원하지 않으며 자동으로 트랜잭션을 결코 실행하지 않는다.
또한 클라이언트 안에서 트랜잭션을 시도해도 그것을 "지원하지 않는(NotSupported")다.

클라이언트 컨테이너
------------------------------------------------------------
1. 클라이언트에 트랜잭션 코드가 없는 경우
bean.deposit() -> bean.deposit()

* 만약 클라이언트 코드 내에서 트랜잭션을 시도하면 엔터프라이즈 빈 메소드 호출이
끝날 때까지 클라이언트 트랜잭션은 멈춘 상태(suspend)가 된다.
2. 클라이언트에 트랜잭션 코드가 있는 경우
utx.begin()
...
bean.deposit() -> utx.suspend();
... bean.depsit();
... utx.resume();
utx.commit()

* 만약 클라이언트 코드에 의해 호출된 엔터프라이즈 빈이 다른 엔터프라이즈 빈을 호출했을 때
클라이언트의 트랜잭션 문맥(Transaction Context)은 전달되지 않는다.
② Required
* 엔터프라이즈 빈 메소드는 클라이언트 내에 트랜잭션 코드가 있건 없건 간에 항상 트랜잭션 상태에서 실행.
만약 클라이언트가 트랜잭션 하에서 동작하지 않으면 EJB 컨테이너는 자동으로 트랜잭션을 시작
만약 클라이언트내에서 트랜잭션을 시도하면 비즈니스 메소드도 트랜잭션 하에서 동작한다.

클라이언트 컨테이너
---------------------------------------------------------------
1. 클라이언트에 트랜잭션 코드가 없는 경우
bean.deposit(1); -> tx.begin();
bean.deposit(1);
tx.commit();

2. 클라이언트에 트랜잭션 코드가 있는 경우
utx.begin()
...
bean.deposit(1); -> bean.deposit(1);
...
utx.commit();

* 만약 호출된 엔터프라이즈 빈 메소드가 다른 엔터프라이즈 빈 메소드를 호출해도 같은
트랜잭션 문맥 아래에서 동작한다.

클라이언트 컨테이너 Account 빈 인스턴스
----------------------------------------------------------------------
1. 클라이언트에 트랜잭션 코드가 있는 경우
begin()
...
deposit() -> 컨테이너 -> deposit()
...
commit()


2. 클라이언트에 트랜잭션 코드가 없는 경우
begin()
deposit() -> 컨테이너 -> -> deposit()
commit()


③ Supports
* 컨테이너는 자동으로 트랜잭션을 결코 실행하지 않는다.
그렇지만 클라이언트 내에서 트랜잭션을 시도하면 그것을 "지원(Supports)" 한다.

* 즉, 클라이언트 코드가 트랜잭션 하에서 엔터프라이즈 빈을 호출하면 "Required"의 경우와 같이 동작한다.
클라이언트 코드가 트랜잭션이 아닌 상태에서 엔터프라이즈 빈을 호출하면 "NotSupported"의
경우와 같이 동작한다.

* 엔터프라이즈 빈 메소드가 반드시 트랜잭션 하에서 동작할 필요가 없을 경우에 선언한다.

④ RequiresNew
* 컨테이너는 엔터프라이즈 빈 메소드를 호출하기 전에 항상 새로운 트랜잭션을 시작하며
매소드 호출이 끝났을 때 트랜잭션의 커미트를 시도한다.

1. 클라이언트에 트랜잭션 코드가 없는 경우

bean.deposit() -> tx.begin();
bean.deposit();
tx.commit();

* 만약 클라이언트 코드가 트랜잭션 하에서 엔터프라이즈 밴의 메소드를 호출하면
메소드 호출이 끝날 때까지 클라이언트 트랜잭션은 멈춘 상태(suspend)가 된다.
따라서 피하는 것이 좋다.

2. 클라이언트에 트랜잭션 코드가 있는 경우

utx.begin()
...
bean.deposit() -> utx.suspend()
... tx.begin();
utx.commit() bean.deposit();
tx.commit();
utx.resume();

⑤ Mandatory
* 클라이언트의 엔터프라이즈 빈의 메소드 호출은 반드시 트랜잭션 하에서 이루어져야 한다.
컨테이너는 자동으로 트랜잭션을 결코 실행하지 않는다.
트랜잭션은 클라이언트에 의해 관리되어야 한다.

* 만약 클라이언트가 트랜잭션 하에서 엔터프라이즈 빈의 메소드를 호출하지 않았을 경우
TransactionRequiredException이 발생한다

* 엔터프라이즈 빈 메소드를 호출하는 클라이언트가 트랜잭션 하에서 호출하지 않으며 아예
애플리케이션이 실행되지 않도록 만들 때 선언한다.

⑥ Never
* 트랜잭션이 어떤 상황에서도 실행되지 않는다.

* 만약 클라이언트 코드가 트랜잭션 하에서 엔터프라이즈 빈 메소드를 호출하면
java.rmi.RemoteException이 발생한다.

* 클라이언트 코드가 트랜잭션 상태가 아니라면 NotSupport경우와 같이 동작한다.


T1 : 클라이언트 코드 내에서 시작된 트랜잭션
T2 : EJB 컨테이너에 의해 시작된 트랜잭션
---------------------------------------------------------------------------------------
트랜잭션속성 클라이언트의트랜잭션 엔터프라이즈빈메소드와연관된트랜잭션 자원관리자와연관된트랜잭션
---------------------------------------------------------------------------------------
NotSupported 없음 없음 없음
T1 없음 없음

Reequired 없음 T2 T2
T1 T1 T1

Supports 없음 없음 없음
T1 T1 T1

RequiresNew 없음 T2 T2
T1 T1 T2

Mandatory 없음 에러 N/A
T1 T1 T1

Never 없음 없음 없음
T1 에러 N/A
---------------------------------------------------------------------------------------

(2) 트랜잭션 속성을 지정하는 구체적인 방법

가. 디플로이먼트 디스크립터 안에 선언
나. 디플로이먼트 툴의 GUI를 사용

* SessionContext 객체를 통해 javax.ejb.EJBContext의 setRollbackOnly()메소드를 호출할 수 있다.
이것은 트랜잭션이 커밋될 수 없도록 해주는 메소드이다.
트랜잭션하에서 실행되는 메소드가 중간에 애플리케이션 관련 예외가 발생할 경우 자동으로 롤백되지 않는다.
따라서 컨테이너에게 롤백시켜달라고 알리는 메소드이다.
이 메소드를 빈 클래스 내에서 호출하면 적당한 시기에 컨테이너에 의해 트랜잭션은 강제로 롤백된다.

(3) 상태유지 세션 빈에서 SessionSynchronization을 사용하는 경우
* 상태유지 세션 빈은 트랜잭션이 시작, 커미트, 롤백될 때 빈 인스턴스의 속성 값과 데이터베이스 정보의
일관성을 유지하기 위해 SessionSynchronization 인터페이스를 구현할 수도 있다.
하지만 반드시 구현해야 하는 것은 아니다.

* EJB 컨테이너에 의해 트랜잭션이 관리되는 겻우, 빈 클래스를 개발하는 개발자는
트랜잭션이 언제 시작되고 커미트되고 롤백되는지 정확히 예측할 수 없다.
하지만 그런 시기를 알고 적절하게 코딩해야 하는 경우도 있는데 SessionSynchronization은 그때를 위해 필요한것.

* EJB 컨테이너는 트랜잭션의 시작, 커밋, 롤백 등이 발생될 때 빈 인스턴스의 SessionSynchronization의 메소드를 호출한다.
따라서 빈 인스턴스는 현재 트랜잭션의 진행상황을 알 수 있게 되어 트랜잭션의 실행에 맞춰 적절한 행동을 할 수 있다.

- implement javax.ejb.SessionSynchronization
을 통해 인터페이스를 구현한다.

- public void afterBegin()
트랜잭션이 시작한 직후에 컨테이너에 의해 호출됨
afterBegin()이 호출되면 이후에 호출되는 비즈니스 메소드는 전부 트랜잭션하에서 동작하는 것이다.
따라서 트랜잭션이 아니거나 다른 속성의 메소드가 호출되면 에러가 발생

- public void beforeCompletion()
트랜잭션이 끝나기 직전에 컨테이너에 의해 호출됨

- public void afterCompletion(boolean committed)
트랜잭션이 끝난 직후에 호출됨.
파라미터가 참이면 커밋, 거짓이면 롤백인 경우에 호출됨

* 트랜잭션이 롤백되었을 때 DB의 값을 돌려 놓는 것 외에 빈 인스턴스의 속성 값도 원래 상태로
돌려야 하는 경우에 SessionSynchronization이 사용된다.

(4) 컨테이너가 관리하는 트랜잭션을 롤백하는 방법

* "컨테이너에 의한 트랜잭션 관리"에서 롤백이 일어나야만 하는 경우는 트랜잭션 수행도중 예외가 발생하는 때이다.
* 엔터프라이즈 빈에서 발생하는 모든 예외는 시스템 레벨의 예외와 애플리케이션 예외의 두종류로 나눠진다.
가. 시스템 레벨 예외
① 시스템 레벨의 예외가 발생하면 컨테이너는 자동으로 트랜잭션을 롤백

- 엔터프라이즈 빈 내에서 시스템 레벨의 예외가 발생하면 개발자는 EJBException을 발생시키기만 하면 된다.

나. 애플리케이션 레벨 예외
① SessionContext객체의 setRollbackOnly()를 호출하면 컨테이너가 트랜잭션을 롤백

- 애플리케이션 레벨의 예외가 발생하면 개발자가 소스 코드 내에 롤백을 지시하는 코드를 직접 작성해야 한다.
왜냐하면 애플리케이션 레벨의 예외가 발생하면 롤백이 자동적으로 수행되지 않기 때문이다.
반드시 수동으로 setRollbackOnly()를 호출하여 롤백해야 한다.

다. Example>
public void transferToSaving(double amount) throws InsufficientBalanceException
{
checkingBalance -= amount;//현재 예금계좌를 이체금액만큼 감소한다.
savingBalance += amount;// 이체할 예금계좌를 이체금액만큼 증가한다.

try
{
updateChecking(checkingBalance);//DB를 현재 예금 금액으로 업데이트

if( checkingBalance < 0.00 )// 만약 잔고가 0보다 작으면
{
context.setRollbackOnly();// 이체할 금액이 부족하므로 롤백을 지시함

throw new InsufficientBalancException();// 애플리케이션 예외 발생
}

updateSaving(savingBalance);// 잔고가 0보다 크면 정상처리
}
catch(SQLException ex)// 만약 SQL예외, 즉 시스템 예외가 발생하면
{
// EJBException을 발생시켜 컨테이너가 자동 롤백하도록 함
throw new EJBException("Transaction failed due to SQL Exception: " + ex.getMessage());
}
}

라. 트랜잰션 롤백을 위한 코드 템플릿

try
{
// 트랜잭션의 내용
if( 애플리케이션 예외 == true )
{
context.setRollbackOnly();// 컨테이너에게 롤백하도록 알림

throw new 애플리케이션예외();
}

// 트랜잭션의 내용
}
catch(시스템예외)
{
throw new EJBException();// 컨테이너에게 롤백하도록 알림
}

(5) Isolation
* 트랜잭션들은 작업을 "All or Nothing"으로 처리해야 할 뿐 아니라 여러 트랜잭션들이 동시에 실행될 경우
한 트랜잭션이 다른 트랜잭션에 의해 방해받지 않고 진행되어야 한다.

* Isolation이란 어떤 트랜잭션이 다른 여러 개의 트랜잭션과 동시에 같은 데이터를 사용해도 서로
독립적으로 해당 데이터를 처리할 수 있는 능력을 의미한다.

* 여러 트랜잭션이 동시에 같은 데이터를 사용하면 다음과 같은 3가지 현상이 발생할 수 있다.

- Dirty Read
: A트랜잭션이 B트랜잭션이 변동한 데이터를 커밋하기 전에 읽는다.
만약 B트랜잭션이 롤백되면 A트랜잭션은 무효가 된다.

update ->
read<-
rollback->

- Non-Repeatable Read
: 한 트랜잭션이 수행중에 읽은 데이터는 트랜잭션중이라면 이후에 읽어도 같은 값을 가질 것을 보장할 수 없다.

read <-
update ->
read <-

- Phantom Read
: DB에 데이터를 삽입하기 전에 시작한 트랜잭션은 DB에 새로 첨가된 레코드들을 알 수 없다.



* JDBC에서는 이런 현상들을 제어하기 위해 java.sql.Connection 클래스와
setTransactionIsolation()로 Isolation 레벨을 지정할 수 있다.

Isolation 레벨 DirtyReads UnRepeatableRead PhantomReads
-----------------------------------------------------------------------------------------------------------------
TRANSACTION_READ_UNCOMMITTED 커밋되지 않은 데이터들을 읽을 수 있다. 예 예 예

TRANSACTION_READ_COMMITTED 커밋되지 않은 데이터들을 읽을 수 없다. 아니오 예 예

TRANSACTION_REPEATABLE_READ 어떤 트랜잭션도 다른 트랜잭션에 의해서 아니오 아니오 예
읽혀지고 있는 데이터를 변경할 수 없다.

TRANSACTION_SERIALIZABLE 어떤 트랜잭션도 다른 트랜잭션이 사용하고 아니오 아니오 아니오
있는 데이터를 읽을 수도 변경할 수도 없다.


* EJB 아키텍처 안에 Isolation을 위한 공식적인 API는 정의되어 있지 않고 따라서
리소스 매니저에 따라 그 방법이 달라진다.

- 리소스 매니저가 데이터베이스 :
DBMS가 지원하는 Isolation과 locking에 따라 실제 정확한 Isolation의 수행 행위가 결정된다.

- 컨테이너에 의해 트랜잭션이 관리 될 경우 컨테이너가 자동으로 Isolation 레벨을 정의한다.

- 엔터프라이즈 빈에 의한 트랜잭션이 관리되는 세션 빈의 경우
개발자가 JDBC의 java.sql.Connection 클래스의 setTransactionIsolation()를 사용하여
빈 클래스내에서 Isolation레벨을 정의할 수 있다.
이런 Isolation 레벨을 엔터프라이즈 빈 내에서 정의하지 않으며 DB 시스템이 디폴트로 제공하는
Isolation레벨대로 동작한다.
만약 트랜잭션의 Isolation을 개발자가 정의한다면 애플리케이션이 사용하는 DBMS가 제공하는
Isolation을 고려해야 하기 때문에 매우 주의해야 한다.
12. 보안
* javax.ejb.EJBContext

javax.security.Principal getCallerPrincipal();
boolean isCallerInRole(String roleName);

// EJB 1.0 메소드는 deprecated 되었다.

java.security.Identity getCallerIdentity();
boolean isCallerInRole(java.security.Identity role);
13. 예외처리
java.lang.Throwable
java.lang.Error
java.awt.AWTError
...
java.lang.Exception
...
java.io.IOException
...
java.lang.RuntimeException
...

(1) 자바의 경우 개발자가 작성한 프로그램이 자바 언어의 구문적인 규약을 위배했을 때 자바 가상 머신은 에러를 발생시키고
이를 예외라는 형태를 통해서 프로그램에게 전달한다.
자바에서 예외는 클래스로 정의되며 모든 예외 클래스는 Throwable 클래스를 상속한다.

가. Error 클래스
자바 가상 머신 내부의 에러, 또는 AWT의 에러와 같이 일반적인 프로그램에서 처리할 수 없는 치명적인 오류이다.
이러한 Error 클래스를 상속한 예외들은 처리할 수도 없고 처리해서도 안된다.
따라서 개발자는 Error 클래스를 상속한 예외들을 고려할 필요가 없으며,
개발과 실행이 안정적으로 이뤄진다면 발생하지 않는다.

나. Exception 클래스
발생할 확률이 높고 프로그램의 책임이 높은 오류이다. 즉, 개발자가 실수로 예외가 발생되는 코드를 작성하는 경우가 많다.
따라서 개발자는 Exception 클래스를 상속하는 예외가 발생하지 않도록 코딩상의 오류를 수정하거나 예외가 발생하는 경우에
대한 처리가 필요하다.

다. RuntimeException 클래스
검사되지 않은 예외나 시스템 정의 예외를 말한다.
예를 들어 숫자를 0으로 나누는 경우나 범위를 벗어난 배열을 참조하는 경우에 발생한다.

(2) 자바에서의 예외는 위와 같이 계층적인 구조와 함께 다음과 같이 분류하는 것도 가능하다.
가. 검사된 예외(checked exception)
메소드의 throws절에 정의된 예외를 말한다. 이러한 예외는 컴파일시에 검사되므로 반드시 처리되어야 한다.
RuntimeExceptin 및 그 서브 클래스를 제외한 나머지 Exception 클래스의 서브 클래스들이 이에 해당한다.
자바에서는 검사된 예외를 발생한 이벤트를 전달하는데 사용하기도 한다.

나. 검사되지 않은 예외(unchecked exception)
컴파일러에 의해 검사되지 않은 예외를 말한다.
따라서 예외 처리를 해주지 않아도 컴파일시에 오류가 발생하지 않는다.
하지만 이 예외가 발생할 경우 프로그램은 비정상적으로 종료된다.
제대로 코딩만 된다면 이 예외는 완벽하게 없앨 수 있으며 따라서 개발자가 세심하게 주의하면 된다.
Error와 RuntimeExceptin 및 그 서브 클래스들이 검사되지 않은 예외에 해당된다.

(3) 자바에서는 예외가 발생하는 3가지 원인
가. 비정상적인 실행 상태가 자바 가상 머신에 의해서 감지되었을 경우
① 표현식의 계산이 자바 언어의 규칙을 위반했을 경우(예: integer를 0으로 나누는 행위)
② 프로그램의 로딩 및 링크 부부에서 에러가 발생했을 때
③ 제한된 자원을 초과하여 사용했을 때(예: 메모리 초과 사용)

나. throw 구문이 실행되었을 경우

다. 다음과 같은 이유로 비동기적인 예외가 발생할 경우
① Thread 클래스의 stop()가 호출될 때
② 자바 가상 머신에서 내부 에러가 발생할 때

(4) EJB에서의 예외 처리

* 예외 처리에 대한 EJB 스펙은 다음과 같은 목적을 위해 디자인되었다.
- 빈 인스턴스가 throw한 애플리케이션 예외는 클라이언트에게 정확히 전달되어야 한다.
- 빈 인스턴스가 throw한 애플리케이션 예외가 자동으로 클라이언트의 트랜잭션을 롤백해서는 안된다.
클라이언트가 애플리케이션 예외로부터 트랜잭션을 복구할 수 있는 기회가 주어져야 한다.
- 인스턴스의 상태 변수나 영속성 있는 데이터를 비안정적인 상태로 만드는 예기치 못한 예외는
안전하게 처리되어야 한다.

* EJB의 예외는 크게 애플리케이션 예외와 시스템 예외로 나눌 수 있다.
<애플리케이션 예외>
스펙에 정의된 표준 애플리케이션 예외나 엔터프라이즈 빈의 홈 인터페이스와 리모트 인터페이스 메소드의
throws절에 정의된 예외들 중 java.rmi.RemoteException를 제외한 나머지 예외들을 말한다.
이러한 애플리케이션 예외는 엔터프라이즈 빈에서 발생한 애플리케이션 수준의 비정상적인 상태를
클라이언트에게 전달하는데 사용된다.

<시스템 예외>
엔터프라이즈 빈의 비즈니스 메소드와 컨테이너 콜백 메소드에서 발생하는 시스템 수준의 예외를 말한다.
이러한 시스템 예외는 주로 EJB 컨테이너가 엔터프라이즈 빈의 메소드에서 발생하는 각종 비정상적인 상태를
제대로 처리해주지 못하기 때문에 발생한다.
이러한 시스템 예외는 EJB 컨테이너에 의해 catch되고, 이를 로그에 기록함으로써 시스템 관리자에게
예외의 발생을 경고한다.

가. 애플리케이션 예외
① 엔터프라이즈 빈의 홈 인터페이스와 리모트 인터페이스 메소드의 throws절에 정의된 예외들 중
java.rmi.RemoteException 예외를 제외한 나머지 예외들

이러한 애플리케이션 예외는 엔터프라이즈 빈의 비즈니스 메소드가 클라이언트에게 애플리케이션 수준의
비정상적인 상태를 알리는데 사용된다. 따라서 빈을 이용해 클라이언트를 개발하는 개발자는 예외에
알맞은 처리를 해줌으로써 이러한 애플리케이션 예외를 복구할 수 있다.

② javax.ejb.CreateException, javax.ejb.RemoveException, javax.ejb.FinderException과 같은
예외와 이들 클래스를 상속한 예외들

이러한 예외들은 엔터프라이즈 빈의 create, remove, find 메소드의 오류를 클라이언트에게 알리기
위한 표준 애플리케이션 예외로 사용된다.

③ 빈 제공자 관점에서의 애플리케이션 예외
* 빈 제공자(개발자)는 리모트 인터페이스와 홈 인터페이스 메소드의 throws절에 애플리케이션 예외를 정의한다.
* 애플리케이션 예외는 시스템 관리자가 아닌 클라이언트에 의해 처리되므로, 시스템 레벨의 문제가 아닌
비즈니스 로직상의 예외를 발싱시키게 된다.
* 빈 제공자는 비즈니스 메소드가 클라이언트에게 비즈니스 로직 예외를 알릴 수 있도록 적절한
애플리케이션 예외를 throw해야 한다.
* 주의사항은 애플리케이션 예외가 발생해도 트랜잭션은 자동으로 롤백되지 않는다는 사실
* 따라서 빈 제공자는 데이터의 무결성을 보장하기 위해서 엔터프라이즈 빈 인스턴스가 애플리케이션 예외를
throw하기 전에 다음 중 하나의 작업을 반드시 수행해야 한다.

- 빈 제공자는 트랜잭션을 커밋 하거나 계속 수행하려는 클라이언트에 의해 엔터프라이즈 빈이
무결성을 잃지 않도록 보장해야 한다.
예를 들어, DB에 대한 갱신을 하기 전에 입력 파라미터의 값이 유효하지 않다는 애플리케이션 예외를
throw함으로써 데이터 무결성을 보장한다.

- 애플리케이션 예외를 throw하기전에 EJBContext.setRollbackOnly()를 이용하여 트랜잭션이 롤백되도록
플래그 세팅. 롤백으로 세팅된 트랜잭션은 절대로 커밋되지 않는다.

* 빈 제공자가 애플리케이션 예외를 작성할 때 특히 주의해야 할 사항

- 애플리케이션 예외는 java.lang.RuntimeException이나 java.rmi.RemoteException 클래스를 상속해서는
안된다. 이들 클래스 및 서브 클래스는 시스템 예외에서 사용된다.

- 빈 제공자는 javax.ejb.CreateExceptio, javax.ejb.RemoveException, javax.ejb.FinderException과
같은 표준 EJB 애플리케이션 예외를 사용해야만 한다.
또한 빈 제공자는 이러한 표준 EJB 애플리케이션 예외의 서브 클래스를 정의하여 엔티티 빈의
메소드에서 그 서브 클래스의 인스턴스를 throw할 수 있다.
이렇게 서브 클래스를 정의함으로써 빈 제공자는 이 예외를 catch하는 클라이언트에게 더 많은
정보를 제공할 수 있다.

④ 클라이언트 관점에서의 애플리케이션 예외

* 엔터프라이즈 빈 호출시 애플리케이션 예외가 발생해도, 클라이언트 프로그램이 엔터프라이즈 빈을 계속해서
호출하는 것은 가능하다. 즉, 애플리케이션 예외로 인해 EJB객체가 제거되지는 않는다.

* 트랜잭션 도중에 클라이언트가 엔터프라이즈 빈을 호출하다가 애플리케이션 예외를 catch하여도
컨테이너가 자동으로 트랜잭션을 롤백으로 세팅하지 않으므로 클라이언트는 트랜잭션을 계속 할 수 있다.

* 하지만 throw된 애플리케이션 예외 때문에 컨테이너가 자동으로 트랜잭션을 롤백시키지 않아도,
엔터프라이즈 빈이 애플리케이션 예외를 throw하기 전에 트랜잭션을 롤백으로 세팅할 수도 있다.

* 특정 애플리케이션 예외가 트랜잭션 롤백을 일으키는지의 여부를 알아내는 방법은 두가지이다.
- 정적인 방법
프로그래머는 엔터프라이즈 빈의 리모트 인터페이스와 홈 인터페이스에 대한 문서를 체크한다.
빈 제공자는 예외를 throw하기 전에 엔터프라이즈 빈이 트랜잭션을 롤백으로 세팅하는
애플리케이션 예외를 지정할 수 있다.

- 동적인 방법
CMP 트랜잭션을 사용하는 엔터프라이즈 빈을 호출하는 클라이언트는 현재 트랜잭션이 롤백으로
세팅되었는지의 여부를 알아내기 위해서 javax.ejb.EJBContext 객체의 getRollbackOnly()를
사용할 수 있다. 다른 방법으로는 javax.transaction.UserTransaction 인터페이스의 getStatus()
를 사용해 트랜잭션 상태를 알아낼 수도 있다.

⑤ 표준 애플리케이션 예외
* EJB 스펙은 다음과 같은 표준 애플리케이션 예외를 정의하고 있다.
- javax.ejb.CreateException
- javax.ejb.DuplicateKeyException
- javax.ejb.FinderException
- javax.ejb.ObjectNotFoundException
- javax.ejb.RemoveException

㉠ CreateException
* CreateException 및 그 서브 클래스는 홈 인터페이스의 create(...)메소드에서 애플리케이션 수준의
예외가 발생했음을 알려주는 역할을 수행한다. 하지만 클라이언트가 이 예외를 받는다고 해도,
해당 엔티티 객체의 초기화가 완료되었는지 아니면 전혀 생성되지 않았는지를 알 수는 없다.

* 또한 CreateException은 엔티티 빈 인스턴스의 ejbCreate(...)와 ejbPostCreate(...)에서 생성이나
초기화 작업중에 애플리케이션 수준의 예외가 발생하였음을 알리기 위해 사용된다.

㉡ DuplicateKeyException
* DuplicateKeyException은 CreateException의 서브 클래스로써, 같은 키를 가진 엔티티 객체가
존재하여 새로운 객체를 생성할 수 없는 경우 ejbCreate(...)가 throw한다.
DuplicateKeyException은 DB의 프라이머리 키나 다른 유일한 키에 의해 발생한다.

㉢ FinderException
* FinderExceptionn 및 그 서브 클래스는 find(...)에서 애플리케이션 수준의 예외가 발생하였음을
알려주는 역할을 수행한다. 즉, find메소드에서 애플리케이션 수준의 예외가 발생하였을 경우
ejbFind<METHOD>(...)메소드는 FinderException 이나 그 서브 클래스를 throw 하게 된다.
㉣ ObjectNotFoundException
* ObjectNotFoundException은 FinderException의 서브 클래스로써, 요청된 엔티티 객체가 존재하지
않는 경우 ejbFind<METHOD>(...)메소드가 throw한다.
주의할 점은, 하나의 객체를 반환하는 find 메소드만이 이 예외를 throw한다는 것이다.
다수의 객체를 반환하는 find 메소드는 이 예외를 throw할 수 없다. 다수의 객체를 반환하는
find 메소드는 적합한 객체를 찾을 수 없음을 알리기 위해서 비어 있는 컬렉션(collection)을 반환해야 한다.

㉤ RemoveException
* RemoveException 및 그 서브 클래스는 remove(...) 메소드에서 애플리케이션 수준의 예외가
발생했음을 알려주는 역할을 수행한다. 하지만 클라이언트가 이 예외를 catch하더라도 엔티티 객체가
제대로 제거되었는지의 여부를 알 수는 없다.
또한 RemoveException은 ejbRemove() 메소드의 엔티티 객체의 제거 과정에서 애플리케이션 수준의
예외가 발생하였음을 알리기 위해 사용된다.

⑥ 시스템 예외
* 엔터프라이즈 빈의 비즈니스 메소드와 컨테이너 콜백 메소드는 다양한 예외와 에러로 인해 정상적인 실행을
방해 받는다. 보통 이러한 예외와 에러들은 전혀 예상치 못했거나 아니면 예상했지만 EJB 컨테이너가 이를
제대로 처리해주지 못하기 때문에 발생한다. 이러한 예외와 에러를 시스템 예외라 통칭

* 엔터프라이즈 빈 메소드가 정상적인 실행을 방해하는 시스템 수준의 예외나 에러에 직면하게 되는 경우
해당 메소드는 throws절에 명시된 예외 클래스와 호환되면서도 상황에 적합한 비 애플리케이션 예외를
throw해야 한다. EJB 스펙이 예외의 사용을 정확하게 정의하고 있지는 않지만, 빈 제공자는
다음의 가이드라인을 따라야 한다.

- 빈 메소드에서 RuntimeException이나 에러가 발생하면, 이 에러는 빈 메소드에서 컨테이너로 전달된다.
따라서 빈 메소드는 절대로 이 예외를 catch하면 안된다.

- 빈 메소드에서 java.lang.RuntimeException의 서브 클래스가 아니면서 복구할 수 없는 예외가 발생하면,
빈 메소드는 원래의 예외를 감싸는 javax.ejb.EJBException을 throw해야 한다.

'공부 > Spring' 카테고리의 다른 글

Spring IOC  (0) 2011.12.12
About Spring  (0) 2011.12.12
RMI(원격 메소드 호출, Remote Method Invocation)  (3) 2011.07.04

메서드 호출은 항상 같은 힙에 들어있는 두 객체 사이에서 이루어진다.

 class Foo{
       void go()  {
             Bar b = new Bar();
             b.doStuff();
       }

        public static void main (String[] args) {
                 Foo f = new Foo();
                 f.go();
       }
}


위 코드의 두 객체는 JVM에서 관리하는 같은 힙안에 들어있으며 힙에 있는 객체에 접근하는 방법을 나타내는
레퍼런스 변수를 비트에 채워 넣는 일은 JVM에서 맡아 처리한다. JVM은 항상 각 객체가 어디에 있는지,
어떻게 그 객체에 접근할 수 있는지를 알고 있다. 하지만 JVM에서는 그 자신의 힙에 있는 인스턴스에 대한 것만 알고 있다.
예를들어, 한 시스템에서 돌아가고 있는 JVM에서 다른 시스템에서 돌아가고 있는 JVM의 힙 공간에 대해서
알수 있게 할수는 없다.
사실 어떤 시스템에서 돌아가고 있는 JVM에서 같은 시스템에서 돌아가고 있는 JVM에 대해서도 전혀
알 수가 없다. JVM이 물리적으로 같은 시스템에 있는 것인지 다른 시스템에있는것인지는 중요하지않다.
중요한것은 JVM 두개가 별도로 호출된 JVM 이라는 것이다.


다른 시스템에서 돌아가고 이쓴ㄴ 객체에 있는 메소드를 호출하려면 어떻게해야하나?

방법은 RMI(원격 메소드 호출, Remote Method Invocation)

원격 메서드 호출 방법 설계
서버, 클라이언트,서버 보조 객체, 클라이언트 보조 객체, 이렇게 네가지를 만든다.



'보조객체(helper)'의 역활

'보조객체(helper)'는 실제 통신 작업을 처리하는 객체다. "클라이언트가 로컬 객체에 있는 메소드를 호출하는 척" 하는 것을
가능하게 해준다. 사실, 클라이언트는 로컬 객체에 있는 메소드를 호출한다. 클라이언트는 그 보조 객체를 실제 서비스로
간주하고 클라이언트 보조 객체에 대한 메소드를 호출한다. 결국, 클라이언트 보조 객체는 진짜 객체를 대신하는 역활을 한다.

즉, 클라이언트 보조 객체는 "클라이언트에서 호출하려고 하는 메소드를 가지고 있는 객체인 척" 하는 객체다.

하지만 클라이언트 보조 객체는 사실 진짜 원격 서비스가 아니다.
(서비스에서 제공하는 것과 같은 메소드가 있 기 때문에) 원격 서비스인 것처럼 행동하긴 하지만 거기에는 클라이언트에서
예상하고 있는 실제 메소드 처리 코드 같은 것은 없다. 대신 클라이언트 보조 객체에서는
서버와 접촉하고, 메소드 호출에 대한정보(메소드명, 인자 등)를 전송하고 서버에서 결과를 리턴할때까지 기다린다.

서버 쪽에서는 서비스 보조 객체에서, (소켓 연결을 통해) 클라이언트 보조 객체에서 보낸 요청을 받아서 호출에 대한
정보를 열어보고 진짜 서비스 객체에 있는 진짜 메소드를 호출한다.

서비스 보조 객체는 서비스로부터 리턴값을 받아 포장한후 다시 (소쳇의 출력 스트림을 통해) 클라이언트 보조 객체로 보낸다.
클라이언트 보조 객체는 그 포장을 풀고 그 정보를 다시 클라이언트 객체로 리턴한다.

메서드 호출과정


1. 클라이언트 객체에서 클라이언트 보조 객체에 있는 메서드를 호출한다.
2. 클라이언트 보조 객체에서 메서드 호출에 대한 정보(인자, 메소드명 등)를 포장해서
    네트워크를 통해 서비스 보조 객체로 보낸다.
3. 서비스 보조 객체에서 클라이언트 보조 객체로부터 받은 정보를 풀어서 어떤 객체의 어떤 메소드를 호출할지 알아낸 다음
    진짜 서비스 객체에있는 진짜 메소드를 호출한다.


자바 RMI가 클라이언트와 서비스 보조 객체를 제공한다.

자바에서는 RMI가 클라이언트와 서비스 보조 객체를 만들어주고 클라이언트 보조 객체가 진짜 서비스인 것처럼 보이게하는
방법도 알고 있다. 즉, RMI에서 클라이언트 보조 객체에 원격 서비스에 대해 호출하고자 하는 것과 같은 메소드를 배정해 주는 방법도
알고있다.

그리고 RMI는 클라이언트에서 클라이언트 보조 객체(진짜 서비스인 것처럼 행동하는 객체)를 찾고 가져올 수 있게 해주는 룩업 시스템을 비롯한 모든 필요한 기반을 제공한다.

RMI를 사용할때 JRMP, IIOP 이렇게 두가지 규약가운데 하나를 사용할수있는데 JRMP는 RMI에서 원래 사용하던 규약으로 자바에서->자바로 원격 호출을 하기 위한 용도로 만들어진 반면, IIOP는 CORBA용 규약이며 자바가 아닌 원격 객체에 있는 것도 호출할수 있는 규약이다.
양쪽에서 모두 자바를 사용하지않으면 엄청나게 많은 해석과 변환이 이루어져야하기 떄문에 CORBA는 RMI에비해 쓰기가 어렵다.


RMI에서 클라이언트 보조 객체는 '스터브(stub)'고
서버 보조 객체는 '스켈레톤(skeleton)' 이다.



코드로 보면 이해하기 쉽다.

서버용코드


-원격 인터페이스(service)
 import java.rmi.*;
//RemoteException과 Remote인터페이스가 java.rmi 패키지에 들어있다.
public interface MyRemote extends Remote {
 //인터페이스에서 반드시 java.rmi.Remote를 확장시켜야한다.
           public String sayHello() throws RemoteException;
           //모든 원격 메소드에 RemoteException을 선언해야한다.
}

-원격 서비스(serviceimpl, 인터페이스를 구현한 클래스)
import jave.rmi.*;
import java.rmi.server.*;
//UnicastRemoteObject가 java.rmi.server패키지에 들어있다.
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
//앞서 만든 원격 인터페이스를 구현해야 한다.
//원격 객체를 만들 때는 UnicastRemoteObject를 확장하는 것이 가장 쉬운 방법이다.
             public String sayHello() {
                       return "Server says, 'Hey'";
             }
             // 당연히 모든 인터페이스 메소드를 구현해야 한다. 하지만 RemoteException을 선언하지 않아도 된다.

            public MyRemoteImpl() throws RemoteExeption {}
           //상위 클래스 생성자(UnicastRemoteObject생성자)에서 예외를 선언하기 떄문에 반드시 생성자를 만들어야한다.
              이렇게 해야 생성자에서 위험한코드(상위클래스 생성자)를 호출한다는 것을 선언할수 있기떄문이다.

            public static void main (String[] args) {

                      try{
                          MyRemote service = new MyRemoteImpl();
                          Naming.rebind("Remote Hello", service);
                          //원격 객체를 만들고 Naming.rebind()라는 정적메소드를 써서 RMI 레지스트리에 결합시킨다.
                             나중에 클라이언트에서 RMI레지스트리에 있는 서비스를 찾을떄 바로 여기에서 지정한이름을 사용한다.

                     }catch ( Exception ex){
                          ex.printStackTrace();
                     }
            }
}


클라이언트코드

import java.rmi.*;
//Naming 클래스(RMI 레지스트리 룩업에 필요함) 가 java.rmi 패키지에 들어있다.

public class MyRemoteClient{
          public static void main (String[] args) {
                    new MyRemoteClient().go();
          }

          public void go(){

                    try{
                         MyRemote service = 1.(MyRemote) Naming.lookup("2.rmi://127.0.0.1/3.Remote Hello");
                         //1. 레지스트리에서 보낸 객체는 Object 유형이므로 반드시 캐스트를 해야함.
                         //2. ip주소 또는 호스트명이필요하다.
                         //3. 서비스를 연결/재연결 할때 사용한 이름도 필요하다.
                         String s = service.sayHello();
                        //  일반 메소드 호출방법하고 똑같다. (RemoteException을 처리하거나 선언해야한다는점을 빼면)
                         System.out.println(s);
                     }catch(Exception ex){
                         ex.printStackTrace();
                     }
           }
}



그림으로 보면


1.클라이언트에서 RMI 레지스트리에 대한 룩업 작업을 한다.
   Namin.lookup("rmi://127.0.0.1/Remote Hello");

2. RMI 레지스트리에서 스터브 객체를 리턴한다.
   (이 객체는 lookup()메소드의 리턴값 형태로 전달된다)
   그리고 RMI에서 스터브를 자동으로 역직렬화 해준다. 클라이언트에 스터브 클래스(rmic가 만들어준것)가 없으면 스터브가 역직렬화되지않음

3. 클라이언트에서 실제 서비스에 있는 메소드를 호출하는 것과 같은 방법으로 스터브에 있는 메소드를 호출한다.

'공부 > Spring' 카테고리의 다른 글

Spring IOC  (0) 2011.12.12
About Spring  (0) 2011.12.12
엔티티 빈  (0) 2011.07.26

스프링을 공부하기전에

스프링에대한 개념을 잡기위해

RMI , 스트러츠, EJB 를 먼저 이해해야 할듯하다

꽁부ㄱㄱ

'공부' 카테고리의 다른 글

오라클 힌트사용하기  (0) 2012.01.02
리눅스 기본명령어  (0) 2011.12.15
Oracle 날짜함수  (0) 2011.08.08
ORACLE에서 제공되는 내장함수  (0) 2011.08.08
공부의 필요성을 느끼다...  (0) 2011.06.08

컨테이너는 JSP 파일을 HttpJspPage 인터페이스를 구현한 서블릿 클래스로 변환하여 생성한다.
 
개발자로서 우리는 아래에 나와있는 서블릿 API만 이해하면된다.

 ▶jspInit()

init()메소드를 호출한다. 이 메소드는 재정의해도 무방하다.

▶jspDestroy()

서블릿의 destroy()메소드에서 호출한다. 이메소드또한 재정의해도 무방

▶_jspService()

서블릿의 service()메소드에서 호출한다. 즉 요청이 들어올떄마다 이 메소드는 새로운 스레드로 실행이 된다는 말이다
컨테이너가 알아서 Request 객체와 Response 객체를 매개변수로 넘겨준다
이 메소드는 재정의 하면 안됀다.(이메소드안에 들어갈 코드를 작성하는것 뺴고)


JSP 초기화 하기

JSP도 일반 서블릿과 마찬가지로 초기화 작업을 할 수 있다. 그러나 방식은 일반 서블릭과 조금 다른데

서블릿 초기화 파라미터 설정하기

일반 서블릿에서 서블릿 초기화 파라미터를 설정하는 방식과 유사하게 JSP 초기화 파라미터를 설정한다
차이점이라고는 <servlet-class> 태그가 아닌 <jsp-file> 태그를 사용한다는 것이다.
<web-app ...>
........
   <servlet>
            <servlet-name>MyTestInit</servlet-name>
            <jsp-file>/TestInit.jsp</jsp-file>
            <init-param>
            <param-name>Email</param-name>
            <param-value>abc@daum.com</param-value>
            </init-param>

   </servlet>
   <servlet-mapping>
//JSP에 대한 서블릿을 정의하려면, JSP 페이지에 대한 서블릿 매핑을 반드시 해야한다
            <servlet-name>MyTestInit</servlet-name>
            <url-pattern>/TestInif.jsp</url-pattern>
   </servlet-mapping>
</web-app>

jspInit() 재정의하기

방식은 아주 단순하다. jspInit() 메소드를 JSP 파일에 코딩해놓으면 컨테이너가 서블릿 인생이 시작하는
시점에 이 메소드를 호출한다. 물론 이메소드는 서블릿 init() 메소드에서 호출한다.
따라서 이 메소드가 실행되는 시점에서는 ServletConfig객체와 ServletContext 객체를 사용할수있다.

아래 예제는 jspInit()에서 DD에 설정되어 있는 서블릿 초기화 파라미터 값을 읽어오는 내용이다. 읽어온 값은
애플리케이션 범위에서 사용할 수 있도록 속성에 묶어둔다
<%! 
//jspInit()을 재정의하려면 <%! 선언문은 사용해야한다 <%를 쓰면 service()메소드 안으로 들어가버린다
     public void jspInit(){
             
            ServletConfig sConfig = getServletConfig()
            // 나중에 서블릿이 될 것이기 떄문에, 상속받은 getServletCOnfig() 메소드를 호출할수있다.

            String emailAddr = sConfig.getInitParameter("Email");

            ServletContext ctx = getServletContext();
         
            ctx.setAttribute("mail", emailAddr);
      }
%>




JSP 내에 있는 속성들

대부분의 경우 JSP에서 이용 가능한 4가지 생존범위 속성과 각각에 매치되는 내장 변수를 가지고 속성을 설정하고 읽고 한다.

표준 서블릿에 있는 request 범위, session 범위, application(context) 범위에 하나를 더추가해서

page 범위까지 총 4개이다. page 범위 속성은 pageContext 객체로 작업을한다.

  서블릿에서  JSP에서(내장 객체를 사용) 
 Application  getServletContext().setAttribute("foo",barObj);  application.setAttribute("foo",barObj);
 Request  request.setAttribute("foo",barObj);  request.setAttribute("foo",barObj);
 Session  request.getSession.setAttribute("foo",barObj);  session.setAttribute("foo",barObj);
 Page 제공하지않음   pageContext.setAttribute("foo",barObj);

pageContext로 속성 접근하기

pageContext는 자신에 설정되어 있는 page 범위 속성뿐만 아니라, 어떤 다른 생존범위 속성도 접근할 수 있을 정도로 매우 막강하다.

다른 생존범위 속성을 참조하려면, 메소드 매개변수로 범위를 나타내는 정수값을 넘겨야 한다. 사실 속성에 접근하는 메소드는

모두 JspContext로부터 상속받아 사용하지만, 속성을 나타내는 상수값은 PageContext에 정의되어 있다.





pageContext를 이용하여 속성을 읽고 설정하는 예제

page 생존범위의 속성 세팅하기
<% Float one = new Float(42.5); %>
<% pageContext.setAttribute("foo", one); %>


page 생존범위의 속성읽기
<%= pageContext.getAttribute("foo") %>


pageContext를 이용하여 session 생존범위 속성 세팅하기
<% Float two = new Float(23.5); %>
<%= pageContext.setAttribute("foo", two, PageContext.SESSION_SCOPE); %>


pageContext를 이용하여 session 생존범위 속성 읽기
<%= pageContext.getAttribute("foo", PageContext.SESSION_SCOPE) %>
(이것과 동일한 의미이다 <%= ssesion.getAttribute("foo")%> )


pageContext를 이용하여 application 생존범위 속성 읽기
<%= pageContext.getAttribute("mail", PageContext.APPLICATION_SCOPE) %>
(이것과 동일한 의미이다 <%= application.getAttribute("mail")%> )


pageContext를 이용하여 어떤 생존범위인지 모르는 속성찾기
<%= pageContext.findAttribute("foo") %>
//findAttribute() 메소드는 속성을 제일먼저 page 생존범위에서 찾는다. page생존범위 속성에 "foo"라는 이름을 가진놈이있으면
PageContext에서 getAttribute(String name)을 부르는 것과 똑같은 결과는 호출하는 것과 같다.
만약 "foo" 라는 이름이 page 생존범위에 없다면 가장작은 범위에서부터 시작해 가장 넓은 범위의 순으로 속성을 찾는다.
즉, request. session, application 속성범위 순으로 찾는다. 똑같은이름이 있더라도 가장 먼저찾은 놈이 넘어 간다.


3가지 지시자

1. page 지시자
<%@ page import="foo.*" session="false" %>
페이지 관련 환경(property)을 정의한다. 즉 문자 인코딩(character encoding), 응답페이지 컨텐츠 타입(content-type),
페이지가 내장 세션 객체를 가질 것인지 여부 등을 정의한다. page 지시자에는 서로다른 속성이 총13가지 존재

2. taglib 지시자
<%@ taglib tagdir="/WEB-INF/tags/cool" prefix="cool" %>
JSP에서 이용 가능한 태그 라이브러리를 정의한다. 뒤에서 자세히 설명

3. include 지시자

<%@ include file="wickedHeader.html" %>
변환시점에 현재 페이지에 포함할 코드나 문서를 정의한다. 여러 JSP페이지에 포함되어야 하는 코드가 있다면, 이를 따로 뽑아내어,
재사용 가능한 단위로 만들어 각각의 페이지에서 이를 포함하면 된다. 예를 들면 문서의 머리말이라든지 내비게이션 바 같은것등,,

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP 기초  (0) 2011.07.01
Session Listener(세션 리스너)  (0) 2011.06.30
세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29

JSP 기초

공부/Sevlets&JSP2011. 7. 1. 10:34
JSP는 결국 웹 애플리케이션에서 돌아가는 서블릿으로 거듭나게된다.

컨테이너가 서블릿을 작성하는 과정은 JSP파일을 서블릿 소스코드(.java)파일로 바꾼ㄷ 뒤, 서블릿 클래스로 컴파일한다.

돌아왔는 바로왔든, 결국은 서블릿이된다. 컨테이너가 서블릿 클래스를 로딩하여 인스턴스화한 다음, 초기화 루틴을 호출하고,

요청이 들어올 때마다 스레드를 만들어, service() 메소드를 호출하는 과정이 정확히 일치한다.

JSP 안에서 자바코드는 <%...%> 태그안에 스크립틀릿(scriptlet)으로 작성한다.

JSP에서도 import문을 쓸수있는데 이걸 쓰려면 지시자를 알아야한다

패키지를 import하기 위해서는 page 지시자를 사용한다.

지시자(directive)는 컨테이너가 페이지를 자바 코드로 변환할 때 특별한 지시를 내릴 수 있도록 고안된 것이다.

지시자에는 3가지가 있는데 page, include, taglib이 그것이다.

일단 page 지시자만 알아보면 page지시자가 import를 가능하게 하는 녀석이다.

 <%@ page import="foo.*" %>
//패키지를 여러개 import할경우 <%@ page import="foo.*",java.util.*" %>
//지시자 끝에는 세미콜론이 없다.

<html>
<body>
the page count is:
<%
     out.println(Counter.getCount());
     //스크립틀릿에는 일반자바소스코드를 그대로 코딩하기떄문에 끝에 반드시 세미콜론이 있어야한다.
%>
</body>
</html>
자바코드는 퍼센트(%) 기호로 묶여있지만 지시자는 시작 부분에 다른문자가 포함되어있다.
JSP코드를보다가 <%@ 로 시작하는 구문을보면 지시자라는 것을 알아 차려야한다.

표현식

-스크립틀릿 코드- 
<%@ page import="foo.*" %>
<html>
<body>
the page count is:
<% out.println(Counter.getCount()); %>
</body>
</html>

-표현식코드-
<%@ page import="foo.*" %>
<html>
<body>
the page count is:
<%= Counter.getCount() %>
</body>
</html>
//표현식은 훨씬 간결하다. 여기서는 더이상 출력에 관련된 코딩을 할 필요가 없다.

<%= Counter.getCount() %> 에서 세미콜론이 빠진것이 이상하지않은가?

그이유는 표현식의 내용은 out.println()의 매개변수가 되기 떄문이다. 다시말하면 <%= 와 %> 사이에 입력한 내용을

내부 Response객체의 PrintWriter 객체인 out으로 출력하기 위한 매개변수로 넘긴다는 말이다.

컨테이너가 이런코드를 만나면

<%= Counter.getCount() %>

아래와같이 변환한다

out.print(Counter.getCount());

그러므로 표현식에 세미콜론을 입력했다면

<%= Counter.getCount(); %>

다음 같이 된다

out.print( Counter.getCount(); );

절대 표현식 끝에 세미콜론을 넣지 말자!



선언문

모든 스크립틀릿 코드와 표현식 코드는 service()메소드 안으로 들어간다

이는 스크립틀릿 안에 선언된 모든 변수는 모두 지역변수를 의미하는데,

선언문을사용해 인스턴스변수로 만들수도있다.

 <%! int count =0; %>
//퍼센트 뒤에 ! 를 붙이면된다
//표현식이아니므로 세미콜론을 붙인다.

<%! 와 %> 안에 들어가는 문장은 서비스 메소드 바깥으로 빠진다. 따라서 정적인 변수나 메소드 또는 인스턴스 변수나 메소드들
모두 여기에 코딩할수 있다.

JSP선언문을 기술하면 클래스 내부에, 서비스 메소드나 여타 메소드의 바깥 쪽에 위치하게 된다. 여기에 간단한 정적인 변수나 메소드
아니면 인스턴스 변수나 메소드를 만들수있다.

컨테이너가 JSP를 어떻게 바꾸는가...

JSP 컨테이너가 결국 서블릿으로 변환시킨다 이때 각각이 서블릿 코드로 어떻게 매핑되는지 알면 JSP 구조를 이해하는 데 도움이된다.

▶ 먼저 지시자(directives)가 있는지 보고선, 변환 작업할때 필요한 정보를 읽는다.

▶HttpServlet의 하위 클래스를 생성

▶import 속성을 가진 page 지시자가 있으면, 클래스 파일의 정의 위에, 패키지 선언 아래에 import문을 넣는다

▶선언문이 있으면, 클래스 파일안에, 서비스 메소드위에, 서블릿 선언 아래에 코딩한다.

▶service()메소드를 만든다. 서비스 메소드의 실제 이름은 _jspService()이다.
   이메소드는 서블릿의 부모 클래스에 정의된 service() 메소드를 이녀석이 호출한다.
   물론 매개변수 HttpServletRequest와 HttpServletResponse를 받는다. 서비스 메소드 처리를 위임받았다고 생각하면된다
   바로밑에 모든 내장객체를 선언하고, 초기화 하는 문장이나온다(밑에 내장객체설명)

▶템플릿 텍스트라고 불리는 HTML과, 스크립틀릿, 표현식을 서비스 메소드 안에 차례대로 Response객체의 출력 스트림인
    PrintWriter의 출력 형식에 맞게 코딩한다.


내장객체


컨테이너가 JSP를 서블릿으로 변환하는 과정 중, 서비스 메소드 선언 다음에 한 묶음의 내장 객체를 선언하고 값을 할당하는 부분이 있다.

JSP를 작성하면서 JSP가 서블릿이 된다는 것을 알기 떄문에, 내장객체를 사용할수있는것이다. 개발자가 서블릿 객체를 직접 코딩하진 않지만,

서블릿이 가지고 있는 특징, 즉 서블릿적인 것(Servletness)을 사용 할수 있다는 말이다.

모든 내장 객체들은 서블릿/JSP API에 일대일로 매핑된다.

예를들면 내장 객체인 request는 컨테이너가 서비스 메소드 매개변수로 넘겨준 HttpServletRequest 객체에 매핑된다.

                API                                         내장객체

                JspWriter    -----------------             out        
     HttpServletRequest   ---------------          request
     HttpServletResponse --------------          response
             HttpSession     ---------------          session
        ServletContext     ----------------        application
        JspException     ----------------         exception //이 내장객체는 "오류 페이지"에 쓸 요량으로만든것이다 (나중설명)
          PageContext    ----------------          pageContext
              //PageContext는 다른 내장 객체들을 포함(은닉)하고 있기떄문에 도우미 클래스로 PageContext만 넘겨도
                 필요한 다른 내장 객체 및 모든 생존범위 속성을 사용할수 있다.

                Object       ----------------          page

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP API 와 속성  (0) 2011.07.01
Session Listener(세션 리스너)  (0) 2011.06.30
세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29

<출처:http://blog.daum.net/wiznel/4653677 >
  • HTML에 JavaScript 삽입
    <script language="javascript">
    JavaScript Statements
    </script>

  • HTML에 JavaScript 코드 파일 삽입
    <script language="javascipt" src="src.js">
    </script>

  • 변수의 대소문자 구분
  • 변수에 포함된 데이터의 형을 지정하지 않고, JavaScript 인터프리터가 변수에 포함된 데이터 형을 추적하고 변환.
  • JavaScript 데이터 형
    • 숫 자 형 : 정수와 부동 소수
    • BOOLEAN : true, false
    • STRING : 작은 따옴표나 큰 따옴표에 들어가 있는 값으로, 특수문자 포맷 사용시에는 '\'와 함께 사용.
    • null : 아무런 값도 없는 것으로, 변수를 초기화 시키거나 어떤 값이나 이벤트를 지울 때 사용됨
    • undefined : 변수만 만들고, 값을 할당하지 않은 상태
  • 유형간의 변환
    • 스트링 피연산자가 비스트링 연산자와 사용된 경우 다른 연산자를 모두 스트링으로 변환
    • BOOLEAN값은 1과 0으로 변환되어 수치 연산을 지원
    • null값은 스트링 연산에 대해서는 "null", 논리 연산에서는 false, 그리고 수치 연산에서는 0으로 각각 변환
    • 변환 함수
      • eval!() : 스트링 표현식을 수치값으로 변환하고, 파라미터가 수치형태가 아닌 스트링 값이면 에러 발생
      • parseInt() : 스트링에 포함된 첫번째 정수를 리턴하고, 스트링이 정수로 시작되지 않으면 0을 리턴
      • parseFloat() : 스트링에 포함된 첫번째 부동 소수를 리턴하거나 스트링이 적절한 부동 소수로 시작되지 않으면 0을 리턴
  • 배열 : 값의 시퀀스를 정렬할 수 있는 객체로, JavaScript의 특수형으로 배열 사용 전엔 반드시 선언해야 한다.
    • 배열 선언 예
      arrayName = new Array(arrayLength)
      arrayName = new Array()
      arrayName = new Array(value0,value1, ..., valuen)
  • JavaScript만의 특수 연산자
    • comma(,) 연산자 : 두 표현식을 계산하고, 두 번째 표현식의 값 리턴
    • delete 연산자 : 객체의 프로퍼티나 배열 인덱스의 요소 삭제하고, 항상 undefined 값 리턴
    • new 연산자 : 객체 형의 인스턴스를 만들기 위해 사용
    • typeof 연산자 : 연산자의 형을 식별하는 스트링 값을 리턴
    • void 연산자 : 값을 리턴하지 않는다
  • 지역 변수와 전역 변수 : 함수 안에서만 사용되는 것을 지역 변수라 하고, 프로그램 내에서 사용되는 변수를 전역 변수라 하는 데, 지역 변수 사용시 반드시 var 키워드와 함께 선언해야 함

    이벤트 처리!!

    • 이벤트 정의와 사용
      • 이벤트 : 사용자가 웹페이지나 기타 다른 브라우저에 수행한 작업으로 인한 결과
      • 이벤트 처리 : 이벤트로 인해 수행되는 프로세스
      • 이벤트 핸들러 : 프로세스를 수행하는 코드
      • 사용 예 : 사용자가 링크 위로 마우스를 갖다 대면 다이얼로그 박스를 표시한다거나, 폼에 입력한 데이터를 검증한다거나, 버튼을 클릭할 때 애니메이션을 나타내거나, Java 애플릿과 브라우저 플러그인이 상호작용을 하도록 한다.

    • JavaScript가 정의한 이벤트
      HTML 태그 JavaScript 이벤트 설명
      다양 mouseMove 마우스 이동
      <A>..</A> Click 마우스로 링크를 클릭
      dbClick 마우스를 링크위에서 더블클릭
      mouseDown 마우스 버튼을 누름
      mouseUp 마우스 버튼을 놓음
      mouseOver 마우스를 링크위로 이동
      mouseOut 링크 위에 있던 마우스를 링크 밖으로 이동
      keyDown 사용자가 키를 누름
      keyUp 사용자가 키를 놓음
      keyPress 사용자가 키를 눌렀다가 놓음
      <IMG> abort 사용자 액션으로 인해 이미지 로딩 작업을 중단함
      error 이미지 로딩하는 동안 에러 발생
      load 이미지가 로드되고 화면에 나타남
      keyDown 사용자가 키를 누름
      keyUp 사용자가 키를 놓음
      keyPress 사용자가 키를 눌렀다가 놓음
      <AREA> mouseOver 마우스가 클라이언트측 이미지맵의 한 영역으로 이동함
      mouseOut 마우스가 이미지맵 영역 밖으로 이동
      dbClick 사용자가 이미지맵의 한 영역을 더블클릭함
      <BODY>..</BODY> Click 사용자가 문서의 본문을 클릭
      dbClick 문서의 본문을 더블 클릭함
      keyDown 키를 누름
      keyUp 키를 놓음
      keyPress 키를 눌렀다가 놓음
      mouseDown 마우스 버튼을 누름
      mouseUp 마우스 버튼을 놓음
      <BODY>..</BODY>
      <FRAMESET>..</FRAMESET>
      <FRAME>..</FRAME>
      blur 윈도우에서 현재 입력 포커스가 사라짐
      error 윈도우가 로드되는 동안 에러 발생
      focus 입력 포커스가 현재 윈도우로 이동
      load 윈도우 로딩이 완료됨
      unload 윈도우를 종료함
      move 윈도우가 이동됨
      resize 윈도우의 크기가 바뀜
      dragDrop 윈도우에 객체를 드롭
      <FORM>..</FORM> submit 사용자가 폼을 제출
      reset 사용자가 폼을 재설정
      <INPUT TYPE="text"> blur 현재 입력 포커스가 텍스트 필드에서 사라짐
      focus 현재 입력 포커스가 텍스트 필드로 이동
      change 텍스트 필드가 변경되어 현재 입력 포커스가 사라짐
      select 텍스트 필드에 있는 텍스트가 선택됨
      <INPUT TYPE="password"> blur 패스워드 필드에서 입력 포커스가 사라짐
      focus 패스워드 필드에 입력 포커스 생김
      <TEXTAREA>..</TEXTAREA> blur 텍스트 영역이 현재 입력 포커스가 사람짐
      focus 텍스트 영역에 입력 포커스 생김
      change 텍스트 영역이 변경되어 입력 포커스가 사라짐
      select 텍스트 영역에서 텍스트가 선택됨
      keyDown 키를 누름
      keyUp 키를 놓음
      keyPress 키를 눌렀다 놓음
      <INPUT TYPE="button"> Click 버튼이 클릭됨
      blur 입력할 수 없도록 버튼이 흐려짐
      focus 입력할 수 있도록 포커스 생김
      mouseDown 버튼 위에서 왼쪽 마우스 버튼 누름
      mouseUp 버튼 위에서 왼쪽 마우스 버튼 놓음
      <INPUT TYPE="submit"> Click 제출 버튼이 클릭됨
      blur 제출 버튼에서 입력 포커스가 사라짐
      focus 제출 버튼에 입력 포커스 생김
      <INPUT TYPE="reset"> Click 리셋 버튼이 클릭됨
      blur 리셋 버튼에서 포커스가 사라짐
      focus 리셋 버튼에서 포터스가 놓임
      <INPUT TYPE="radio"> Click 라디오 버튼이 클릭
      blur 라디오 버튼에서 입력 포커스가 사라짐
      focus 라디오 버튼에 입력 포커스 생김
      <INPUT TYPE="checkbox"> Click 체크 박스가 클릭
      blur 체크 박스에서 입력 포커스가 사라짐
      focus 체크 박스에 입력 포커스 놓임
      <INPUT TYPE="file"> blur 파일 업로드 폼 요소에서 입력 포커스 사라짐
      change 사용자가 업로드될 파일을 선택
      focus 파일 업로드 폼 요소에 입력 포커스 놓임
      <SELECT>..</SELECT> blur 선택 요소가 현재 입력 포커스 잃음
      change 선택 요소가 변경되어 입력 포커스가 사라짐
      focus 선택 요소에 현재 입력 포커스가 놓임

    • 이벤트 처리 속성
      이벤트핸들링속성 실행되는 상황
      onAbort 이미지를 로딩하는 작업이 사용자의 한 행동으로 인해 취소되었음
      onBlur! 문서나 윈도우, 프레임세트, 폼 요소에서 현재 입력 포커스가 사라짐
      onChange 텍스트 필드나 텍스트 영역, 파일 업로드 필드, 선택 항목이 변경되어 현재 입력 포커스가 사라짐
      onClick 링크나 클라이언트측 이미지맵 영역, 폼 요소가 클릭됨
      onDbClick 링크나 클라이언트측 이미지맵 영역, 문서가 더블 클릭됨
      onDragDrop 드래그된 객체가 윈도우나 프레임에 드롭됨
      onError 이미지나 윈도우, 프레임을 로딩하는 동안 에러가 발생함
      onFocus 문서나 윈도우, 프레임 세트, 폼 요소에 입력 포커스 놓임
      onKeyDown 키를 누름
      onKeyPress 키를 눌렀다 놓음
      onKeyUp 키를 놓음
      onLoad 이미지나 문서, 프레임이 로드됨
      onMouseDown 마우스 버튼 누름
      onMouseMove 마우스를 이동함
      onMouseOut 링크나 클라이언트측 이미지맵에서 마우스를 옮김
      onMouseOver 마우스를 링크나 클라이언트측 이미지맵으로 옮김
      onMouseUp 마우스 버튼을 놓음
      onMove 사용자가 윈도우나 프레임을 이동함
      onReset 폼의 리셋 버튼을 클릭하여 폼을 리셋시킴
      onResize 사용자가 윈도우나 프레임의 크기를 조절
      onSelect 텍스트는 텍스트 필드나 영역에서 선택됨
      onSubmit 폼이 제출됨
      onUnload 사용자가 문서나 프레임 세트를 종료함



    객체 정의하기

    • 객체 유형 정의
      • 프로퍼티 : 객체에 들어 있는 데이터 값에 액세스할 때 사용.
      • 메소드 : 객체에 어떤 작업을 할 때 사용하는 함수.
    • 객체 유형 만들기
      사용자가 직접 객체 유형을 정의하고 특정 객체 인스턴스를 만들 수 있 는데 이렇게 만들려면 객체 유형의 특정 인스턴스를 만들 때 사용되는 함수를 정의하기만 하면 된다. 본래 이러한 생성자 함수는 다음과 같은 일을 한다.
      • 객체 유형의 프로퍼티에 값을 할당한다.
      • 객체 유형의 메소드로 사용할 수 있는 다른 함수를 지정한다.
    • 객체 사용 예
      1. table 객체의 정의 (table.js)
        function table_getValue(row,col){
        return this.data[row* this.columns+col ];
        }
        function table_setValue(row,col,value){
        this.data[row* this.columns+col ]=value;
        }
        function table_set(contents){
        var n=contents.length;
        for(var j=0;jthis.data[j]=contents[j];
        }
        function table_isHeader(row,col){
        return this.header[row* this.columns+col ];
        }
        function table_makeHeader(row,col){ this.header[row* this.columns+col ]=true;
        }
        function table_makeNormal(row,col){ this.header[row* this.columns+col ]=false;
        }
        function table_makeHeaderRow(row){ for(var j=0;j< this.columns+j)
        this.header[row* this.columns+col ]=true;
        }
        function table_makeHeaderColumn(col){ for(var i=0;i< this.rows;++i)
        this.header[i* this.columns+col ]=true;
        }
        function table_write(doc){
        doc.write("<TABLE BORDER="+ this.border+">");
        for(var i=0;i< this.rows;++i) {
        doc.write("<TR>");
        for(var j=0;j< this.columns;++j) {
        if( this.header[i* this.columns+j ]) {
        doc.write("<TH>");
        doc.write( this.data[i* this.columns+j ]);
        doc.write("</TH>");
        }
        else {
        doc.write("<TD>");
        doc.write( this.data[i* this.columns+j ]);
        doc.write("</TD>");
        }
        }
        doc.writeln("</TR>");
        }
        doc.writeln("</TABLE>");
        }
        funtion table(rows,columns) {
        this.rows=rows
        this.columns=columns
        this.border=0
        this.data=new Array(rows*columns)
        this.header=new Array(rows*columns)
        this.getValue=table_getValue
        this.setValue=table_setValue
        this.set=table_set
        this.isHeader=table_isHeader
        this.makeHeader=table_makeHeader
        this.makeNormal=table_makeNormal
        this.makeHeaderRow=table_makeHeaderRow
        this.makeHeaderColumn=table_makeHeaderColumn
        this.write=table_write
        }

      2. table 객체 사용하기
        <HTML>
        <HEAD>
        <TITLE>Defining Object Types</TITLE
        <SCRIPT LANGUAGE="JavaScript" SRC="table.js"><!-
        //-></SCRIPT>
        </HEAD>
        <BODY>
        <H1>Defining Object Types</H1>
        <SCRIPT LANGUAGE="JavaScript"><!-
        t=new table(3,4)
        contents=new
        Array("This","is","a","test","of","the","table","object.","Let's","see","it","work")
        t.set(contents)
        t.border=4
        t.makeHeaderColumn(0)
        t.write(document)
        //-></SCRIPT>
        </BODY>
        </HTML>

      3. 객체 유형에 프로퍼티와 메소드 추가
        : prototype 프로퍼티를 통해서 인스턴스화할 수 있는 미리 정의된 객체 유형에 프로퍼티와 메소드 추가
        사용 예
        <HTML>
        <HEAD>
        <TITLE>Updating Object Types </TITLE>
        <SCRIPT LANGUAGE="JavaScript" SRC="table.js"><!-
        //-></SCRIPT>
        </HEAD>
        <BODY>
        <H1>Updating Object Types</H1>
        <SCRIPT LANGUAGE="JavaScript"><!-
        function table_colorWrite(doc){
        ........
        함수 정의
        ........
        ........
        }
        t=new table(3,4)
        table.prototype.bgColor="Cyan"
        table.prototype.colorWrite=table_colorWrite
        .............
        .............
        t.colorWrite(document)
        //-></SCRIPT>
        </BODY>
        </HTML>

      4. 프로퍼티와 메소드 삭제
        delete objectName.propertyName
        delete objectName.methodName



    브라우저 객체

    객 체 용 도
    window 객체 브라우저 윈도우나 윈도우 안에 있는 프레임에 액세스할 때 사용한다. 프로퍼티와 메소드를 참조할 때, window 객체가 존재하는 경우에는 "window."접두사를 붙일 필요가 없다
    document 객체 현재 윈도우에 로드되어 있는 문서에 액세스할 때 사용한다. document 객체는 컨텐트를 제공하는 HTML 문서, 즉 HEAD와 BODY 태그가 있는 문서를 의미한다.
    location 객체 URL을 나타낼 때 사용한다. 이 객체는 URL객체를 만들거나 URL의 일부분에 액세스하거나 기존의 URL을 수정할 때 사용할 수 있다.
    history 객체 한 윈도우 안에서 액세스된 URL의 히스토리를 유지할 때 사용
    frame 객체, frames 배열 HTML 프레임에 액세스할 때 사용
    frames 배열은 윈도우안에 있는 모든 프레임에 액세스할 때 사용
    link 객체, links 배열 하이퍼텍스트 링크의 텍스트 기반이나 이미지 기반 소스 앵커(anchor)에 액세스할 때 사용
    links배열은 문서 안에 있는 모든 link 객체에 액세스할 때 사용한다. I.E.는 link 객체의 anchor객체를 결합한다.
    anchor 객체, anchors 배열 하이퍼텍스트 링크의 타켓에 액세스할 때 사용
    anchors 배열은 문서 안에 있는 모든 anchor 객체에 액세스할 때 사용
    image객체, images 배열 HTML 문서에 삽입되어 있는 이미지에 액세스할 때 사용
    images 배열은 문서 안에 있는 모든 image 객체에 액세스할 때 사용
    area 객체 클라이언트측 이미지맵 안에 있는 영역에 액세스할 때 사용
    applet! 객체, applet!s 배열 Java 애플릿에 액세스할 때 사용
    애플릿 배열은 문서 안에 있는 모든 애플릿에 액세스할 때 사용
    event 객체, Event 객체 이벤트 발생에 대한 정보에 액세스할 때 사용
    event 객체는 특정 이벤트에 대한 정보 제공
    Event 객체는 이벤트를 식별하는 데 사용하는 상수 제공
    form 객체, forms 배열 HTML 폼에 액세스시 사용
    forms 배열은 문서 안에 있는 모든 폼에 액세스시 사용
    element 객체 폼 안에 들어있는 모든 폼 요소에 액세스시 사용
    text 객체 폼의 텍스트 필드에 액세스시 사용
    textarea 객체 폼의 텍스트 영역 필드에 액세스시 사용
    radio 객체 폼의 라디오 버튼 세트에 액세스하거나 세트 안에 있는 각각의 버튼에 액세스할 때 사용
    checkbox 객체 폼의 체크 박스에 액세스할 때 사용
    button 객체 Submit나 Reset 버튼이 아닌 폼 버튼에 액세스시 사용
    reset 객체 폼의 Reset 버튼에 액세스시 사용
    selet 객체 폼의 선택 리스트에 액세스시 사용
    option 객체 option 객체는 선택 리스트의 요소에 액세스시 사용
    password 객체 폼의 패스워드 필드에 액세스시 사용
    hidden 객체 폼의 숨겨진 필드에 액세스시 사용
    FileUpload 객체 폼의 파일 업로드 요소에 액세스시 사용
    navigator 객체 스크립트를 실행하고 있는 브라우저에 대한 정보에 액세스시 사용
    screen 객체 사용자의 화면의 색상 깊이와 크기에 대한 정보에 액세스시 사용
    embed 객체, embeds 배열 삽입된 객체에 액세스시 사용
    embeds 배열은 문서 안에 삽입된 모든 객체에 대한 액세스 제공
    mimeType 객체, mimeTypes 배열 브라우저가 제공하는 특징 MIME 유형에 대한 정보에 액세스시 사용
    mimeTypes 배열은 제공하는 모든 mimeType 객체의 배열
    I.E.는 빈 배열을 리턴하면서 mimeTypes에 대해서 임시적으로 지원
    plugin 객체, plugins 배열 특정 브라우저 플러그인에 대한 정보에 액세스시 사용
    plugins 배열은 브라우저가 지원하는 모든 플러그인의 배열
    I.E.는 빈 배열을 리턴하면서 plugins에 대해서 임시적으로 지원


    window 객체

    • 모든 브라우저 스크립트의 기본적인 것으로, 브라우저가 자동으로 정의하는 최상위 레벨의 객체이다. 현재 열려 있는 각 윈도우에 대해 별도의 window 객체가 정의된다.


    window 객체의 프로퍼티
    프로퍼티 설 명
    closed 윈도우가 닫혀 있는지 식별
    defaultStatus 브라우저 윈도우의 하단의 상태바에 나타나는 디폴트 상대 메시지를 지정
    document 윈도우에 표시되어 있는 현재 문서를 지정하는 객체
    frames 윈도우 객체에 들어 있는 모든 프레임 객체로 구성된 배열
    history 마지막으로 윈도우로 로드된 URL의 리스트를 포함하는 윈도우의 히스토리 객체
    length window에 들어 있는 프레임의 수 식별
    location window 객체와 관련된 URL을 지정하는 객체
    name 윈도우의 이름 지정
    offscreenBuffering 윈도우 정보의 오프스크린 버퍼링이 사용될 것인지를 지정하는 부울값
    오프스크린 버퍼링은 윈도우를 나타내기 전에 윈도우의 모든 요소를 로드할 때 사용
    opener 윈도우를 만들거나 열 수 있도록 해주는 window 객체 지정
    parent 특정 윈도우를 포함하는 윈도우를 지정하는 시너님
    self 참조될 현재 윈도우를 지정하는 시너님
    status 브라우저 윈도의 하단의 상태 표시줄에 나타날 임시 메시지를 지정
    top 중첩된 일련의 윈도우에서 맨 위에 있는 브라우저 윈도우를 의미하는 시너님
    window 참조될 현재 윈도우를 식별하는 시너님

    window 객체의 메소드
    메 소 드 설 명
    alert!(text) 경고 다이얼로그 박스를 표시
    blur() 포커스를 윈도우에서 옮긴다
    setInterval(expression!,milliseconds) 지정된 타임아웃 인터벌이 지난 이후에 표현식을 반복해서 평가하거나 함수를 불러온다.
    clearInterval(interval) 이전에 설정된 인터벌 타이머를 클리어
    setTimeout(expression!,milliseconds) 타임아웃 기간이 지난 이후에 표현식을 평가하거나 함수를 호출한다.
    clearTimeout(timer) 이전에 설정된 타임아웃을 클리어
    close() 지정된 윈도우를 닫는다.
    confirm!(text) 확인 다이얼로그 박스를 나타낸다.
    focus() 윈도우로 포커스를 가져간다.
    open(url,name,[options]) 새로운 윈도우를 열고 새로운 window 객체를 만듬
    prompt(text,defaultInput) 프롬프트 다이얼로그 박스를 나타낸다.
    scroll(x,y) 윈도우를 특정 위치까지 스크롤한다.

    open() 메소드의 옵션
    옵 션 설 명
    toolbar yes no 윈도우에 툴바 제공
    location yes no 윈도우에 위치 필드 제공
    directories yes no 디렉토리 버튼 제공
    status yes no 상태 표시줄 제공
    menubar yes no 메뉴바 제공
    scrollbars yes no 스크롤 바 제공
    resizable yes no 윈도우 크기 조절 가능
    width 정수 윈도우의 폭(픽셀)
    height 정수 윈도우의 높이(픽셀)


    frame 객체

    • 프레임은 윈도우를 독립된 표시 영역들로 분할한 후, 이 영역들에 표시되는 정보들을 강력하게 컨트롤 할 수 있게 해준다.
    • 프레임 객체의 프로퍼티와 메소드는 window 객체와 같지만, close() 메소드는 지원하지 않는다.



    document 객체

    • JavaScript 에서 아주 중요한 객체로, 이 객체를 사용하면 로드될 문서를 업데이트하고 로드된 문서 안에 있는 HTML 요소에 액세스할 수 있다.


    프로퍼티 설 명
    alinkColor <BODY> 태그의 alink 속성의 값 지정
    anchor 문서에 들어 있는 배열을 참조하는 객체
    anchors 문서에 들어 있는 모든 앵커의 배열
    applet! 문서에 들어 있는 애플릿을 참조하는 객체
    applet!s 문서에 들어 있는 모든 애플릿의 배열
    area 문서 안의 이미지맵 영역을 참조하는 객체
    bgColor <BODY> 태그의 bgColor 속성의 값 식별
    cookie 쿠키의 값 식별
    domain 문서가 로드되는 서버의 도메인 이름 식별
    embeds 문서안의 모든 플러그인의 배열
    fgColor <BODY> 태그의 text 속성값 지정
    form 문서 안의 폼을 참조하는 객체
    Forms[] 문서 안의 모든 폼의 배열
    image 문서 안의 이미지를 참조하는 객체
    Images[] 문서 안의 모든 이미지의 배열
    lastModified 문서가 마지막으로 수정된 날짜
    link 문서 안의 링크를 참조하는 객체
    links 문서 안의 모든 링크의 배열
    linkColor <BODY> 태그의 link 속성의 값 식별
    plugin 문서 안의 플러그인을 참조하는 객체
    plugins[] 브라우저가 지원하는 플러그인을 나타내는 객체의 배열
    referrer 문서에 대한 링크를 제공하는 문서의 URL
    title 문서의 타이틀
    URL 문서의 URL
    vlinkColor <BODY> 태그의 vlink 속성의 값 식별

    document 객체의 메소드
    메 소 드 설 명
    close() 문서의 객체를 만드는 데 사용된 스트림
    open([mimeType][,"replace"]) 선택적인 MIME 유형으로 문서 객체를 만들 때 사용되는 흐름을 개시한다. "replace" 파라미터는 text/html MIME 유형과 함께 사용되어 히스토리 리스트에 있는 현재 문서를 대체
    write(expr1[,expr2...,exprN]) 문서에 표현식의 값을 기록
    write(expr1[,expr2...,exprN]) 개행 문자가 다음에 따라오는 문서에 표현식의 값 기록


    navigator 객체

    • navigator 객체는 window 객체와 마찬가지로 브라우저 객체 모델에서 최상위 레벨의 객체이며, 스크립트를 실행할 때 사용되는 브라우저의 종류와 버전에 대한 정보 제공한다.


    navigator 객체의 프로퍼티
    프로퍼티 브라우저 지원 설 명
    appCodeName N2, I.E3 브라우저 색상 이름
    AppMinorVersion I.E4 브라우저 버전 번호
    appName N2, I.E3 브라우저 이름
    appVersion N2, I.E3 브라우저의 버전
    browserLanguage I.E4 브라우저에 설정되어 있는 언어
    connectionSpeed I.E4 브라우저가 네트워크에 연결되는 속도
    cookieEnabled I.E4 브라우저가 쿠키를 허용하도록 설정되어 있는지의 여부
    cpuClass I.E4 브라우저 실행시 사용되는 마이크로프로세서의 유형
    onLine I.E4 브라우저가 현재 온라인 연결을 가지고 있는지 여부
    Language N4, I.E4 브라우저에 설정되어 있는 언어
    mimeTypes N3, I.E4 현재 브라우저가 지원하는 모든 MIME 유형의 배열
    platform N4, I.E4 브라우저가 실행되는 운영체제 플랫폼
    plugins N3, I.E4 현재 브라우저에 설치된 모든 플러그인의 배열
    systemLanguage I.E4 운영체제의 디폴트 언어
    userAgent N2, I.E3 브라우저에서 서버로 전송된 HTTP 프로토콜의 사용자 에이전트 헤더
    userLanguage I.E4 사용자가 사용하는 언어
    userProfile I.E4 사용자 프로파일 정보에 대한 액세스를 제공하는 객체

    navigator 객체의 메소드
    메 소 드 설 명
    javaEnabled() 사용자가 브라우저의 Java 기능을 켜두었는지의 여부를 나타내는 부울값 리턴
    taintEnabled() 사용자가 data tainting(보안 메커니즘)을 활성화했는지 여부를 나타내는 부울값 리턴
    preference 서명이 되지 않은 스크립트가 보안 관련 프로퍼티를 얻고 설정할 때 사용


    event 객체

    event 객체의 프로퍼티
    프로퍼티 브라우저 설 명
    data N DragDrop 이벤트로 인해 드롭된 객체의 URL이 들어있는 스트링 배열
    height, width N 윈도우나 프레인의 길이와 너비(픽셀표시)
    pageX, pageY N 픽셀로 나타낸 커서의 수평/수직 위치(페이지에서의 상대적위치)
    screenX, screenY N, I.E 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치)
    layerX, layerY N 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 레이어에 대한 상대적 위치. Resize 이벤트와 함께 사용하면 layerX와 layerY가 이벤트가 타겟으로 하는 객체의 길이와 너비 지정
    clientX와 clientY I.E 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 웹페이지에서의 상대적 위치
    offsetX, offsetY I.E 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 컨테이너에 대한 상대적 위치
    X, Y I.E 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 문서에 대한 상대적 위치
    target N 이벤트가 전송된 원래 객체
    srcElement I.E 이벤트가 전송된 원래 객체
    type N, I.E 발생한 이벤트 유형
    which N 눌려진 마우스 버튼(왼:1, 가:2, 오:3)이나 눌려진 키의 ASCII값
    keyCode I.E 키 누름과 연관된 Unicode 키 코드를 식별
    button I.E 이벤트가 발생했을 때 눌려진 마우스 버튼 식별(0:눌려진버튼없음, 1:왼, 2:오, 4:가)
    modifiers N 마우스나 키 이벤트와 연관된 수정자 키(ALT_MASK,CONTROL_MASK,SHIFT_MASK,META_MASK)를 식별
    altkey,ctrlkey,shiftkey I.E true나 false로 설정하여 이벤트가 발생했을 때 Alt키와 Control키, Shift 키 중에 어떤 것이 눌려졌는지 알려준다.
    cancelBubble I.E true나 false로 설정하여 이벤트 버블링을 취소하거나 활성화한다.
    fromElement, toElement I.E 이동 중인 HTML 요소 지정
    reason I.E 데이터 소스 객체에 대한 데이터 전송 상태를 나타내는데 사용
    returnValue I.E true나 false로 설정하여 이벤트 핸들러의 리턴값을 나타낸다. 이벤트 핸들러에서 true나 false를 리턴하는 것과 같다.
    srcFilter I.E onfilterchange 이벤트를 시작하는 filter객체 지정


    screen 객체

  • screen 객체의 프로퍼티
    • height : 사용자의 화면의 현재 높이(픽셀)
    • width : 사용자의 화면의 현재 너비(픽셀)
    • colorDepth : 사용자의 화면/비디오 카드에서 현재 지원하는 색상당 바이트 수


    form 객체

    • document 객체의 프로퍼티로 액세스되고, form 객체는 문서 안의 폼에 액세스할 수 있도록 해주고, 폼 관련 이벤트에 응답을 할 수 있도록 해주기 때문에 중요하다.
    form 객체의 프로퍼티
    프로퍼티 설 명
    action <FORM> 태그의 HTML action 속성에 대한 액세스 제공
    button GUI 컨트롤 버튼을 나타내는 객체
    checkbox 체크 박스 필드를 나타내는 객체
    elements 폼 안에 포함되어 있는 모든 필드와 GUI 컨트롤을 포함하는 배열
    encoding <FORM> 태그의 HTML enctype 속성에 대한 액세스 제공
    FileUpload 파일 업로드 폼 필드를 나타내는 객체
    hidden 숨겨진 폼 필드를 나타내는 객체
    length elements 배열의 길이에 대한 액세스 제공
    method <FORM> 태그의 HTML method 속성에 대한 액세스 제공
    name 폼의 이름 식별
    password 패스워드 필드를 나타내는 객체
    radio 라디오 버튼 필드를 나타내는 객체
    reset reset 버튼을 나타내는 객체
    select 선택 항목 리스트를 나타내는 객체
    submit submit 버튼을 나타내는 객체
    target <FORM> 태그의 HTML target 속성에 대한 액세스 제공
    text 텍스트 필드를 나타내는 객체
    textarea 텍스트 영역 필드를 나타내는 객체

    form 객체의 메소드
    메 소 드 설 명
    handleEvent() 지정된 이벤트에 대한 폼의 이벤트 핸들러를 호출할 때 사용
    submit() 폼을 제출시 사용
    reset 폼의 엔트리를 디폴트 값으로 재설정시 사용

    form 요소 객체의 프로퍼티
    객 체 프로퍼티 설 명
    button name 버튼의 name 속성에 대한 액세스 제공
    type 객체의 유형 지정
    value 객체의 값 지정
    checkbox checked 체크박스가 현재 체크되어 있는지를 식별
    defaultChecked 체크박스가 디폴트로 체크되어 있는지 식별
    name 체크박스의 HTML name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    FileUpload name 객체의 name 속성에 대한 액세스 제공
    type 객체의 type 속성에 대한 액세스 제공
    value 객체의 값 식별
    hidden name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    password defaultChecked 객체의 디폴트 값 식별
    name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    radio checked 라디오 버튼이 체크되어 있는지 식별
    defaultChecked 라디오 버튼이 디폴트로 체크되어 있는지 식별
    name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    reset name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    select length 선택 리스트의 길이 식별
    name 객체의 name 속성에 대한 액세스 제공
    option 선택 리스트가 제공하는 옵션 식별하는 배열
    selectedIndex 선택 리스트 안에서 처음 선택된 옵션 식별
    type 객체의 유형 식별
    submit name 객체의 name 속서에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    text defaultValue 텍스트 필드에 나타나는 디폴트 텍스트를 식별
    name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별
    textarea defaultValue 텍스트 영역 필드에 나타나게 되는 디폴트 텍스트 식별
    name 객체의 name 속성에 대한 액세스 제공
    type 객체의 유형 식별
    value 객체의 값 식별

    form 요소 객체의 메소드
    객 체 메 소 드 설 명
    button Click() 클릭된 버튼 시뮬레이트
    blur() 포커스 잃음
    focus() 포커스 맞춤
    checkbox Click() 클릭된 체크 박스 시뮬레이트
    blur() 포커스 잃음
    focus() 포커스 맞춤
    FileUpload blur() 포커스 잃음
    focus() 포커스 맞춤
    select() 입력 영역을 선택
    hidden 없음
    password blur() 포커스 잃음
    focus() 포커스 맞춤
    select() 패스워드 필드에 나타나는 텍스트를 하이라이트
    radio Click() 라디오 버튼 클릭 시뮬레이트
    blur() 포커스 잃음
    focus() 포커스 맞춤
    reset Click() 리셋 버튼 클릭 시뮬레이트
    blur() 포커스 잃음
    focus() 포커스 맞춤
    select blur() 포커스 잃음
    focus() 포커스 맞춤
    submit Click() 제출 버튼 클릭 시뮬레이트
    blur() 포커스 잃음
    focus() 포커스 맞춤
    text blur() 포커스 잃음
    focus() 포커스 맞춤
    select() 텍스트 필드에 있는 텍스트 하이라이트
    textarea blur() 포커스 잃음
    focus() 포커스 맞춤
    select() 텍스트 영역에 있는 텍스트 하이라이트


    location 객체

    • 윈도우에 로드되어 있는 현재 문서의 URL에 액세스하거나 새로운 문서를 로드할 때 사용

    location 객체의 프로퍼티
    프로퍼티 설 명
    hash URL의 앵커 부분(존재하는 경우)
    host URL의 hostname:port 부분
    hostname URL의 host부분
    href 전체 URL
    pathname URL의 경로명 부분
    port URL의 포트 부분
    protocol URL의 프로토콜 부분
    search URL의 쿼리 스트링 부분

    location 객체의 메소드
    • reload() : 윈도우의 현재 문서를 브라우저의 Reload 버튼에서 사용하는 정책에 따라 다시 로드
      • Every time : 문서는 매번 서버에서 다시 로드
      • Once per session : 서버의 문서의 날짜가 캐시에 저장되어 있는 문서보다 더 최신 날짜라는 것을 나타내면 문서는 세션당 한 번씩 서버에서 다시 로드된다. 문서가 캐시에 없는 경우에는 서버에서 로드
      • Never : 문서는 가능하면 캐시에서 다시 로드, 그렇지 않으면 서버에서 로드
    • replace() : URL을 파라미터로 취하여, 현재 문서 히스토리 목록에 있는 현재 문서위로 그 URL의 문서를 로드, 그러면 브라우저의 Back버튼을 클릭하여 이전 문서로 돌아갈 수 없음


    link 객체

    • link 객체는 document 객체의 프로퍼티로, 문서에 들어있는 텍스트나 이미지 링크를 캡슐화
    • links 배열은 문서에 들어있는 모든 링크의 배열
    • link 객체의 메소드
      handleEvent() : event 객체를 인자로 취하며 그 이벤트에 대해 적당한 이벤트 핸들러 호출

    link 객체의 프로퍼티
    프로퍼티 설 명
    hash URL의 앵커 부분(존재하는 경우)
    host URL의 hostname:port 부분
    hostname URL의 host부분
    href 전체 URL
    pathname URL의 경로명 부분
    port URL의 포트 부분
    protocol URL의 프로토콜 부분
    search URL의 쿼리 스트링 부분
    target 링크의 HTML, target 속성


    anchor 객체

    • HTML 문서 안에서 이름이 지정된 오프셋으로 사용되는 앵커 의미
    • anchors 배열에는 문서의 모든 앵커가 들어있음
    • 프로퍼티나 메소드 또는 이벤트를 전혀 가지고 있지 않음
    • HTML 문서와 관련하여 정의된 이름이 지정된 오프셋을 추적할 때 사용
    • anchor 객체는 HREF 속성을 포함하는 경우에 link 객체가 된다.


    history 객체

    • history 객체의 프로퍼티
      • current : 윈도우에 나타나는 현재 문서의 URL
      • length : History 리스트의 길이
      • next : History 리스트에서의 다음 URL
      • previous : History 리스트에서의 이전 URL
    • history 객체의 메소드
      • back() : History 리스트에 이전 문서를 로드. 브라우저의 Back 버튼을 클릭하는 것과 같은 효과
      • forward() : History 리스트에 다음 문서를 로드. 브라우저의 Forward 버튼을 클릭하는 것과 같은 효과
      • go() : History 리스트에 있는 특정 문서로 감
        • go(n) : n>0인 경우, 이 메소드는 History 리스트에서 n개의 엔트리가 앞에 있는 문서를 로드, n=0인 경우에는 현재 문서가 다시 로드되고, n<0인 경우엔 History 리스트에서 n개의 엔트리 뒤에 있는 문서를 로드
        • go(string) : go()는 이 스트링을 서브스트링으로 갖고 있는 URL의 History 리스트에서 가장 가까운 문서를 로드


    image 객체

    • document 객체의 프로퍼티
    • 문서와 함께 로드된 이미지에 대한 액세스 제공
    • images 배열은 문서 안에 지정되어 있는 각각의 <IMG>태그에 대한 엔트리가 들어있음
    • image 객체 유형을 사용하면 키워드와 생성자로 새로운 image 객체를 명시적으로 만들 수 있다. Image() 생성자는 웹페이지의 일부로서 처음에 나타나지 않는 이미지를 만들고 미리 로드할 때 사용한다. 이러한 image 객체는 브라우저의 캐시에 저장되면 이미 나타난 이미지를 대체할 때 사용
      * Image() 생성자를 사용하여 캐시된 이미지 만드는 예 cachedImage=new Image()
      cachedImage.src="myImage.gif"
      = > 첫번째 문장은 새로운 image 객체를 만들고 그것을 cachedImage 변수에 대입하고, 두번째 문장은 image 객체의 src프로퍼티를 myImage.gif 이미지 파일로 설정한다. 이 경우 myImage.gif는 브라우저 캐시로 로드된다. 그러면 로드된 이미지는 cachedImage 변수를 사용하여 참조 가능하다.

      image 객체의 프로퍼티
      프로퍼티 설 명
      border <:IMG> 태그의 BORDER 속성의 값
      complete 이미지가 완전히 로드되었는지 식별
      height <:IMG> 태그의 HEIGHT 속성의 값
      hspace <IMG> 태그의 HSPACE 속성의 값
      lowsrc <IMG> 태그의 LOWSRC 속성의 값
      name <IMG> 태그의 NAME 속성의 값
      prototype image 객체에 사용자 지정 프로퍼티를 추가할 때 사용
      src <IMG> 태그의 SRC 속성의 값
      vspace <IMG> 태그의 VSPACE 속성의 값
      width <IMG> 태그의 WIDTH 속성의 값


    area 객체

    • 이미지맵은 여러 가지 다른 영역으로 나누어져 있는 이미지로서 각각의 영역은 자체 URL과 관련되어 있다. 그리고 이러한 영역과 관련된 사용자 처리 방식으로 area 객체를 제공

    area 객체의 프로퍼티
    프로퍼티 설 명
    hash area 객체의 HREF 속성의 파일 오프셋 부분
    host area 객체의 HREF 속성의 호스트 이름 부분
    hostname area 객체의 HREF 속성의 host:port 부분
    href area 객체의 완전한 HREF 속성
    pathname area 객체의 HREF 속성의 경로명 부분
    port area 객체의 HREF 속성의 포트 부분
    protocol area 객체의 HREF 속성의 프로토콜 부분
    search area 객체의 HREF 속성의 쿼리 스트링 부분
    target area 객체의 TARGET 속성


    Array 객체

    • Array 객체를 사용하면 배열을 객체처럼 액세스 가능
    • Array 객체의 프로퍼티
      • length : 배열의 길이 식별
      • prototype : 모든 객체 유형이 지원하는 프로퍼티로 객체 유형에 대해 추가적인 프로퍼티 및 메소드 정의 가능
    • Array 객체의 메소드
      • toString() : 배열의 스트링 버전 리턴, 배열 요소는 컴마로 구분
      • join(separator) : 배열의 스트링 버전 리턴, 배열 요소는 seperator 스트링으로 구분, 분리자가 없으면 컴마로 구분
      • reverse() : 배열의 요소를 역순으로 바꿈
      • sort(comparisionFunction) : 비교 연산에 따라 배열의 요소 정렬. 비교 함수가 지정되면, 배열 요소는 사전순서로 정렬. 비교 연산이 지정되면 두개의 파라미터 p1,p2를 취하고, p1이 p2보다 작은 경우에는 음의 정수를 리턴하고, 같으면 0을 리턴하고, p1이 p2보다 크면 양의 정수 리턴


    Boolean 객체

    • Boolean 객체를 사용하면 부울값은 객체로서 액세스 가능
    • Boolean 객체는 생성자에 대한 인자로서 값을 식별하여 만들어짐 myBoolean=new Boolean(false)
      yourBoolean=new Boolean(true)
    • Boolean 객체의 프로퍼티
      • prototype : 모든 객체 유형이 지원하는 프로퍼티로 객체 유형에 대해 추가적인 프로퍼티 및 메소드 정의 가능
    • Boolean 객체의 메소드
      • toString() : 부울값에 해당하는 스트링 리턴
      • valueOf() : 객체의 값에 따라 true나 false로 리턴


    Date 객체

    Date 객체의 메소드
    메 소 드 설 명
    getDate()
    getUTCDate()
    setDate()
    setUTCDate()
    Date 객체의 날짜를 설정하거나 리턴
    getDay()
    getUTCDay()
    Date 객체의 한 주의 날짜를 설정하거나 리턴
    getHours()
    getUTCHours()
    setHours()
    setUTCHours()
    Date 객체의 시간를 설정하거나 리턴
    getMilliseconds()
    getUTCMilliseconds()
    setMilliseconds()
    setUTCMilliseconds()
    Date 객체의 밀리초 값을 설정하거나 리턴
    getMinutes()
    getUTCMinutes()
    setMinutes()
    setUTCMinutes()
    Date 객체의 분을 설정하거나 리턴
    getMonth()
    getUTCMonth()
    setMonth()
    setUTCMonth()
    Date 객체의 달을 설정하거나 리턴
    getSeconds()
    getUTCSeconds()
    setSeconds()
    setUTCSeconds()
    Date 객체의 초를 설정하거나 리턴
    getTime()
    getUTCTime()
    Date 객체의 시간을 설정하거나 리턴
    getTimeZoneOffset() Date 객체의 시간대 오프셋(분)을 리턴
    getYear()
    getFullYear()
    getUTCFullYear()
    setYear()
    setFullYear()
    setUTCFullYear()
    Date 객체의 연도를 리턴하거나 설정한다. 완전한 연도를 나타내는 방법으로 4자리 연도 값을 사용한다.
    toGMTString() 날짜를 Internet GMT(Greenwich Mean Time) 포맷의 스트링으로 변환
    toLocaleString() 날짜를 로케일(locale)포맷의 스트링으로 변환. 로케일 포맷이란 사용자가 위치해 있는 지형적 위치에서 일반적으로 사용하는 포맷 의미
    toString() Date 객체의 스트링 값을 리턴
    valueOf() 1970년 1월 1일 자정 이후의 밀리초 값 리턴
    toUTCString() UTC에서 시간을 나타내는 스트링 값을 리턴

    Date 생성자
    생 성 자 설 명
    Date() 현재 날짜와 시간으로 Date 인스턴스 만듬
    Date(dateString) dateString 파라미터에 지정되어 있는 날짜로, Date 인스턴스를 만든다. dateString의 포맷은 "월,일,연도,시:분:초"
    Date(milliseconds) 1970년 1월 1일 자정 이후 지정된 밀리초 값으로 Date 인스턴스를 만든다.
    Date(year,month,
    day,hours,minutes,
    seconds,milliseconds)
    년,월,일,시,분,초,밀리초 정수에 따라 지정된 날짜로 Date 인스턴스를 만든다. 연도와 월 파라미터는 제공되어야 하고 다른 나머지 파라미터가 포함되면 앞에 오는 모든 파라미터가 제공되어야 한다.


    Function 객체

    • 함수를 객체처럼 액세스 가능하고, 이 객체는 스크립트를 실행하는 동안에 함수를 동적으로 만들고 호출할 때 사용
    • Function 객체는 함수의 파라미터와 본문을 Function() 생성자에 제공하면 된다.
      variable=new Function("p1","p2", ... ,"pn","body")
    • Function 객체 프로퍼티
      • length : 함수에 대해 정의된 파라미터의 숫자 식별
      • prototype : 모든 객체 유형이 지원하는 프로퍼티로 객체 유형에 대해 추가적인 프로퍼티 및 메소드 정의 가능
      • arguments : 호출시 함수에 전달되는 인자를 가리키는 배열
      • caller : 특정 함수를 호출한 함수를 가리킴
    • Function 객체의 메소드
      • toString() : 함수의 스트링 형태 리턴
      • valueOf() : 함수 자체 리턴


    Global 객체

    • new Global() 을 통해서 명시적으로 만들거나, 참조할 수 없다. 대신 해당 프로퍼티와 메소드가 전역 변수와 함수로 직접 참조됨
    • Global 객체의 프로퍼티
      • Nan : 숫자가 아니라는 의미
      • Infinity : 양수 무한대 값 의미
    • Global 객체의 메소드
      • escape(string) : string을 새로운 스트링으로 변환
      • eval!(x) : 표현식 x의 값을 계산하고 리턴
      • inFinite(number) : number가 유한하면 true를 리턴하고, 무한하면 false를 리턴
      • inNaN(number) : number가 숫자가 아니면 true를 리턴하고, 숫자이면 false를 리턴
      • parseFloat(string) : string을 부동 소수 값으로 파싱
      • parseInt(string,radix) : string을 밑이 radix인 정수로 파싱
      • unescape(string) : escape()에 들어 있는 스트링을 원래의 값으로 되돌린다.


    Math 객체

    • 수학적 상수와 함수의 표준 라이브러리 제공
    • Math의 특수 인스턴스는 Math가 내장 객체이고 객체 유형이 아니기 때문에 만들어지지 않는다.

    Math 프로퍼티
    프로퍼티 설 명
    E Euler의 상수. 이것은 계산을 하는 어디에서나 발견할 수 있으며 자연대수의 기초
    LN2 2의 자연대수. 이것은 자연대수와 밑이 2인 대수 사이의 전환에 사용되는 간단한 상수
    LN10 10의 자연대수. LN2와 마찬가지로 대수 변환에 사용
    LOG2E 밑이 2인 E의 대수. 이것은 밑이 10인 대수를 밑이 E인 대수로 변환시 사용
    PI 원의 원주 대 지름의 비율
    SQRT1_2 1/2의 제곱근은 많은 삼각법 계산에서 사용
    SQRT2 2의 제곱근은 대수식에서 흔히 사용

    Math 메소드
    메 소 드 설 명
    abs(x) x의 절대값 리턴
    acos(x) x의 아크 코사인값 라디안으로 리턴
    asin(x) x의 아크 사인값 라디안으로 리턴
    atan(x) x의 아크 탄젠트 값을 라디안으로 리턴
    atan2(x,y) (x,y)에 해당하는 극좌표의 각도를 리턴
    ceil(x) x보다 크거나 작은 최소 정수값 리턴
    cos(x) x의 코사인 값 리턴
    exp(x) eX를 리턴
    floor(x) x보다 작거나 같은 최대 정수값 리턴
    log(x) x의 자연대수 리턴
    max(x,y) x, y 중 큰 값 리턴
    min(x,y) x, y 중 작은 값 리턴
    pow(x,y) xy를 리턴
    random() 0과 1사이의 임의의 숫자 리턴
    round(x) x의 가장 가까운 정수로 반올림되는 값 리턴
    sin(x) x의 사인값 리턴
    sqrt(x) x의 제곱근 리턴
    tan(x) x의 탄젠트 값 리턴


    Number 객체

    • Number 객체 유형을 사용하면 숫자를 객체로 다룰 수 있다.
    • Number 객체의 프로퍼티
      • MAX_VALUE : 숫자는 가능한 최대 수치값
      • MIN_VALUE : 숫자는 가능한 최소 수치값
      • NaN : 숫자가 아니다
      • NEGATIVE_INFINITY : 숫자가 음수 무한대 값
      • POSITIVE_INFINITY : 숫자가 양수 무한대 값
      • prototype : 모든 객체 유형이 지원
    • Number 객체의 메소드
      • toString(radix) : 밑이 radix인 숫자를 나타내는 스트링 리턴
      • valueOf() : Number 객체의 수치값 리턴


    Object 객체

    • Object 객체는 다른 모든 객체들이 파생되어 나가는 기반 객체로 이것의 프로퍼티와 메소드는 다른 객체 유형들에서 사용 가능
    • Object 객체의 프로퍼티
      • prototype : 모든 객체 유형이 지원
      • constructor : 객체 생성자의 이름 식별
    • Object 객체의 메소드
      • toString() : 객체를 스트링 표현으로 바꾸는 역할
      • valueOf() : 객체와 관련된 경우의 원시값(숫자,스트링,부울값)을 리턴하고, 그렇지 않은 경우에는 객체 자체를 리턴


    String 객체

    • 스트링을 객체로 액세스 가능
    • String 객체의 프로퍼티
      • length : 문자에서 스트링의 길이 알아내는 역할
      • prototype : 모든 객체 유형이 지원
    String 메소드
    메 소 드 설 명
    charAt(index) 메소드가 적용되는 스트링의 지정된 인덱스에 있는 문자로 구성된 스트링을 리턴
    charCodeAt(index) 지정된 인덱스의 문자의 Unicode 인코딩 리턴
    fromCharCode(codes) 문자 코드의 컴마로 구분된 시퀀스에서 스트링 만듬
    indexOf(pattern) 스트링안에 들어있는 pattern 파라미터가 지정한 첫 번째 스트링의 인덱스 리턴, 패턴이 스트링 안에 들어있지 않으면 -1 리턴
    indexOf(pattern,startIndex) startIndex가 지정한 위치에서 검색을 시작하는 것을 제외하면 indexOf(pattern) 메소드와 같다.
    lastIndexOf(pattern) 스트링에 들어 있는 pattern 파라미터가 지정한 마지막 스트링의 인덱스 리턴, 패턴이 스트링 안에 들어있지 않으면 -1 리턴
    lastIndexOf(pattern,startIndex) startIndex가 지정한 위치에서 검색을 시작하는 것을 제외하면 lastIndexOf(pattern)과 같다.
    splitSeparator() 하나의 스트링을 분리자를 기반으로 하여 서브스트링의 배열로 분리
    substring(startIndex) startIndex에서 시작하는 스트링의 서브스트링을 리턴
    substring(startIndex,endIndex) startIndex에서 시작하고, endIndex에서 끝나는 스트링의 서브스트링을 리턴
    toLowerCase() 소문자로 변환된 스트링의 복사본 리턴
    toString() 객체의 스트링 값을 리턴
    toUpperCase() 대문자로 변환된 스트링의 복사본 리턴
    valueOf() 객체의 스트링 값을 리턴
  • '공부 > JavaScript' 카테고리의 다른 글

    javascript 공백처리, 글자수체크  (0) 2011.11.25
    쿠키(cookie)  (0) 2011.06.29
    체크박스 전체해지  (0) 2011.06.13


    세션 생명주기 이벤트

     이정표  이벤트와 리스너 유형
     
    생명주기

         -세션 생성
         컨테이너가 세션을 생셩했을 떄 이시점까지 새션은 여전히 새것(new)
         으로 간주된다(왜냐하면, 클라이언트가 세션ID를 가진 요청을 아직
         보내지 않았기 떄문이다).
         -세션 소멸
         컨테이너가 세션을 무효화했을 때(세션이 타임아웃 되었거나 또는
         다른 애플리케이션에서 invalidate()메소드를 호출했을 경우)
     HttpSessionEvent

     HttpSessionListener
     
    속성

        -속성 추가
        세션의 setAttribute()를 호출했을때.
        -속성 제거
        세션의 removeAttribute()를 호출했을때.
        -속성 대체
        세션의 setAttribute()를 호출했을때. 동일 속성 이름이 이미 존재하는
        경우에.
     HttpSessionBindingEvent

     HttpSessionAttributeListener
     

     이동

        - 세션이 비활성화(passivate)되려고 할떄
        컨테이너가 세션을 다른VM으로 옮기려고 할 때. 세션이 옮겨지기 바로
        전에 호출되어, 세션이 가지고 있는 속성들도 옮길 준비를 함
        -세션이 활성화 될때
        컨테이너가 세션을 다른 VM으로 옮기고 난 다음. 세션의 getAttribut()
        를 호출하기 바로 직전에 호출되어 속성들이 리턴할 준비를 함.
     HttpSessionEvent

     HttpSessionActivationListener


    HttpSessionBindingListener

    위에 나와있는 이벤트는 세션의 일생중 중요한 순간들이다

    HttpSessionBindingListener는 세션이 아닌 세션 속성의 중요 순간들에 대하여 리스닝한다.

    속성이 세션에 추가될 떄 속성의 정보를 데이터베이스에서 읽어 온다든지,

    아니면 세션에서 제거될 떄 속성의 정보로 데이터베이스를 업데이트한다든지 할 떄 사용 한다.

    코드를 보면

    package com.example;

    import javax.servlet.http.*;

    public class Dog implements HttpSessionBindingListener {
    //Dog라는 속성 클래스는 HttpSessionBindingListener이기도 하다. Dog객체가 세션에 추가되거나 제거될 떄를 리스닝 하고있다.
            private String breed;

            public Dog(String breed){
                   this.breed=breed;
            }

            public String getBreed() {
                  return breed;
            }

             public void valueBound(HttpSessionBindingEvent event) { //"Bound"라는 말은 이 속성을 세션에 추가했다는걸 의미
             //세션에 추가 되었을 때 실행될 코드
             }

             public void valueUnbound(HttpSessionBindingEvent event){ //속성을 세션에서 제거했다는걸 의미
             //세션에서 제거되었을 떄 실행될 코드
             }
    }

    *세션 바인딩 리스너는 DD에서 설정하지 않는다.
    Dog와 같은 속성 클래스가 HttpSessionBindingListener를 구현하면, 컨테이너는 이 객체가 세션에 추가되거나 제거될떄
    관련 콜백 메소드(valueBound(), valueUnBound())를 호출한다. 이걸로 끝이다
    하지만 HttpSessionListenner, HttpSessionActivationListener는 DD에 등록해야한다
    왜냐하면 이들은 세션 안에 추가되는 개별 속성들이 아니라 세션 그 자체에 관련된 것이기 떄문이다.


    세션 이동

    클러스트링 환경 하에서, 컨테이너는 클라이언트의 요청을 몇몇의 JVM으로 분산하여 넘기는 로드밸런싱 환경을 구현한다

    그림으로 간단하게 보면




    세션 이동 및 직렬화

    컨테이너는 직렬화가 구현된 속성은 별다른 코딩을 하지않더라도 옮길수 있어야 한다.
    (속성에 있는 모든 인스턴스는 직렬화되거나 아니면 null이어야한다는 말이다)

    그렇다고 해서 컨테이너가 HttpSession 객체를 옮기기 위하여 꼭 직렬화를 요구하는것은 아니다.

    이게무슨말이냐하면 속성 클래스를 직렬화 하라는 뜻이다.

    직렬화가 되있지않았다면(전부다가 아니라도, 속성 인스턴스 변수중 하나라도 직렬화 되지 않았을 경우에도)

    속성 객체를 HttpSessionActivationListener 로 구현한수 활성화(activation)/비활성화(passivation) 콜백 메소드를 가지고 이동할수 있게하면 된다.

     

    *리스너종류와 메소드 가궁금하면 API를 찾아 보자

    '공부 > Sevlets&JSP' 카테고리의 다른 글

    JSP API 와 속성  (0) 2011.07.01
    JSP 기초  (0) 2011.07.01
    세션(sisson) 관리  (0) 2011.06.29
    RequestDispatcher  (0) 2011.06.29
    동기화  (0) 2011.06.29

    쿠키(cookie)

    공부/JavaScript2011. 6. 29. 17:58

    원래 쿠키는 세션을 지원하기 위하여 고안된 것이지만, 다른 목적으로 사용하여도 무방하다.

    서버와 클라이언트간에 교환하는 조그마한 데이터(이름/값의 String 쌍) 이다.

    서버가 클라이언트로 쿠키를 보내면, 클라이언트는 새로운 요청을 보낼떄 쿠키를 돌려보낸다.

    쿠키에 관한 것 중 재미있는 것은 사용자는 전혀 이 과정에 개입하지 않는다는 것이다.
    쿠키의 교환은 자동적으로 이루어진다( 클라이언트가 쿠키기능이 가능하게 설정되어 있다는 가정 하에)

    쿠키는 디폴트로 세션과 생존 범위가 같다. 클라이언트가 브라우저를 중지하면, 쿠키도 사라진다.
    이것이 "JSESSIONID"가 동작하는 방식이다. 그러나 브라우저를 중지하더라도 쿠키는 계속 유지하도록 할 수도 있다.

    서블릿 API로 쿠키 사용하기

    Http Request와 Response 에서 쿠키 관련 헤더 정보를 핸들링 할 수있다. 다음 3개의 클래스에 이들이 정의 되어 있다.



    Cookie 객체를 생성한다

     Cookie cookie =new Cookie("username", name);
    //Cookie 클래스 생성자는 "이름/값" 쌍을 인자로 받는다.

    쿠키가 클라이언트에 얼마나 오랬동안 살아 있을지 설정한다.

    cookie.setMaxAge(30*60);
    //setMaxAge()는 초단위로 설정한다. 30분 동안 클라이언트에 살아있어라는 의미이며,
    -1을 설정하면 쿠키는 파일 같은 곳으로 영구적으로 저장되지 않으며, 브라우저가 빠져나가는 대로 지우라는 의미이다.

    쿠키를 클라이언트로 보낸다.

    response.addCookie(cookie);

    클라이언트 Request에서 쿠키(들)를 읽어온다.

    Cookie[] cookies = request.getCookies();
    for(int i = 0 ; i <cookies.length ; i++){
            Cookie cookie = cookies[i];
            if ( cookie.getName().equels("username")){
                  String userName = cookie.getValue();
                  out.println("Hello" + userName);
                  break;
            }
    }
    //getCookie(String) 메소드는 존재하지 않는다
    Cookie에서 getCookies()만 호출 가능하다. 원하는 쿠키를 찾으려면 배열을 루프로 돌려야한다.

    '공부 > JavaScript' 카테고리의 다른 글

    javascript 공백처리, 글자수체크  (0) 2011.11.25
    자바스크립트 총정리  (0) 2011.06.30
    체크박스 전체해지  (0) 2011.06.13