벤치 프레스


40kg x 15

50kg x 12

70kg x 6

70kg x 5

60kg x 8

60kg x 7


인클라인 덤벨 프레스


15kg x 15

17.5kg x 9

15kg x 12

20kg x 6

17.5kg x 7


케이블 크로스 오버


15kg x 17

15kg x 15

20kg x 11

20kg x 9

15kg x 10


케이블 프레스 다운


20kg x 20

35kg x 15

45kg x 10

30kg x 10

20kg x 15


딥스머신


90kg x 12

70kg x 10

70kg x 9



저녁 : 마카롱 1개, 라떼 1잔


'생활 > 운동일지' 카테고리의 다른 글

2월 2째주 화요일 / 가슴&삼두  (0) 2019.02.12
2월 2주차 월요일/ 하체  (0) 2019.02.11

 java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig



Junit으로 테스트 케이스를 만들어 세션에 어떤 작업을 할 때, MockHttpSession 객체를 생성하게 되는데, 서블릿 버전 3.1 이하에서는 SessionCookieConfig 클래스를 찾지 못하는 오류가 발생한다.


서블릿 jar 파일을 3.1 버전으로 업데이트 해 주면 해결된다.


 

1
2
3
4
5
6
7
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
cs


인텔리제이에서 자바 기반의 프로젝트를 진행하다보면, 프로젝트에 분명 JDK 경로를 잡아주었는데도 불구하고,


다른 버전이 설정되어 있을 때가 있다.


나 같은 경우에는 JDK 1.8을 설정했음에도 불구하고, JDK 1.5를 계속 찾아서 API를 사용하기가 힘들었다.


그럴경우, 아래와 같이 설정 해 주면 된다.


1.제일 상단 바에 가서 FIle - > Project Structure -> Module -> (프로젝트 더블클릭) -> Sources -> Language level -> JDK 버전 설정




2. Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler ->  Target bytecode version -> 설정할 버전




백 하이바 스쿼트 5세트


40kg x 15

60kg x 12

90kg x 8

90kg x 7

110kg x 2




레그 프레스 5세트


140kg x 12

180kg x 12

220kg x 11

260kg x 12

140kg x 12




레그컬 4세트


40kg x 12

60kg x 10

60kg x 10

40kg x 12




힙 측면 운동하는 머신 (이름 뭐지?) 4세트


40kg x 12

80kg x 10

80kg x 10

60kg x 12





레그레이즈 3세트


25회 x 3




'생활 > 운동일지' 카테고리의 다른 글

2월 2째주 화요일 / 가슴&삼두  (0) 2019.02.12
2월 2주차 월요일/ 하체  (0) 2019.02.11

어플리케이션을 만들다 보면 중요한 정보를 사용해야 할 때가 있다.


그런데 이걸 소스내에 하드코딩해서 관리하기엔 아래와 같은 문제가 있다.



1. 런타임 중에 변경할 수 없다.


즉 정보가 하나라도 변경되면 서버를 껐다가 켜야한다.


2. 유지보수가 힘들다.


ENUM이나 상수로 정의해서 사용해도 되지만, 결국은 소스코드를 뒤져야 하며, 유지보수에 악영향을 미친다.


3.보안 처리가 힘들다


소스코드 자체는 암호화 하기가 힘들다. 파일로 따로 빼서 관리하면 IO 과정에서 암/복호화 할 수 있으므로 보안에 유리하다.




1
2
3
4
db.driverName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mydb
db.id=myid
db.pwd=mypwd
cs



JDBC 접속 정보를 관리하는 info.properties 라는 파일을 만들자.


Key = Value 로 작성하면 되고, 콤마를 안써도 개행을 하면 다른 정보라고 인식한다. 


이 파일을 배포하는 서버에서 관리하려면 특정 경로에 파일을 생성하고 이 경로를 상수로 관리하면 되고,


프로젝트 파일 밑에 놔두려면, WEB-INF 아래 classes 폴더를 생성해서 그 안에 넣어두면 된다.




불러올 때는, ClassLoader를 통해 WEB-INF classes 폴더 밑을 탐색할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static final String PROPERTIES_FILE = "info.properties";
private Properties props;
 
