레이블이 ORACLE DB BUFFER인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ORACLE DB BUFFER인 게시물을 표시합니다. 모든 게시물 표시

2013년 10월 12일 토요일

스프링3.2,하이버네이트4.2.3 [Spring3.x, Hibernate4연동하기] 1. 하이버네이트 다운로드

[Spring3.x, Hibernate4연동하기] 1. 하이버네이트 다운로드 www.hibernate.org (hibernate-4.2.3.Final.zip 사용) 

[Spring3.x, Hibernate4연동하기]
1. 하이버네이트 다운로드
 다운로드
 www.hibernate.org (hibernate-4.2.3.Final.zip 사용)
 lib : 하이버네이트를 실행 시 필요한 JAR 파일
 project : 각종 소스 코드
 documentation : 문서들
 하이버네이트를 실행하기 위해서는 hibernate4.2.3.jar 파일 뿐 아니라 lib 폴더의 각종 jar 파일이 필요하다.
 물론 이클립스 하이버네이트 플러그인을 설치해도 된다. 현재 Eclipse INDIGO 까지 나와 있다.

2. 준비
 이클립스 ? Spring Project
hibernate4 및 spring 관련 라이브러리 추가
(하이버네이트4 의 경우 스프링 3,1 이상이 필요)
주) 스프링의 Template Project에서 hhibernate Template을 이용하여 하이버네이트 APP 작성가능하나 라이브러리 버전이 맞지 않아 hibernate4 예제와 연동 어려움
    

예제 테이블 작성
  create table myemp (
      empno number ,
      ename varchar2(10)
  )

 
 

3. MyEmp.java
package edu.onj.hibernate;
public class MyEmp {
private int empno;
private String ename;
 public MyEmp() {}
 public MyEmp(int empno, String ename) {
  this.empno = empno;    this.ename = ename;
 }
 public int getEmpno() { return empno;  }
 public void setEmpno(int empno) {this.empno = empno;}
 public String getEname() {
  return ename;
 }
 public void setEname(String ename) {
  this.ename = ename;
 }
}
 
 
4. MyempDao.java

package edu.onj.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional(propagation=Propagation.REQUIRED)
public class MyEmpDao {
private SessionFactory sessionFactory;
private Session session;
public MyEmpDao() {}
//constructor injection(생성자 주입)
@Autowired
public MyEmpDao(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getSession() {
return sessionFactory.getCurrentSession();
}
public void insertMyEmp(MyEmp myemp) {
getSession().save(myemp);
}
public void deleteMyEmp(int empno) {
getSession().delete(getMyEmpByEmpno(empno));
}
public MyEmp getMyEmpByEmpno(int empno) {
return (MyEmp)getSession().get(MyEmp.class, empno);
}
public void saveMyEmp(MyEmp myemp) {
getSession().update(myemp);
}
}
 
5. myemp.hbm.xml
<?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
    <hibernate-mapping>
    <class    name="edu.onj.hibernate.MyEmp"    table="MyEmp"    lazy="false">
        <id name="empno"  type="java.lang.Integer"   column="empno"  />
        <property  name="ename" type="java.lang.String"  column="ENAME" length="10"/>
    </class>
    </hibernate-mapping>
 
6. spring-hibernate.xml
 
<?xml version="1.0" encoding="UTF-8"?>
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation=
        "http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx.xsd
         http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util.xsd" >

<!-- Annotation 쓰기 위해서 -->
      <context:annotation-config />
      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
        <property name="url"><value>jdbc:oracle:thin:@localhost:1521:onj</value></property>
        <property name="username"><value>scott</value></property>
        <property name="password"><value>tiger</value></property>
      </bean>
      <!-- Hibernate Session Factory 설정 -->
      <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource"><ref bean="dataSource"/></property>
        <property name="mappingResources">
          <list>
            <value>myemp.hbm.xml</value>
          </list>
        </property>
        <property name="hibernateProperties">
          <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
          </props>
        </property>
      </bean>
      <!-- 트랜잭션 -->
      <tx:annotation-driven transaction-manager="transactionManager" />
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
          <property name="sessionFactory" ref="sessionFactory" />
      </bean>
      <!-- MyEmpDAO autowiring  -->
      <bean id="myEmpDao" class="edu.onj.hibernate.MyEmpDao"> </bean>
   </beans>
  
  
7.    SpringHibernateExam.java

public class SpringHibernateExam {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-hibernate.xml");
MyEmpDao myEmpDao = (MyEmpDao)ctx.getBean("myEmpDao");
try {
MyEmp myemp1 = new MyEmp(1, "1길동");
MyEmp myemp2 = new MyEmp(2, "2길동");
MyEmp myemp3 = new MyEmp(3, "3길동");
myEmpDao.insertMyEmp(myemp1);
myEmpDao.insertMyEmp(myemp2);
myEmpDao.deleteMyEmp(1);
myEmpDao.insertMyEmp(myemp3);
MyEmp emp1 = (MyEmp)myEmpDao.getMyEmpByEmpno(3);
System.out.println(emp1.getEmpno() + "::" + emp1.getEname());
myemp2.setEname("2가아니고4");
myEmpDao.saveMyEmp(myemp2);
MyEmp emp2 = (MyEmp)myEmpDao.getMyEmpByEmpno(2);
System.out.println(emp2.getEmpno() + "::" + emp2.getEname());
}
catch (HibernateException e)
        {             e.printStackTrace();         }
        finally        {                }
}
}
 
8. 결과
/*
SQL> select * from myemp;
EMPNO ENAME
---------- ----------
    2 2가아니고4
    3 3길동
*/

  


오라클자바커뮤니티에서 설립한 개발자교육6년차 오엔제이프로그래밍 실무교육센터(오라클SQL,튜닝,힌트,자바프레임워크,안드로이드,아이폰,닷넷 실무개발강의)  

[개강확정강좌]오라클자바커뮤니티에서 운영하는 개발자 전문교육 ,개인80%환급(www.onjprogramming.co.kr) 




2013년 8월 8일 목요일

[ORACLEJAVA커뮤니티,ORACLEJAVANEW.KR]사용자가 로그인 했는지를 확인하는 커스텀태그(cart.jsp에서 사용), 자바교육

사용자가 로그인 했는지를 확인하는 커스텀태그(cart.jsp에서 사용) 예제입니다. 참고하세요~~~~~


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  




 이번에는 장바구니와는 별개 이지만 cart.jsp에서 사용되었던... 사용자가 로그인을 했는지를 확인하는 사용자 정의 태그에 대한 소개 입니다.