.....
 
 
props = new Properties();
        try {
            
            props.load(this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE));
        } catch (IOException e) {
            System.out.println("Properties File Load Fail!");
            e.printStackTrace();
        }
cs


classes 폴더 밑에 파일을 두고 이름을 주면 ClassLoader가 알아서 찾아온다.


만약 classes 폴더 밑에 말고 WEB-INF 하위의 다른 곳에 두고 싶다면 ServletContext로 접근해야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public String getDbName() {
 
        return props.getProperty("db.driverName");
    }
 
    public String getDbUrl() {
 
        return props.getProperty("db.url");
    }
 
    public String getDbId() {
 
        return props.getProperty("db.id");
    }
 
    public String getDbPwd() {
 
        return props.getProperty("db.pwd");
    }
cs

properties 파일에 있는 정보에 접근하려면 파일에 적어두었던 키 값으로 접근하면 된다.







SQL문 사용 시에 동적으로 계속 바뀌는 경우가 있다.

예를 들어 학생 테이블에서 검색하는 경우,

조건에 따라 학생의 번호만으로 찾을 수도 있고 혹은 이름으로 찾을 수도 있는데

이것을 정적으로 사용하면 같은 SQL문을 중복해서 사용해야 한다.

이럴때 SQL문을 문자열로 저장 해 놓고 자주 변하는 조건만 바꿔주면 재사용성도 높아지고 유지보수도 편해진다.





동적 SQL을 사용하는 방법은 원시동적 SQL을 사용하는 방식과 DBMS_SQL이란 시스템 패키지를 사용하는 방식이 있는데 SQL문을 문자열 형태로 만들어 실행한다는것은 같지만 구조와 사용법은 약간 다르다.




NDS (Native Dynamic SQL)




EXECUTE IMMEDIATE문


EXECUTE IMMEDIATE SQL문_문자열

[ INTO OUT변수, OUT변수 ... ]

[ USING 

[ IN | OUT | IN OUT ] 매개변수1, 

[ IN | OUT | IN OUT ] 매개변수2,

.... ];



1
2
3
BEGIN
      EXECUTE IMMEDIATE 'select employee_id, emp_name, job_id from employees where job_id = ''AD_ASST'' ';
END;
cs


Single quote를 두 개 사용한 이유는 문자열 안에서 또다른 문자열 (AD_ASST)를 구분하기 위해서이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DECLARE
  vn_emp_id employees.employee_id%TYPE;
  vs_emp_name employees.emp_name%TYPE;
  vs_job_id employees.job_id%TYPE;
  
BEGIN
  EXECUTE IMMEDIATE 'SELECT employee_id, emp_name, job_id
                    FROM employees WHERE job_id = ''AD_ASST'' '
                    INTO vn_emp_id, vs_emp_name, vs_job_id;
                    
  DBMS_OUTPUT.PUT_LINE(vn_emp_id);
  DBMS_OUTPUT.PUT_LINE(vs_emp_name);
  DBMS_OUTPUT.PUT_LINE(vs_job_id);
  
END;
cs


PL/SQL 프로시저가 성공적으로 완료되었습니다.


200

Jennifer Whalen

AD_ASST



일반적으로는 변수에 sql문을 선언하여 사용한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
DECLARE
  vn_emp_id employees.employee_id%TYPE;
  vs_emp_name employees.emp_name%TYPE;
  vs_job_id employees.job_id%TYPE;
  vs_sql VARCHAR2(1000);
 
  
BEGIN
  vs_sql := 'SELECT employee_id, emp_name, job_id FROM employees WHERE job_id = ''AD_ASST'' ';
 
 
  EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id;
                    
  DBMS_OUTPUT.PUT_LINE(vn_emp_id);
  DBMS_OUTPUT.PUT_LINE(vs_emp_name);
  DBMS_OUTPUT.PUT_LINE(vs_job_id);
  
END;
cs



바인드 변수의 사용




바인드 변수(Bind Valiable) : 쿼리문에서 조건절에 사용하는 상수를 변수에 대입하여 사용하는 것. 이때 이 변수를 바인드 변수라고 한다.


바인드 변수를 사용하는 이유는 동일한 SQL문이 여러번 실행되면 오라클은 메모리상 처리 결과를 캐싱해 놓고 계속 참조하며, 구문검사와 오류검사등을 생략하여 빠른 속도로 결과값을 가져올 수 있다.



그런데 만약 조건절에 있는 상수로 처리하고, 상수가 계속 변하게 된다면 오라클 옵티마이저는 이것을 SQL문 전체가 다르다고 판단하여, 쿼리 작업을 계속 새로 하게된다. 그러면 성능 저하가 발생하여 좋지 않다.


조건절에 있는 상수를 변수에 대입하여 사용하면, 변수의 값이 달라지더라도 옵티마이저가 SQL문 전체가 달라졌다고 인식하지는 않아서 앞에서 얘기했던 처리 절차를 단축시킬 수 있어 쿼리 속도가 빨라진다.


바인드 변수는 따로 변수를 선언하여 값을 할당한 이후에, 


: 변수명 


으로 조건절에 명시해 준다.


EXECUTE IMMEDIATE sql문자열 INTO 담을 변수1, 담을 변수2....

USING sql문자열에서 사용한 바인드변수1, 바인드변수2, ...... ; 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
DECLARE
  vn_emp_id employees.employee_id%TYPE;
  vs_emp_name employees.emp_name%TYPE;
  vs_job_id employees.job_id%TYPE;
  vs_sql VARCHAR2(1000);
  pd_job_id employees.job_id%TYPE := 'AD_ASST';    
BEGIN
  vs_sql := 'SELECT employee_id, emp_name, job_id FROM employees WHERE job_id= :pd_job_id ';
 
  EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id
  USING pd_job_id;
                    
  DBMS_OUTPUT.PUT_LINE(vn_emp_id);
  DBMS_OUTPUT.PUT_LINE(vs_emp_name);
  DBMS_OUTPUT.PUT_LINE(vs_job_id);
  
END;
cs



pd_job_id를 바인드 변수로 사용하였고 USING 절에 사용한 바인드 변수를 명시해 주었다.


중요한 것은 USING 절에는 반드시 SQL문장 안에 선언한 바인드 변수를 순서대로 명시해 주어야 한다는 것이고, 바인드 변수의 변수명과는 상관이 없다는 점이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
DECLARE
  vn_emp_id employees.employee_id%TYPE;
  vs_emp_name employees.emp_name%TYPE;
  vs_job_id employees.job_id%TYPE;
  
  vs_sql VARCHAR2(1000);
  
  pd_job_id employees.job_id%TYPE := 'SA_REP';
  pd_salary employees.salary%TYPE := 7000;
  pd_manager_id employees.manager_id%TYPE := 148;
BEGIN
  vs_sql := 'SELECT employee_id, emp_name, job_id FROM employees WHERE job_id = :hi AND salary < :hi AND manager_id = :hi ';
 
  EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id
  USING pd_job_id, pd_salary, pd_manager_id;
                    
  DBMS_OUTPUT.PUT_LINE(vn_emp_id);
  DBMS_OUTPUT.PUT_LINE(vs_emp_name);
  DBMS_OUTPUT.PUT_LINE(vs_job_id);
  
END;
cs



PL/SQL 프로시저가 성공적으로 완료되었습니다.


173

Sundita Kumar

SA_REP


SQL 문장 안에서 실제 변수명과는 다른 이름을 사용했음에도 컴파일이 잘 되는것을 볼 수 있다.

실제 USING절에 선언한 변수 순서대로 매핑되는것에 유의하자.


익명블록이나 함수, 프로시저를 호출할때 전달하는 매개변수를 동적SQL로 호출할 수도 있는데, 

이 때는 반드시 변수타입과 개수, 변수명도 맞추어 주어야 한다.

또한 USING 절에 매개변수의 범위인 IN, OUT, INOUT 등도 함께 선언해야 한다.


1
2
3
4
5
6
7
  vs_sql := 'BEGIN 
  test_proc1(:pd_job_id, :pd_salary, :pd_manager_id); 
  END;';
 
  EXECUTE IMMEDIATE vs_sql INTO vn_emp_id, vs_emp_name, vs_job_id
  USING IN pd_job_id, OUT pd_salary, IN OUT pd_manager_id;
 
cs



DDL문이나 ALTER SESSION에 관한 SQL문도 이렇게 문자열에 저장하여 실행시키면 사용이 가능하다. 




OPEN FOR문