cart.jsp의 상단에서 사용되었던 다음부분이죠^^..

음 ...

refer라는 속성은 로그인을 한 후 다시 돌아올 URL을 기술한겁니다.

<%@ taglib uri="/WEB-INF/login_tld/app.tld" prefix="loginChk" %>

<!-------------------------------------------------------->
<!-- 로그인이 되어 있는지 확인 (로그인 해야 볼수 있는 페이) -->
<!-------------------------------------------------------->
<loginChk:IsLogin refer="/yfarm/goods/cart.jsp"/>


1. taglib을 위한 tld 파일(app.tld)

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
  "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>Application Tag Library</shortname>
  <uri>http://jakarta.apache.org/taglibs/struts-example-1.0</uri>
  <info>
    Example Application.
  </info>
  <tag>
    <name>IsLogin</name>
    <tagclass>login.IsLogin</tagclass>
    <bodycontent>empty</bodycontent>
    <info>
          로그인 체크를 위한 커스텀 태그 용 TLD 파일
    </info>
    <attribute>
      <name>name</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
      <name>page</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>     
    </attribute>
    <attribute>
      <name>refer</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>     
    </attribute>
  </tag>
</taglib>



2. 다음은 로그인을 했는지를 검사하는 IsLogin.java 입니다.

package login;

import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import yfarm.Constants;


public final class IsLogin extends TagSupport {
        private String name = yfarm.Constants.USER_KEY;
        private String page = "/index.jsp";
        private String refer = null;
       
        public String getRefer() {
            return refer;
        }
       
        public void setRefer(String refer) {
            this.refer = refer;
        }
       
        public String getName() {
                return (this.name);
        } 

        public void setName(String name) {
                this.name = name;
        }

        public String getPage() {
                return (this.page);
        }

        public void setPage(String page) {
                this.page = page;
        }

        public int doStartTag() throws JspException {
                return (SKIP_BODY);
        }

        public int doEndTag() throws JspException {
            // Is there a valid user logged on?
            boolean isLogin = false;
            HttpSession session = pageContext.getSession();
            if ((session != null) && (session.getAttribute(name) != null)) {
                isLogin = true;           
            }
 

            // Forward control based on the results
            if (isLogin)
                return (EVAL_PAGE);  //JSP 페이지의 다음을 수행
            else {
                try {
                    pageContext.getOut().println("<script>");
                    pageContext.getOut().println("alert('로그인을 하셔야 합니다.');");
                    pageContext.getOut().println("location.href='/yfarm/main/login.jsp?uri=" + refer + "'");
                    pageContext.getOut().println("</script>");
                   
                    session.invalidate();
                   
                    //pageContext.forward(page);
                } catch (Exception e) {
                    throw new JspException(e.toString());
                }
                return (SKIP_PAGE);  //JSP 페이지의 다음을 스킵
            }
        }

        /**
        * Release any acquired resources.
        */
        public void release() {
            super.release();
            this.name = Constants.USER_KEY;
            this.page = "/index.jsp";
        }
}

2013년 8월 6일 화요일

[자바교육,오라클자바커뮤니티]struts1 struts-config.xml 설정에 관해

struts-config.xml 설정에 관해 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  


org.apache.struts.config package는 struts 1.1에서 추가 되었으며 자바 빈을 이용하여 실행 시 XML 설정 파일의 설정 내용을 자바 빈의 인스턴스를 이용하여 담아두는 역할을 합니다.

아래는 org.apache.struts.config에 대한 클래스 다이어그램 입니다.

 


설정 파일(struts-config.xml)의 검증과 파싱 작업이 마무리 되면 메모리에 올라와 있는 설정 정보를 빈즈 인스턴스를 이용하여 담아 둡니다.

위 클래스 다이어그램에서 ConfigResultSet 클래스는 다른 클래스와 다른 작업을 하는데 주로 struts 설정 파일을 해석 하는데 필요한 규칙을 포함하고 있는데 그 역할은 값을 설정하기 위해 필요한 빈의 인스턴스를 생성 하는 것 입니다.


-------------------------------
Struts-Config.xml 설정
-------------------------------

설정을 위한 DTD

<!ELEMENT struts-config (data-source?, form-beans?, global-exceptions?, global-forwards?, action-mappings?, controller?, message-resources*, plug-in*)

Struts-config.xml 파일에 설정시 위에서 정의한 순서는 지켜져야 합니다.

1.        data-source 요소

데이터 소스에 대한 설정을 하는 곳이며 대부분의 벤더들이 데이터 소스 객체의 구현을 제공 하는데 자바에서는 javax.sql.DataSource 인터페이스를 제공 하며 벤더들이 제공하는 구현 부에서 이 인터페이스를 구현해 주어야 합니다.

DTD정의

<!ELEMENT data-sources (data-source*)>
<!ELEMENT data-source (set-property*)>

예)
<data-sources>
        <!-- configuration for commons BasicDataSource -->
        <data-source key="mysql" type="org.apache.commons.dbcp.BasicDataSource">
                                <set-property property="driverClassName" value="com.mysql.jdbc.Driver" />
                                <set-property property="url" value="jdbc:mysql://localhost/test" />
                <set-property property="username" value="root" />
                <set-property property="password" value="pw" />
                <set-property property="maxActive" value="10" />
                <set-property property="maxWait" value="5000" />
                <set-property property="defaultAutoCommit" value="true" />
                                <set-property property="defaultReadOnly" value="false" />
                <set-property property="maxIdle" value="10000" />
        </data-source>
        <data-source key="oracle" type="org.apache.commons.dbcp.BasicDataSource">
                <set-property property="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
                <set-property property="username" value="scott" />
                <set-property property="password" value="tiger" />
                <set-property property="url" value="jdbc:oracle:thin:@localhost:1521:WINK" />
                <set-property property="maxActive" value="50" />
                <set-property property="maxIdle" value="10000" />
                <set-property property="maxWait" value="100" />
                <set-property property="defaultAutoCommit" value="true" />
        </data-source>
</data-sources>

속성으로 다음과 같은 것들이 있습니다.

key : 데이터 소스가 저장 될 서블릿 컨텍스트 속성, 선택적 이며 기본값은 Action.DATA_SOURCE_KEY 입니다.

type : 데이터 소스 구현체 클래스의 전체 클래스 이름, 반드시 javax.sql.DataSource 클래스를 구현해야 합니다.

2.        form-bean 요소