동적 SQL에서는 한 개 이상의 로우를 결과 집합으로 반환하는 SELECT문을 OPEN FOR문과 커서 변수를 사용해 결과 값을 받아올 수 있다.



OPEN 커서변수 FOR 동적SQL문

USING 바인드변수1, 바인드변수2....;




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DECLARE
    TYPE cur_query_employees IS REF CURSOR;
    cur_employees cur_query_employees;
    row_emp employees%ROWTYPE;
    vs_sql VARCHAR2(1000);
    vn_count NUMBER := 1;
BEGIN
    vs_sql := 'SELECT * FROM employees';
    OPEN cur_employees FOR vs_sql;
  LOOP 
      FETCH cur_employees INTO row_emp;
        EXIT WHEN cur_employees%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(vn_count || ' - ' || row_emp.emp_name);
        vn_count := vn_count + 1;
      END LOOP;
    
    CLOSE cur_employees;
    
  END;
cs

1 - Donald OConnell

2 - Douglas Grant

3 - Jennifer Whalen

4 - Michael Hartstein

5 - Pat Fay

6 - Susan Mavris

.............

102 - Sarah Bell

103 - Britney Everett

104 - Samuel McCain

105 - Vance Jones

106 - Alana Walsh

107 - Kevin Feeney



OPEN FOR문을 통해 받아온 직원들의 이름이다. 


이번에는 바인드 변수를 사용해서 라인번호 30번과 50번 사이의 직원들의 이름을 출력해본다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DECLARE
    TYPE cur_query_employees IS REF CURSOR;
    cur_employees cur_query_employees;
    row_emp employees%ROWTYPE;
    vs_sql VARCHAR2(1000);
    vn_count NUMBER := 1;
    
    vn_min NUMBER := 30;
    vn_max NUMBER := 50;
BEGIN
 
    vs_sql := 'select employee_id, emp_name, email, phone_number,hire_date, salary, 
    manager_id, commission_pct, retire_date, department_id, 
    job_id, create_date, update_date from 
        (select rownum as cnt, employees.* from employees where rownum < :vn_max) insql 
                where insql.cnt > :vn_min';
        
    OPEN cur_employees FOR vs_sql USING vn_max, vn_min;
    vn_count := vn_min + 1;
  LOOP 
      FETCH cur_employees INTO row_emp;
        EXIT WHEN cur_employees%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(vn_count || ' - ' || row_emp.emp_name);
        vn_count := vn_count + 1;
      END LOOP;
    
    CLOSE cur_employees;
    
  END;
cs


31 - Adam Fripp

32 - Payam Kaufling

33 - Shanta Vollman


......


47 - Renske Ladwig

48 - Stephen Stiles

49 - John Seo



성공적으로 출력이 됨을 볼 수 있다. 




BULK COLLECT INTO




다중 로우를 처리할 때, 커서나 레코드 변수 혹은 반복문을 사용하는 방식은 데이터의 양이 늘어나면 늘어날수록 시간도 많이 걸리고 성능면에서도 좋지 않다.


BULK COLLECT INTO절은 일일이 한 로우씩 읽는 것이 아니라 집합적으로 데이터를 처리할 수 있도록 해 준다.



성능 확인을 위해 커서 변수와 BULK COLLECT를 통한 출력 속도 차이를 벤치마크 한다.


정확한 비교를 위해 새로운 새션 생성 후 테스트, 하나의 테스트가 끝나면 다시 새로운 세션을 생성하여 테스트 하였다.


CUSTOMERS 테이블에는 55500건의 데이터를 가지고 있다.


1. 커서를 사용한 방법.



1
2
3
4
5
6
7
8
9
10
11
12
DECLARE
  TYPE cust_cur IS REF CURSOR;
  var_cust_cur cust_cur;
  cust_row customers%rowtype;
BEGIN
  OPEN var_cust_cur FOR SELECT * FROM CUSTOMERS;
  LOOP
  FETCH var_cust_cur INTO cust_row;
  EXIT WHEN var_cust_cur%NOTFOUND;
  DBMS_OUTPUT.PUT_LINE(cust_row.cust_name);
  END LOOP;
END;
cs



1.8초에서 2초 사이의 시간이 측정되었다.



2. BULK COLLECT 방식이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
DECLARE
    TYPE nt_cust is table of customers%rowtype; 
    va_nt_cust nt_cust;