form-bean 요소는 여러 개의 ActionForm 클래스를 설정 할 수 있게 합니다. Form-beans 요소에서 form-bean 요소를 사용할 수도 있고 안 할 수도 있습니다. 각각의 form-bean 요소 역시 자식 요소를 포함 합니다.

DTD 정의

<!ELEMENT form-bean (icon?, display_name?, description?, set-property*, form-property*)>

가질 수 있는 속성은 다음과 같습니다…

className : 기본값은 FormBeanConfig이며 이 클래스를 사용하지 않는다면 지정한 클래스는 반드시 FormBeanConfig를 상속 해야 합니다.

dynamic : type속성 값이 org.apache.struts.DynaActionForm 클래스나 그 하위클래스라면 이 속성값을 true라고 설정하며 그렇지 않은 경우엔 false이다. 기본값은 false

name : 이 빈의 유일한 식별자

type : ActionForm 클래스를 상속하는 자바 클래스의 전체 이름, 실제 폼빈 역할을 하는 클래스의 이름을 패키지 명까지 포함해서 기술 합니다. 만약 이 값을 org.apache.struts.action.DynaActionForm으로 지정하면 스트럿츠가 DynaActionForm 클래스의 인스턴스를 동적으로 생성 합니다. 속성값은 반드시 지정해야 합니다.

<form-beans>
        <form-bean name="loginForm" type="login2.LoginForm">                 
            <form-property name="pwd" type="java.lang.String" />
            <form-property name="id" type="java.lang.String" />           
        </form-bean>           
    </form-beans>


3.        global-exceptions 요소

예외처리에 관한 설정을 하며 global-exceptions에는 exception 요소가 0개 이상 나타날 수 있습니다.

<!ELEMENT global-exceptions (exception*)>

exception 요소는 action 요소에도 정의가 가능한데 exception 요소가 global-exceptons와 action 요소에 동시에 정의되어 있다면 action에 선언된 것이 우선권을 가집니다.

exception 요소는 클라이언트의 요청을 처리하는 동안 발생하는 자바의 예외상황과 해당 예외를 처리하는 org.apache.struts.action.ExceptionHandler 클래스의 인스턴스를 매핑하는 역할을 합니다.

exception 요소의 DTD는 다음과 같습니다.

<!ELEMENT exception (icon?, display-name?, description?, set-property*)

Exception 요소의 속성은 다음과 같습니다.

className : 예외정보를 가지게 되는 설정 빈의 구현 클래스, 지정한 클래스는 ora.apache.struts.config.ExceptionConfig의 하위 클래스여야 하며 기본값은 ExceptionConfig 클래스 입니다.

handler : 예외 처리를 담당할 예외 처리 클래스의 전체 이름. 값을 지정하지 않으면 org.apache.struts.action.ExceptionHandler 클래스 입니다. 만약 다른 클래스를 지정한다면 ExceptionHandler의 하위클래스 이여야 합니다.

key : 하위 애플리케이션의 리소스 번들에 지정된 키 값이며 ActionError 클래스의 인스턴스에서 이 속성의 값을 사용 합니다.

path : 예외가 발생 시 전송해야 할 리소스의 상대 경로, 만약 값을 지정하지 않으면 action mapping에서 지정하는 input 속성의 값을 사용 합니다.

scope : ActionError 클래스의 인스턴스를 저장 할 스코프, “request” 또는 “session” 이여야 합니다. 기본값은 “request” 입니다.

type : 예외 처리 클래스의 전체 이름

<global-exceptions>
        <exception
                key = “global.error.invalidlogin”
                path = “/login/login.jsp”
                scope = “request”
                type = “login2.exception.InvalidLoginException”
        />
</global-exceptions>


4.        global-forward 요소

모든 Action은 View화면으로 포워드 되거나 리다이렉트 되는 방법으로 실행 됩니다. 뷰의 역할은 JSP가 할 수도 있고 HTML이 할 수도 있습니다. Struts 에서는 뷰 역할을 하는 자원을 직접 참조하는 대신 주로 어떤 이름을 사용 합니다.

global-forwards에서는 0개 이상의 forward요소를 가집니다.

<!ELEMENT global-forwards (forward*)>

forward 요소 역시 몇 개의 자식 요소를 가집니다. forward 요소는 논리적인 이름을 Web Application의 URI,의 상대 경로에 mapping 합니다. 이를 통해 애플리케이션은 논리적인 이름을 통해 포워드 또는 리다이렉트를 수행 합니다.  이러한 방법을 통해 뷰로부터 컨트롤러와 모델을 분리 할 수 있습니다.

<!ELEMENT forward(icon?, display-name?, description, set-property*)>

다음은 forward요소의 속성 입니다.

className : 포워드 설정 값을 포함하게 되는 자바 빈을 구현한 클래스, 기본값은 ForwardConfig 입니다. Optional 값

contextRelative : true로 지정 할 경우 path 속성에 지정된 리소스를 컨텍스트 상대 경로로 인식 합니다, 기본값은 false

name : 애플리케이션에서 이 포워드를 참조하기 위한 유일한 값, 반드시 값을 지정 해야 합니다.

path : 포워드 되거나 redirect 되어야 하는 애플리케이션의 상대 경로(contextRalative가 false인 경우) 또는 컨텍스트의 상대 경로의 URI를 지정,  반드시 “/”로 시작해야 합니다.

<global-forwards>
        <forward name="success" path="/main.jsp"  redirect=”true”/>
        <forward name="logoff" path="/logoff.do" />
        <forward name="login" path="/login.jsp" />
    </global-forwards>

5.        action-mapping 요소

action-mappings 요소는 action 요소를 0개 이상 포함할 수 있습니다.

<!ELEMENT action-mappings(action*)>

Action 요소는 사용자의 요청을 특정한 경로에 해당 하는 Action 클래스와 매핑을 하는 역할을 담당 합니다. Action 요소의 path 속성과 클라이언트로부터 들어온 요청 URI 경로를 매치시켜 특정 매핑을 선택 합니다.

Action 요소의 자식요소는 다음과 같습니다.

<!ELEMENT action (icon?, display-name?, description, set-property*, exception*, forward*)>

앞에서 설명한 exception 요소의 경우 global, action 양쪽에서 선언이 가능하다고 했습니다. 물론 action에서 정의한 exception이 global로 선언 한 것 보다는 우선권이 있습니다.


또한 forward인 경우에도 global, action 양쪽에서 선언이 가능하며 exception의 경우와 비슷합니다.

다음은 action 요소의 속성 입니다.

attribute : 이 action이 접근 가능한 요청 또는 세션 scope의 폼빈 이름, 이속성은 name 속성에 폼빈이 지정되어 있는 경우에만 사용 가능 합니다.

className : 액션과 관련된 정보를 포함하게 되는 빈을 구현한 클래스, 값을 지정하지 않으면 org.apache.struts.action.ActionMapping이 기본 클래스 입니다. 이속성은 선택적 입니다.

forward : 포워드될 서블릿이나 JSP의 상대경로, 이 속성은 선택적이며 org.apache.struts.action.ForwardAction 클래스가 동일한 역할을 하는데 서용 됩니다.

include : 클라이언트의 요청에 대해 포함되어야 할 서블릿이나 JSP의 상대경로

input : 폼빈에서 검증오류가 생기는 경우 돌아갈 곳

name : 폼빈의 이름

path : 액션의 이름, 요청을 처리할 액션의 상대 경로

parameter : action 인스턴스에 어떤 정보를 넘기기 위해 사용, 여기에 값을 지정하면 getParameter  메소드를 이용하여 값을 알아낼 수 있습니다.

prefix : 예를 들어 폼빈의 모든 속성이 “pre_”로 시작한다면 prefix 속성을 세팅해서 요청 인자가 ActionForm 속성과 일치  하도록 할 수 있습니다. Name 속성이 지정된 경우에만 사용 가능 합니다.

scope : 폼빈의 스코프, name 속성을 지정한 경우에만 사용 가능 하며 “request” or “session” 이 들어 올 수 있으며 기본값은 “session” 입니다.

suffix : 예를 들어 폼빈의 모든 속성이 “_foo” 로 끝난다면 suffix 속성을 지정하여 요청인자가 ActionForm 빈의 속성과 일치하게 합니다.

type : Action 클래스를 상속하는 즉 액션을 처리하는 클래스의 전체경로 및 이름

unknown : 이 액션을 애플리케이션에서 기본으로 설정 해야 하는지 여부를 표시 한다. true로 설정하면 이 액션은 처리할 액션이 지정되지 않은 모든 요청을 처리

validate : 폼빈의 validate() 메소드가 execute() 메소드 전에 실행 되어야 하는 지의 여부를 표시, 기본값은 true

<action-mappings>
        <!-- loginAction에 대한 정의 -->
        <action         
                path="/LoginSubmit"
                type="login2.LoginAction"
                    scope=”rewuest”
                name="loginForm"                       
                validate="true"
                input="/login.jsp"
        >       
                  <forward name=”SUCCESS” path=”/success.jsp” redirect=”true”/>
            </action>
    </action-mappings>


6.        controller 요소

struts 1.1이상에서 새로 나온 기능으로 이전 버전에서는 ActionServlet 클래스가 컨트롤러 기능을 하며 이를 상속해서 컨트롤러의 기능을 구현 했습니다. 그러나 1.1이상에서는 대부분의 컨트롤러의 기능은 RequestProcessor 클래스로 이전 했습니다.

1.1이전의 예

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>myPackage.myActionServlet</servlet-class>
</servlet>


ActionServlet은 여전히 사용자의 요청을 받아 들이지만 그 요청에 대한 처리는 RequestProcessor 클래스의 인스턴스에 위임 합니다. 이렇게 함으로서 요청을 처리하는 클래스를 할당하고 기능을 수정 하는 것이 가능 해집니다.

Controller 요소는 자식요소 하나를 포함 합니다.

<!ELEMENT controller (set-property*)>

아래는 controller 요소의 속성 입니다.

bufferSize : 파일 업로드 시 사용하는 입력 버퍼의 크기, 기본값은 4096 입니다.

className : 컨트롤러 정보를 담아놓을 자바 빈을 구현한 클래스, org.apache.struts.config.ControllerConfig의 하위클래스여야 합니다. 기본값은 ControllerConfig 입니다.

contentType : 응답 경과를 보낼 때 사용하는 contentType, 이 속성은 선택적으로 사용 할 수 있으며 기본값은 “text/html” 입니다. 이 속성에 값이 있더라도 JSP 파일에 contentType을 기술 한다면 JSP 파일의 내용이 우선 합니다.

debug : 디버깅 레벨, 값이 클수록 많은 로깅 정보들이 기록되며, 기본값은 0으로 로깅 정보가 기록되지 않습니다.

locale : 사용자의 지역 정보를 세션에 저장 할지 여부, 기본값은 false

maxFileSize : 파일 업로드 시 허용되는 최대 용량

multipartClass : Multipart 요청에 대한 처리를 담당할 클래스, 기본값은 ora.apache.struts.upload 패키지의 DiskMultipartRequestHandler 입니다.

nocache : 응답에 있는 nocache 헤더에 대한 설정, true 또는 false, 기본값은 false, c가 소문자임을 주의

processClass : 사용자의 요청을 처리 할 클래스의 전체 이름

tempDir : 파일 업로드의 경우 사용할 임시 디렉토리


<controller
            contentType="text/html;charset=euc-kr"
            debug="3"           
            locale="true"
            nocache="true"
            processorClass="filter.MyFilter"/>


7.        message-resources 요소

메시지 리소스 번들과 관련된 특징을 기술 합니다.

각각의 스트럿츠 설정 파일은 메시지 리소스 번들을 하나 이상 지정 할 수 있습니다.

<!ELEMENT message-resources (set-propert*)>

필요한 속성만 살펴 보도록 합니다.
 
className : message-resources의 정보를 담을 자바빈을 구현한 클래스

key : 메시지 리소스 번들이 저장될 서블릿 컨텍스트 속성, 기본값은 Action.MESSAGE_KEY에 의해 지정 됩니다.

null : 정의되지 않은 메시지 키가 사용된 경우 MessageResource의 하위 클래스에서 어떻게 처리 할지를 나타내는 Boolean 값. true로 설정하면 빈 문자열을 돌려줍니다. false로 설정하면 “???global.label.missing???”와 같은 문자를 돌려 줍니다.

parameter : 예를 들어 리소스 번들의 이름이 Application.properties 라면 이 속성의 값은 Application이 됩니다. 반드시 정의해야 하는 속성 입니다. 만약 리소스 번들이 패키지화 되어 있다면 전체 경로를 지정 해야 합니다.

<message-resources parameter="resources.application"/>


8.        plug-in 요소

struts application이 구동 시에 동적인 자원을 처리 할 수 있게 해주는 기능

예를 들어 애플리케이션 구동 시 원격의 시스템에 연결 해야 된다면 직접 코딩하지 않고 플로그인 기능을 이용하여 이 기능을 구현할 수 있습니다. 플러그인을 사용하기 위해서는 org.apache.struts.PlugIn 인터페이스를 구현하는 자바 클래스를 생성 한 후 설정 파일의 plug-in 요소에 추가 하면 됩니다.