BEGIN
    SELECT *
      BULK COLLECT INTO va_nt_cust
      FROM customers;
   
      FOR i in 1.. va_nt_cust.COUNT
        LOOP
        DBMS_OUTPUT.PUT_LINE(va_nt_cust(i).cust_name);
        END LOOP;
    
END;
cs




소요 시간이 절반 이하로 줄었다. 엄청난 개선이다.



동적 sql문을 사용한 BULK COLLECT INTO 구문이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  DECLARE
      TYPE nt_cust is table of customers%rowtype; 
      va_nt_cust nt_cust;
      va_sql varchar2(1000);
  BEGIN
     
     va_sql := ' SELECT * FROM customers';
        
      EXECUTE IMMEDIATE va_sql BULK COLLECT INTO va_nt_cust;
     
        FOR i in 1.. va_nt_cust.COUNT
          LOOP
          DBMS_OUTPUT.PUT_LINE(va_nt_cust(i).cust_name);
          END LOOP;
      
  END;
cs


EXECUTE 구문 뒤에 BULK COLLECT를 선언하고 데이터를 저장할 컬렉션 변수를 걸어준다.


만약 바인드변수를 작성한 경우에는 INTO 뒤에 USING 절을 통해 사용한 바인드 변수를 반드시 명시해 주어야 한다.






패키지 (Package) : 논리적 연관성이 있는 PL/SQL 타입, 변수, 상수, 서브 프로그램, 커서, 예외 등의 항목을 묶어 놓은 객체.

컴파일 과정을 거쳐 DB에 저장되고, 다른 프로그램 (타 패키지, 프로시저, 외부 프로그램 등)에서 패키지의 항목을 참조, 공유, 실행할 수 있다.


PL/SQL의 패키지는 자바의 Class 개념과 유사한데, 논리적 연관성이 있는 프로시저와 함수, 변수와 상수등을 정의한 부분에서 그러하다. 다만 자바에서 지원하는 상속의 개념은 없다.


패키지의 장점을 정리하면 아래와 같다.


1. 모듈화 기능

2. 프로그램 설계의 용이성

3. 캡슐화

4. 성능 최적화 (메모리에 패키지 전체가 올라가 있으므로 안에 있는 부 프로그램 호출시 빠른 처리 가능)




패키지 구조




PL/SQL은 선언부와 본문이 나누어지며, 선언부에는 사용할 상수와 메소드, 함수와 프로시저의 시그니처만을 작성하고 구체적인 구현부는 본문에 작성한다는 것을 유의하자.


또한, 선언부는 다른 사용자들이 접근이 가능하나, 본문에는 반드시 패키지 소유자만 접근을 할 수 있다는 점을 알아두자!


선언부(Specification) : 패키지에서 사용할 사용자 정의 타입, 변수, 상수, 예외, 서브 프로그램의 골격을 선언.

함수와 프로시저는 시그니처(Signature)만 존재할 뿐, 안에 내용은 작성하지 않는다.

해당 패키지 소유자 외의 다른 사용자는 선언부의 내용만 볼 수 있지만, 사용하려는 함수나 프로시저에 대해 필요한 모든 정보(함수와 프로시저의 시그니처)를 참조할 수 있으므로 사용하는데는 전혀 문제가 없다.



CREATE OR REPLACE PACKAGE 패키지명 IS

TYPE_구문;

상수명 CONSTANT 상수_타입;

예외명 EXCEPTION;

변수명 변수_타입;

커서 구문;


FUNCTION 함수명 (매개변수 IN 타입, 매개변수 IN 타입 ... )

RETURN 반환 타입;



PROCEDURE 프로시저명 (매개변수 [ IN, OUT, INOUT ] 타입, 매개변수 [ IN, OUT, INOUT ] 타입 ... );


...


END 패키지명




패키지 본문(Body) : 여기서 유의할 것은 패키지 본문에서 선언한 상수나 변수는 외부에서 참조할 수 없다는 점이다. 패키지 본문의 내용은 패키지 작성자만 접근해 수정이 가능하며, 다른 사용자는 전혀 볼수가 없다.




CREATE OR REPLACE PACKAGE BODY 패키지명 IS