public interface PlugIn {
public void init(ActionServlet servlet, ApplicationConfig config)
throws ServletException;
public void destroy();
}


1.1이전 버전에서는 ActionServlet의 subClass를 통해 애플리케이션 구동 시 애플리케이션의 리소스를 초기화 했지만 1.1이후 버전에서는 Plug-In을 통해 이것이 가능 하게 됨

Plug-In의 경우 스트럿츠 애플리케이션이 초기화 되는 경우 ActionServlet이 Plug-In의 Init() method 를 호출 합니다.

Plug-In은 struts-config.xml 파일에 기술된 순서에 따라  호출됩니다.

<!ELEMENT plug-in (set-property*)>

<plug-in className="org.apache.struts.plugins.ModuleConfigVerifier"/>
<plug-in
className="org.apache.struts.webapp.example.memory.MemoryDatabasePlugIn">
<set-property property="pathname" value="/WEB-INF/database.xml"/>
</plug-in>

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>

예제

public final class MemoryDatabasePlugIn implements PlugIn {
...

        public void init(ActionServlet servlet, ModuleConfig config) throws ServletException {
                log.info("Initializing memory database plug in from '" +        pathname + "'");
                // Remember our associated configuration and servlet
                this.config = config;
                this.servlet = servlet;

                // Construct a new database and make it available
                database = new MemoryUserDatabase();
                try {
                        String path = calculatePath();
                        if (log.isDebugEnabled()) {
                                log.debug(" Loading database from '" + path + "'");
                        }
                        database.setPathname(path);
                        database.open();
                } catch (Exception e) {
                        log.error("Opening memory database", e);
                        throw new ServletException("Cannot load database from '" +        pathname + "'", e);
                }

                // Make the initialized database available
                servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,database);

                // Setup and cache other required data
                setupCache(servlet, config);
        }
}

public final class MemoryDatabasePlugIn implements PlugIn {
...

        public void destroy() {
                log.info("Finalizing memory database plug in");
                if (database != null) {
                        try {
                                database.close();
                        } catch (Exception e) {
                                log.error("Closing memory database", e);
                        }
                }

                servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
                database = null;
                servlet = null;
                database = null;
                config = null;
        }
}

[ORACLE SGA TUNING, 오라클교육,자바교육, 오라클자바]Literal SQL & Bind Variable

Literal SQL Statement와  Bind Variable 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  




 Literal SQL문을 많이 사용하면 Hard Parsing의 빈도를 높이게 되어 Library Cache내에서 Cache되는 SQL문들이 자주 age out 하게 되므로 주기를 빠르게 하고 Dictionary Cache의 사용율을 높이게 됩니다. 이러한 이유로 OLTP DB환경에서는 Shared SQL문중에서 Literal SQL 문들을 찾아내어 Bind Variable을 이용한 방법을 사용하도록 해야 합니다. 즉 OLTP 환경에서 가급적 Literal SQL Statement의 사용은 줄이라는 이야깁니다.

아래의 내용을 참고 하시구요…

Eg 1: SELECT * FROM emp WHERE ename='CLARK';

 is used by the application instead of SELECT * FROM emp WHERE ename=:bind1;

Eg 2: SELECT sysdate FROM dual;

does not use bind variables but would not be considered as a literal SQL statement for this article as it can be shared.

Eg 3: SELECT version FROM app_version WHERE version>2.0;

If this same statement was used for checking the 'version' throughout the application then the literal value '2.0' is always the same so this statement can be considered sharable.

자 그럼 이젠 Hard Parsing과 Soft Parsing에 대해 정리 해보도록 하겠습니다.

Hard Parse

하드파싱이란 새 SQL문장이 실행 되는 경우엔 Shared Pool에는 없으므로 완전히 전부 새로 파싱을 한다는 의미 입니다. 오라클은 Shared Pool에 새로운 SQL문장을 할당 하며 SQL 문장이 문법은 맞는지등을 검사 하게 됩니다. 이 경우 CPU 사용이 매우 많아 지게 되는거죠, 물론 Latch의 사용도 증가 하게 됩니다.

Soft Parse

소프트 파싱이란 스행하고자 하는 SQL 문장이 이미 Shared Pool에 있어 이미 존재하는 SQL에 관련된 정보를 그대로 이용하는 겁니다.

그럼 Soft Parse가 되기 위해서는 가능 하면 동일한 SQL 문장을 구사해야 하겠죠? (당근이죠^^)

동일한 SQL 문장이란 무엇인지 알아 보도록 하겠습니다. 우선 하드 파싱의 대상에는 어떤 것이 있는지 알아 보기로 하겠습니다.

우선 같은 테이블을 질의 하더라도 사용자 계정이 다른 경우 동일한 SQL 문장으로 간주 되지 않으므로, 또 SQL문장의 공백이 다른 경우, (select * from emp와 select    *    from    emp는 다릅니다.) 음 그리고 Bind Variable을 사용하는 경우 변수명 이나 타입이 다른 경우에도 그렇구요, 동일한 질의라도 SQL문장의 대소문자 역시 다르면 이것 역시 하드 파싱의 대상이므로 삼가 해야 합니다. 마지막으로 SQL문장의 라인이 달라두 역시..
같은 SQL 문장을 한라인에 쓰는 경우와 여러 라인에 나누어 쓰는 것은 다르게 인식 되는 것 입니다.

select substr(sql_text,1,40) "SQL", count(*),
      sum(executions) "총 실행 횟수"
from v$sqlarea
group by substr(sql_text,1,40)
having count(*) > 5
order by 2;

다음의 예문을 잘 이해하도록 하자구요~

SQL> conn / as sysdba
연결되었습니다.

공유 영역을 클리어 합니다.
SQL> alter system flush shared_pool;

시스템이 변경되었습니다.

SQL> conn scott/tiger
연결되었습니다.
SQL> select count(*) from emp;

  COUNT(*)
----------
        14

Emp 테이블의 개수를 얻기 위한걸 한번 수행 했습니다.

그런 다은 v$SQLAREA 뷰에서 확인 해 봅니다.
SQL> conn / as sysdba

SQL> select substr(sql_text,1,40) "SQL", count(*),
  2        sum(executions) "총 실행 횟수"
  3  from v$sqlarea
  4  where sql_text like '%emp%'
  5  group by substr(sql_text,1,40)
  6  having count(*) > 0
  7  order by 2;


 SQL                    COUNT(*)      총 실행 횟수
---------- ----------------------------------
select count(*) from emp        1            1
이하 생략

SQL> conn scott/tiger
연결되었습니다.
SQL> select count(*) from emp;

  COUNT(*)
----------
        14

SQL> select count(*) from emp;

  COUNT(*)
----------
        14

그런 다음 다시 v$SQLAREA에서 확인 하죠^^

SQL> select substr(sql_text,1,40) "SQL", count(*),
  2        sum(executions) "총 실행 횟수"
  3  from v$sqlarea
  4  where sql_text like '%emp%'
  5  group by substr(sql_text,1,40)
  6  having count(*) > 0
  7  order by 2;

SQL
---------------------------------------------------------------------

  SQL                    COUNT(*)  총 실행 횟수
---------- -----------------------------
select count(*) from emp        1            3

자 그럼 이번에는 동일한 SQL 문장인데 공백을 더 넣어서 Hard Parsing이 일어나게 해 볼까요…

SQL> conn scott/tiger
연결되었습니다.
SQL> select count(*) from    emp;

  COUNT(*)
----------
        14

V$sqlarea를 조회해 보죠…

SQL> select substr(sql_text,1,40) "SQL", count(*),
  2        sum(executions) "총 실행 횟수"
  3  from v$sqlarea
  4  where sql_text like '%emp%'
  5  group by substr(sql_text,1,40)
  6  having count(*) > 0
  7  order by 2;

SQL                            COUNT(*)    총 실행 횟수
---------- ---------------------------------------
select count(*) from    emp        1            1
select count(*) from emp              1            3

이해 되시죠… 공백 뿐 아니라 대소문자등도 주의 해야 합니다.

2013년 8월 5일 월요일

(오라클시퀀스, ORACLEJAVA,오라클자바교육)Oracle Sequence

오라클 시퀀스는 DB Table의 자동증분 컬럼에 사용하면 유용하다. 아래 내용을 확인하자.



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 



A. 개념
- Sequence는 순차적인 일련번호를 생성한다.(최대 38자리의 Oracle정수)
- Sequence는 다중 사용자환경에서 디스크 입출력 오버헤드나 Transaction Locking없이
고유한 순번을 생성하는데 용이하다.
- Sequence생성시 Sequence이름, 오름차순또는 내린차순여부, 번호간격등을 정의한다.
- Sequence번호는 Table과 독립적으로 생성되며,따라서 동일한 Sequence를 하나또는 여러
개의 Table에 사용할수 있다.
B. Sequence생성
- create sequence emp_sequence
increment by 1
start with 1
nomaxvalue
nocycle
cache 10;

cache Optiom은 일련의 Sequence를 미리 할당하고 메모리에 유지하면서 시퀀스를 빠르게 Access
할수있게 한다. 일련의 Sequence를 Cache하면 Sequence를 건너 뛸수있다.
예를들어 Instance가 비정상적으로 종료되면 캐시되었지만 사용안된 Sequence를 잃어버리게 된다.
즉 Cache를 상요하면 Sequence를 빠르게 Access할수 있으나 비정상적으로 종료돨 경우에는 번호가
건너 뛰게된다.

C. Sequence 변경
Alter sequence emp_sequence
Increment by 10
Maxvalue 10000
Cycle
Cache 20;
D. Sequence에 영향을 주는 변수
Sequence_cache_entries매개변수는 캐시될 시퀀스를 설정하다. 너무 낮으면 시퀀스값을 건너
뛸수도 있다. 예를들면 다섯개의 Cache된 Sequence를 사용하고 캐시가 다찼으며,매개변수 값이
4라면 현재 4개의 시퀀스가 Cache되었다면 캐시에서 최근에 가장적게 사용한 Sequence는 5번째
Sequence로 바뀌면서 이 Sequence의 모든 다른값(캐시된 마지막 Sequence까지)은 손실된다.

E. Sequence삭제
- drop sequence emp_sequence; 

(자바 스윙, 자바오라클교육,ORACLE)JAVA SWING JFC

JFC(Java Foundation Class)


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 


 www.onjprogramming.co.kr 


그래픽 사용자 인터페이스의 구현을 위한 일련의 기능요소를 묶은것으로 다음과 같은 요소가 포함 됩니다.
- 스윙컴포넌트(Swing Component)
- 교체 가능한 외양(Pluggable look & feel) 지원 GUI의 겉모습과 작동방식을 자유롭게 선택 교체할수 있게함 , 예를들면 같은 프로그램을 java look&feel로 또는 window look&feel로 나타내도록 할 수 있습니다.
- 접근지원 API 화면의 내용을 음성으로 읽어 주거나 점자로 출력하는등의 장애자용 인터페이스에 관련된 기능
- Java 2D API 고품질의 2D 그래픽, 텍스트, 이미지를 Appication이나 Applet등에서 쉽게 사용가능 - 드래그&드롭 지원 자바 어플리케이션과 운영체제 고유의 어플리케이션 사이에서 끌어놓기를 지원 합니다.



자바 스윙(Swing) 이란...
자바나 C++, C#등 보게 되면 처음에는 Helloworld 부터 컨솔화면에 찍기 시작하여 나중에는 멋진 윈도우 화면에 무언가 다이나믹한것을 만들게 됩니다. 어느정도 console 창(도스 창)에서 작성하는 프로그래밍에 숙련되면, GUI(graphic user interface)를 통해 작동하는 프로그램을 짜게 된다는 거죠~ 기본적으로 자바는 AWT(abstract window toolkit)라는 것을 제공하여 윈도우 프로그램을 개발 하게 했지만 무거우며 플랫폼나자 다른 형태로 나타나는 등의 단점이 있어 아마도 JDK1.2 이상에서 Swing이라는 것을 지원하기 시작 했습니다. 자바 프로그램에서 Swing을 이용하여 윈도우 프로그램을 개발할려면 import javax.swing.*; 형태로 사용 합니다. 또한 스윙 컴포넌트는 앞에 'J'를 붙입니다. 즉 기존 AWT에서 제공 되었던 컴포넌트와 구분하기 위해서 입니다.