상수명 CONSTANT 상수_타입;

변수명 변수_타입;

커서 정의 구문;


FUNCTION 함수명 (매개변수 IN 매개변수 타입, 매개변수 IN 매개변수 타입, .... )

RETURN 반환타입



IS 

...

BEGIN 

...

END 함수명;


PROCEDURE 프로시저명 (매개변수 [ IN, OUT, INOUT ] 매개변수 타입, 매개변수 [ IN, OUT, INOUT ] 매개변수 타입,  ....)

IS

...

BEGIN

...

END 프로시저명;

...

END 패키지명;



패키지를 사용할 때는,


패키지명.서브프로그램명


패키지명.변수명


패키지명.상수명


으로 사용한다.





패키지에서 선언한 변수(+상수)의 특징




1. 패키지 선언부에 선언한 변수는 외부에서 접근하고 수정할 수 있다. 이를 공용항목 (Public Item) 이라고 한다.

2. 패키지에서 선언한 변수는 그 값이 세션이 살아있는 동안 유지된다. 블록의 종료와 함께 소멸하는것이 아니다.

3. 패키지 본문에 선언한 변수나 상수는 외부에서 접근할 수 없다. 이를 내부(전용) 항목 (Private Item) 이라고 한다. 그러나, 직접 참조를 못할 뿐이지 서브 프로그램을 통해 간접적으로 참조하거나 값도 변경할 수 있다.



패키지 내에서의 커서의 사용




패키지 내에서 선언한 커서는 세션이 살아있는 동안 유지된다. 변수는 값이 유지되지만 커서는 그 상태까지 유지가 된다.


패키지 내부에서 사용되는 형태


1. 패키지 선언부에 커서 전체를 선언하는 형태

선언부에 커서 전체를 선언하면 공용이 되어 패키지명.커서명 으로 접근이 가능하다.


2. 쿼리를 제외한 커서 헤더 부분만 선언하는 형태

커서 헤더만 선언부에 명시하면, 해당 커서의 쿼리는 본문에서 작성할 수 있고 구현부인 쿼리를 외부에 숨길 수 있다.


헤더부분만 선언할 때는 커서가 반환, 패치하는 데이터를 가리키는 RETURN 절을 명시해야 한다.

구현부의 결과로 반환되는 컬럼 타입을 RETURN절에 함꼐 적어주어야 하는데, %ROWTYPE으로 명시할 수도 있고 사용자 정의 레코드 타입을 명시하는 것이 있다. 


패키지에서 커서를 사용할 때 주의점은, LOOP나 WHILE문을 사용시 열기 - 패치 - 닫기 과정을 직접 명시해 줘야 하는데 만약 닫기 과정을 생략하면 같은 세션에서 재사용이 불가하다. 




기타 특징




PRAGMA SERIALLY_REUSABLE 옵션 : 패키지 선언부와 본문에 명시하면, 해당 패키지 데이터는 호출이 끝나면 다시 초기화 된다. 같은 세션에있더라도 값을 공유하지 않음. 굳이 세션별로 데이터 값을 공유할 필요가 없는 경우에 사용하거나, 과다한 세션으로 패키지 데이터가 저장되는 UGA(User Global Area)의 메모리 공간 낭비를 초래할 때 사용한다.


오버로딩 (Overloading) : 동일한 이름이지만 매개변수 타입이나 개수가 다르면 함수를 여러 개 정의해 만들어 사용할 수 있는 특징. 함수와 프로시저 모두 오버로딩이 가능하다.

The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

처음 서블릿 프로젝트를 만들었을 때, 이라는 에러가 뜨는 경우가 있다.

말 그대로 현재 상속받는 서블릿 코드를 지금 설정해놓은 Build Path에서 못 찾았다는 뜻이다.

이럴 때는 서블릿을 구동 시킬 수 있는 환경을 설정해 주면 해결된다.

만약 톰캣을 안깔았으면 먼저 톰캣을 설치하고 환경설정 까지 끝내주자.

  1. Project 파일의 제일 상단에서 우클릭 -> Build Path -> Configure Build Path..

  2. Add Library.. 클릭

  1. Server Runtime 클릭

  1. class path에 잡혀있는 서버 목록이 뜬다. 해당 환경을 선택하고 Finish하면 된다.

+ Recent posts