스윙 Component와 AWT Component의 차이점
- 스윙 컴포넌트는 ‘ J ' 로 시작한다.(Button, JButtion)
- AWT컴포넌트는 java.awt 패키지안에, Swing 컴포넌트는 javax.swing 패키지 내에 존재 합니다.
- 모든 스윙 컴포넌트는 javax.swing.Jcomponent를 상속 합니다.
- 스윙 컴포넌트는 특정 플랫폼에 의존적인 코드가 전혀 포함되지 않고 구현됨 즉, 그들이 수행될 때 플랫폼으 로부터 어떠한 native code도 가져다 쓰지 않습니다.
- 스윙의 버튼은 텍스트뿐만 아니라 이미지도 표시 할 수 있습니다.
- 스윙 컴포넌트는 직사각형 이외의 모양도 가능 합니다.(둥근버튼)
- 프로그램 내에서 스윙컴포넌트와 중량(heavy weight) 컴포넌트를 사용하면 안된다. 즉시 사용가능한 AWT 컴포넌트나 AWT Canvas, Panel을 상속한 클래스는 중량컴포넌트이다. 경량과 중량이 곁쳐지는 경우에는 경량컴포넌트가 가려지기 때문이다.
- JFrame와 같은 최상위 컨테이너에 직접 컴포넌트를 추가하지 않습니다. 그대신 Jframe에 포함된 다른 컨테이너에 컴포넌트를 추가 하는 겁니다.(Panel등)
- 스윙에서는 Border를 그맇수 있습니다. AWT는 Peer를 거치므로 모양에 관여할수 없었지만, 스윙은 직접 그리 는것을 담당하므로 Border를 쉽게 그릴수 있습니다.
- 컴포넌트의 최대/최소 크기와 가장 적절한 크기를 지정 할 수 있습니다. AWT에서는 Peer에 의해 제어되므로 마 음대로 크기를 제어하기가 어렵습니다
- ToolTip을 만들기가 쉽습니다.(Jcomponent에 ToolTip에 대한 메소드가 존재)
- 투명한 Component가 가능(setOpaque() 이용하여 설정가능)
- Jframe은 윈도우 이벤트 핸들링을 하지 않아도 윈도우를 종료할수가 있다. 이는 내부적으로 이벤트 핸들링 코드가 존재하기 때문인데 프로그래머가 바꿀수 있도록 설정이 가능합니다. setDefaultCloseOperation(int) 이 라는 메소드를 이용 합니다. 파마미터로 java.swing.WindowConstants의 DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE,DISPOSE_ON_CLOSE 값을 이용할수 있으며 DISPOSE_ON_CLOSE가 기본값 입니다.

스윙의 특징
- 교체 가능한 외관(look & feel) --> look & feel이 동작도중에 동적으로 교체가 가능 합니다.. 자바의 확실한 멀티플랫폼 지원의 일부 현재 Window, java, Motif 세가지 외관이 지원 됩니다.
- MVC(Model View Controller) 모델 --> MVC 구조는 Alan Kay라는 사람이 만든 객체 지향 언어인 Smalltalk-80 version에서 소개 컴포넌트 디자인 모델의 하나로 각각의 컴포넌트를 Model, View, Controler로 구분하여 추상화 한것이며 ① 모델(Model) : 프로그램의 상태에 대한 논리적인 데이터를 표현, 또한 모델의 데이터가 변경되었을 경우 이를 뷰 객체에게 알려주는 역할을 하는 객체 입니다. ② 뷰(View) : 모델에 의해서 표현된 데이터에 대한 시각적인 화면 출력을 관리하는 객체 입니다. 뷰는 응답 메커니즘을 기술하기 위하여 콘트롤러를 이용 하는거죠 즉, 콘트롤러의 입력에 응답하여 그 결과를 화면으로 출력해 주는ㄴ것 입니다. ③ 콘트롤러(Controller) : 모델에 의해서 표현된 데이터를 사용자가 변경할 수 있도록 사용자 상호작용(User Interaction)을 제공하는 객체 입니다. JFC의 Swing에서의 MVC의 구조는 상태부분(Model)과 표현부분(View+Controller=UI)으로 구분함으로써 다음과 같은 특징을 갖는것 입니다.
- 같은 모델을 가지고 쉽게 동시에 여러 개의 뷰를 만들 수 있습니다.
- 모델에는 표현부분이 없기 때문에 모델의 영향을 주지 않고 필요에 따라 뷰를 자유롭게 수정할 수 있습니다.
- Swing 일반적인 MVC 구조에서 공통적으로 약간 변형시킨 형태로 컴포넌트를 표현 합니다. 즉, 뷰와 콘 트롤러를 하나로 묶어서 델리게이트라는 커다란 컴포넌트를 형성,모델은 바꾸지 않고 프로그램 실행 중 간에 Delegate(view+Controller)를 통해 Java Look&feel을 윈도우 look&feel로 바꿀 수가 있는 것입니다.
- 경량 컴포넌트(lightweight Component) : 시스템의 Native Component와 연계되지않은 컴포넌트, 반대로 AWT의 모든 컴포넌트는 Peer라는것을 통하여 시스템의 Native Component와 연계되어 있습니다. Native Component를 사용하지 않으므로 자원을 적게 소모하며 플랫폼에 독립적인 컴포넌트를 만들수 있는 것 입니다. 스윙 컴포넌트는 경량 컴포넌트라 말할 수 있습니다. 그렇다고 스윙 컴포넌트가 모두 경량 컴포넌 트라는 말은 아닙니다. 경량 컴포넌트는 완전히 Java 만으로 작성되어야 하고, 사용자가 임의로 룩앤필 을 바꿀 수 있는 것이라야 합니다 .
- 중량 컴포넌트란 그 플랫폼이 제공하는 컴포넌트로 사용자가 변화를 모색할 수 없는 매우 경직된 컴포넌트, AWT 컴포넌트는 중량형 컴포넌트 입니다.
- 스윙은 모든 플랫폼에서 동일한 외형을 갖고, 동일한 작동을 하며, 최대한 유연성을 갖는 완전히 Java 만으로 작성된 "경량형lightweight" 컴포넌트를 제공한다는 목적으로 시작된것 입니다.
아래는 간단한 스윙 예제 입니다.
[예제]
// HelloSwing.java
// JMEnuBar를 제외하고 나머지(JButton, LayoutManger등)을 JFrame에 추가할때 contentPane에 추가
// JFrame의 경우 윈도우 이벤트를 처리하지 않아도 윈도우는 종료되지만 프로그램이 종료되지는 않는다.
import java.awt.*; import java.awt.event.*; import javax.swing.*;
class HelloSwing extends JFrame {
public HelloSwing(String title) {
super(title);
display();
}
public void display() {
Container cpane;
JMenuBar mb = new JMenuBar();
JMenu menu;
menu = new JMenu("File");
menu.add(new JMenuItem("Open"));
menu.add(new JMenuItem("Save"));

menu.addSeparator();
menu.add(new JMenuItem("Exit"));
mb.add(menu);
setJMenuBar(mb);
cpane = getContentPane();
cpane.setLayout(new BorderLayout());
cpane.add(new JButton("안녕, 스윙"),BorderLayout.CENTER);
}
public static void main(String[] args) {
HelloSwing hs = new HelloSwing("수윙 시작... 시작이 반이다.");
hs.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
}
);
hs.pack(); hs.setSize(300, 200); hs.setVisible(true);
}
}




ORACLE DataBase Buffer Cache Tuning

DataBase Buffer Cache의 튜닝


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 
 www.onjprogramming.co.kr 


 데이터베이스 버퍼 캐시는 데이터 처리를 위해 사용되는 부분이며 가장 최근에 사용 되어진 DB 블록을 저장하고 있는 SGA의 구성 요소 입니다. 말그대로 버퍼 캐시이므로 수향 속도와 밀접한 관계가 있습니다. 최근에 사용되어진 데이터를 메모리에 보관해 추후 질의시 이를 이용하여 디스크에서 직접 데이터를 가지고 오지 않고 메모리에서 읽어 오므로 성능의 향상을 꽤 할 수 있는 겁니다. 이 곳에는 변경되지 않은 데이터 뿐 아니라 변경된 데이터도 가지고 있습니다. 또한 DataBase Buffer Cache는 chain list, dirty list, LRU list로 구성 되어져 있습니다. 오라클의 백그라운드 프로세스인 DBWR는 FREE BUFFER의 확보를 위해 변경된 데이테베이스 블록을 디스크(데이터베이스 파일)에 기록하는 역할을 합니다.

 DataBase Buffer Cache의 BUFFER는 LRU list와 dirty list로 구성되는데 LRU list의 버퍼들은 Free buffer, Pinned Buffer, Dirty Buffe중 하나로 존재하게 됩니다. 처음엔 버퍼가 free 상태인데 사용자가 질의를 해서 디스크에서 테이블의 내용을 읽으면 이 블록들은 LRU에서 가장 최근에 읽은 것이므로  HEADER 부분(MRU, Most recently used)에 위치하게 됩니다. 이 버퍼들이 차츰 다른 테이블의 내용들이 읽혀 짐에 따라 LRU의 tail부분인 LRU(Lease Recent Used)로 이동되게 되는 겁니다. 만약 사용자가 대량의 데이터를 질의하여 버퍼가 필요한데 빈 버퍼가 없다면 제일 사용된 빈도가 작은 블록을 찾기 위해 LRU 알고리즘에 의해 LRU list의 맨 끝인 tail 부분부터 검색하기 시작 합니다.

 LRU list의 작 버퍼에 대해 살펴 보면 Pinned Buffer는 현재 사용자가 사용중이므로 재사용 될 수 없는 상태이며 Free Buffer는 dirty buffer등이 데이터파일(디스크)에 기록되어져서 free로 mark가 되어 사용될 수 있는 상태의 버퍼 입니다. 또는 modify 되지않아 사용가능 한 상태를 나타 냅니다. 그리고 dirty buffer는 사용자가 사용하여 내용이 변경되었지만 아직 디스크에 기록되지 않은 버퍼를 나타냅니다.

LRUW(dirty list)는 서버 프로세스에 의해 모아진 dirty buffer들이 모여 있는 곳 입니다. 이 dirty buffer들은 오라클 프로세스들이 빈 버퍼(free buffer)를 찾기 위해 LRU의 tail 부분부터 찾아 가다가 dirty buffer를 만나면 LRUW(dirty list)에 옮겨 놓게 되는 겁니다. 이 버퍼들은 추후 DBWR에 의해 디스크에 있는 데이터파일에 기록되고 다시 free로 mark 되어 LRU list에 자게 되는 것입니다.

이번에는 버퍼 캐시의 튜닝에 대해 알아 보겠습니다.

 버퍼 캐시에 대한 hit ratio는 논리적인 IO와 물리적인 IO에 대한 비율을 의미하며 DataBase Buffer Cache의 성능을 측정 하기 위한 주요한 척도가 됩니다. DataBase Buffer  Cache의 hit ratio는 V$sysstat에서 DB BLOCK GETS와 CONSISTENT GETS, physical reads 값으로 구해지는데 DB BLOCK GETS와 CONSISTENT GETS는 logical read를 의미하며 메모리상의 버퍼에서 access되는 블록을 뜻합니다. Physical reads는 디스크에서 읽는 것을 나타내며 데이터파일에서 로딩되는 블록의 수를 나타냅니다.

 Hit ratio는 90%이상을 유지하는 것이 좋으며 70% 이하기 되었을 때는 db_block_buffers 또는 유_cache_size를 증가 시키는 것이 바람직 합니다. 과거의 Oracle7,8에서는 아래처럼 hit ratio를 구했습니다.

                            (physical reads)
    Hit ratio = ---------------------------------
                          (consistent reads + db_block_gets)

SQL> conn / as sysdba
연결되었습니다.
SQL> select trunc((1-(phy.value/(curr.value + consis.value))) * 100,5)
  2      from v$sysstat phy, v$sysstat curr, v$sysstat consis
  3      where phy.name = 'physical reads'
  4    and curr.name = 'db block gets'
  5      and consis.name = 'consistent gets'
  6  /

하지만 Oracle 8i, 9i에서는 좀더 정확한 값을 구하기 위해 아래처럼 physical reads direct + physical reads direct(lob)를 포함 합니다.

SQL> set serveroutput on
SQL> declare
  2    physicalreads number;
  3    physicalreadsdirect number;
  4    physicalreadsdirectlob number;
  5    dbblockgets number;
  6    consis number;
  7    hratio number;
  8  begin
  9    select value into physicalreads from v$sysstat where name = 'physical r
ads';
 10    select value into physicalreadsdirect from v$sysstat where name = 'phys
cal reads direct';
 11    select value into physicalreadsdirectlob from v$sysstat where name = 'p
ysical reads direct (lob)';
 12    select value into dbblockgets from v$sysstat where name = 'db block get
';
 13    select value into consis from v$sysstat where name = 'consistent gets';
 14    select 100 * (1- (physicalreads - (physicalreadsdirect + physicalreadsd
rectlob))
 15                      /(dbblockgets + consis - physicalreadsdirect -physical
eadsdirectlob )) into hratio
 16          from dual;
 17          dbms_output.put_line('DB Buffer Cache Hit Ratio : ' || hratio);
 18  end;
 19  /