레이블이 Oracle Database Startup shut down인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Oracle Database Startup shut down인 게시물을 표시합니다. 모든 게시물 표시

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일 목요일

[오라클자바커뮤니티강좌교육]JAVA instance, static class 변수

이번 강좌에서는 자바에서의 변수에 대해 알아 보도록 하죠...



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




자바에서의 변수는 지역변수(local variables), 매개변수(parameters),클래스 범위에서 선언 한 인스턴스 변수(instance fields), 클래스 변수(class fields) 등으로 구분 할 수 있습니다. 물론 인스턴스 변수나 클래스변수나 전부 어떤 메소드(함수)안에서 선언되는 것이 아니라 메소드 밖에 선언되는 변수 입니다. 말이 틀리지만 그 쓰임새 또한 대단히 다르니 잘 아래의 내용을 발 봐두어야 합니다.

전 가끔 붕어빵 찍는 틀클래스로 비유하고 그 틀에 의해 찍혀 나오는 각각의 붕어(인스턴스)객체라고 비유 합니다. 붕어빵 찍는 클이 클래스라고 했으니 클래스 변수 붕어빵 찍는 틀과 관련이 있는 거죠... 즉 찍혀 나온 모든 붕어빵들이 공유하는 전역 변수로서 역할을 하며 또한 붕어를 만들어 내지 않아도 붕어빵 찍는 틀애 있는 것이니까 New 하지 않아도(붕어를 찍어 내지 않아도) 접근이 가능하죠... 즉 클래스 변수는 클래스이름.클래스변수명 으로 접근이 가능 한겁니다. 각각의 붕어를 찍어 낼때 팥의 양을 조절이 가능하다고 가정 할때 클래스변수가 아닌 인스턴스 변수팥의양을 둘 수가 있겠죠... 이건 붕어빵 찍는 틀(클래스)과 관련이 있는 변수가 아니라 찍혀 나온 붕어(인스턴스)들에 관련이 있는 변수 이므로 인스턴스 변수라고 하고 반드시 붕어를 찍어 낸 후(New 한 후) 접근이 가능한 변수가 되는 겁니다. 이해가 되시나요? 아래를 보시면서 다시 한번 정리하시기 바랍니다. 그래서 static이라는 키워드를 보는 순간 전역변수, 초기화가 한번만(붕어빵 찍는 틀과 관련이 있으므로), New 하지 안아도(붕어를 찍어 내지 않아도) 접근이 가능하며 즉 클래스이름.변수명... 잘 기억하시기 바랍니다.

클래스 변수

클래스의 인스턴스(객체)가 아니라 그것이 정의된 클래스와 연관된다.
static 한정자는 이 변수(필드)가 클래스필드 임을 의미
상수를 정의하는것이 클래스필드의 일반적인 사용이다.public static final double PI=3.14159;
정적필드의 복사본은 오직 한 개 존재하며 전역변수로 사용 된다.
같은 클래스 내부에서는 PI로 지칭되며 클래스 외부에서 해당 변수(필드)를 유일하게 지칭하기 위해서는 클래스명.PI로 인스턴스를 생성하지 않고도 직접 참조가 가능(물론 인스턴스를 만든 후 객체참조변수.PI형태의 참조도 가능하다.)


인스턴스 변수

static으로 선언되지 않은 모든 변수(필드)는 인스턴스 변수 입니다. public double r;
클래스의 인스턴스와 연관, 생성된 모든 객체는 자신만의
복사본을 가진다.
클래스 내부에서 이름 하나만으로 지칭된다
public double r;
public double area() {
return PI * r * r;
}
클래스 외부에서는 클래스를 인스턴스화한 객체.변수명 형
태로 사용한다. 인스턴스 필드(변수)의 값은 한객체를 다른
객체와 구분한다.
Circle c = new Circle(); c.r=2.0;
Circle c1 = new Circle(); c1.r=5.0;






[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월 5일 월요일

(자바 스윙, 자바오라클교육,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 SGA Tuning]DBMS_SHARED_POOL, Object KEEP

[ORACLE SGA Tuning]DBMS_SHARED_POOL, Object KEEP

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




DBMS_SHARED_POOL을 이용한 KEEP

 Shared Poll에 크기가 큰 프로그램을 KEEP하기 위해서는 아래에 있는 것처럼 DBMS_SHARED_POOL Package를 이용 할 수 있습니다.

SQL> @C:\oracle\ora92\rdbms\admin\dbmspool.sql

패키지가 생성되었습니다.


권한이 부여되었습니다.


뷰가 생성되었습니다.


패키지 본문이 생성되었습니다.

SQL> @C:\oracle\ora92\rdbms\admin\prvtpool.plb

뷰가 생성되었습니다.


패키지 본문이 생성되었습니다.

SQL> grant execute on dbms_shared_pool to scott;

권한이 부여되었습니다.

Object를 KEEP하는 방법은 다음과 같습니다.

Procedure,Function,Package : exec dbms_shared_pool.keep(‘pname’,’p’)
Trigger : exec dbms_shared_pool.keep(‘tr_emp’,’r’)
Sequence : exec dbms_shared_pool.keep(‘seq_empno,’q’)
SQL문은 아래와 같은 방법으로 KEEP 합니다.

예를들어 select empno, ename, sal from emp where deptno = ‘20’ 라는 SQL문장을 Library Cache안의 Shared Cursor 부분에 KEEP하기 위해서는 아래처럼 하면 됩니다…

SQL> conn scott/tiger
연결되었습니다.

SQL> select empno, ename, sal from emp where deptno = 20;

    EMPNO ENAME            SAL
---------- ---------- ----------
      7369 SMITH            800
      7566 JONES            2975
      7788 SCOTT            3000
      7876 ADAMS            1100
      7902 FORD            3000

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

SQL> select address, hash_value from v$sqlarea
  2  where sql_text = 'select empno, ename, sal from emp where deptno = 20';

ADDRESS  HASH_VALUE
-------- ----------
7856AC4C 1137127237  <- 원하는 SQL문장에 대한 주소와 해시 값

아래 명령으로  KEEP 합니다.

SQL> exec dbms_shared_pool.keep('7856AC4C, 1137127237','c');

PL/SQL 처리가 정상적으로 완료되었습니다.

Object의 KEEP 상태는 다음으로 체크 가능 합니다.

SQL> select distinct name, sharable_mem, loads
  2  from v$db_object_cache
  3  where name like '%emp%'
  4  and kept = 'YES';

NAME                                      SHARABLE_MEM      LOADS
------------ ----------------------------------------------
select empno, ename, sal from emp where deptno = 20  1469          1

또는 exec dbms_shared_pool.sizes(0)로 확인 가능 합니다. 이 sizes라는 procedure는 제한된 사이크 이상의 keep된 Object를 나타내 줍니다.

SQL> set serveroutput on size 2000
SQL> exec dbms_shared_pool.sizes(0)  -> buffer overflow가 나더라도 pin시킬(KEEP할) SQL문장을 찾을 수는 있습니다.

각 Object를 Shared Pool에 유지하던 것을 해제 할 때는 아래의 unkeep 프로시저를 이용 합니다.

SQL> exec dbms_shared_pool.unkeep('7856AC4C, 1137127237','c');

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select distinct name, sharable_mem, loads
  2  from v$db_object_cache
  3  where name like '%emp%'
4  and kept = 'YES';

결과가 없겠죠…


아래는 DBMS_SHARED_POOL.keep procedure 명셉니다… 메타링크 자료니 참고 하세요…

PROCEDURE:DBMS_SHARED_POOL.KEEP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Version/s:  7.1+, 8.0, 8.1
See Also:  [NOTE:67537.1] The Purpose of DB Package Reference Articles
            [NOTE:67569.1] DBMS_SHARED_POOL Package Description
 
Specification:
  procedure keep(name varchar2, flag char DEFAULT 'P');
 
Description:
  Keep an object in the shared pool.  Once an object has been keeped in
    the shared pool, it is not subject to aging out of the pool.  This
    may be useful for certain semi-frequently used large objects since
    when large objects are brought into the shared pool, a larger
    number of other objects (much more than the size of the object 
    being brought in, may need to be aged out in order to create a
    contiguous area large enough.
    WARNING:  This procedure may not be supported in the future when
    and if automatic mechanisms are implemented to make this 
    unnecessary.
 
  Input arguments:
    name
      The name of the object to keep.  There are two kinds of objects:
      PL/SQL objects, triggers, sequences which are specified by name,
          and SQL cursor objects which are specified by a two-part number
      (indicating a location in the shared pool).  For example:
        dbms_shared_pool.keep('scott.hispackage')
      will keep package HISPACKAGE, owned by SCOTT.  The names for
      PL/SQL objects follows SQL rules for naming objects (i.e., 
      delimited identifiers, multi-byte names, etc. are allowed).
      A cursor can be keeped by
        dbms_shared_pool.keep('0034CDFF, 20348871')
      The complete hexadecimal address must be in the first 8 characters.
      The value for this identifier is the concatonation of the
      'address' and 'hash_value' columns from the v$sqlarea view.  This
      is displayed by the 'sizes' call above.
      Currently 'TABLE' and 'VIEW' objects may not be keeped.
    flag
      This is an optional parameter.  If the parameter is not specified,
        the package assumes that the first parameter is the name of a
        package/procedure/function and will resolve the name.  It can also
        be set to 'P' or 'p' to fully specify that the input is the name
        of a package/procedure/function.
       
        Other FLAG options are:
          'T' or 't'        to specify that the input is the name of a type.
          'R' or 'r'        to specify that the input is the name of a trigger 
          'Q' or 'q'        to specify that the input is the name of a sequence.
          other        In case the first argument is a cursor address and 
                        hash-value, the parameter should be set to any 
                        character except 'P','p','Q','q','R','r','T' or 't'.
 
  Exceptions:
    An exception will raised if the named object cannot be found.

2013년 8월 4일 일요일

Oracle View...(오라클 뷰)

A. . 정의
- View는 하나 이상의 Table또는 다른 View에 포함된 데이터를 원하는대로 나타낸 것
- View는 내장질의또는 가상 Table등으로 표현할수 있다.
- View는 Table에서 파생되므로 둘사이에는 많은 유사성이 있다. 예를들어 Table과 같이 최대
254개의 Column이 있는 View를 정의할수 있고 뷰를 질의하고 몇가지 제한 사항을 사용하여 뷰를
갱신,삽입,삭제를 할수있다.  뷰에대해 수행되는 모든 작업은 뷰의 기본 Table에 있는 Data에
실제 영향을 주며 기본 Table의 무결성 제약조건과 트리거를 따른다.
- 뷰에는 저장영역이 할당되지 않으며 실제로 Data를 포함하지도 않는다.
B. 처리방법
- Oracle은 View를 정의하는 질의 Text를 Data Dictionary(user_views)에 저장한다,
- Oracle은 기존공유 SQL영역에 동일한 멸령이 들어있지 않을때만 새로운 공유 SQL영역에 뷰를
참조하는 명령문을 Parsing합니다. 따라서 뷰를 사용시 공유 SQL영역과 관련하여 메모리 사용이
감소하는 이익이 있다.
- Oracle은 원래 질의를 뷰정의 질의와 병합할 때 원래 뷰를 변형하여 뷰에 대한 질의에 인덱스를
사용할지를 결정한다.

Create view emp_view as
    Select emp_no, ename, sal, loc
    From emp
    Where emp.deptno = dept.deptno
    And dept.deptno = 10;

<사용자 Query>
select ename from emp_view
where empno = 9876;


select ename
from emp, dept
where emp.deptno = dept.deptno
and  dept.deptno = 10
and  emp.empno = 9876;

Oracle은 가능한 모든 경우에 뷰에대한 질의를 뷰정의 질의 및 기본뷰 질의와 병합한다. 또한 뷰를
참조하지않고 질의를 발생하는 것 처럼 병합된 질의를 최적화한다.
따라서 Column이 뷰 정의 또는 뷰에대한 사용자정의에서 참조되는지의 여부에 관계없이 모든 참조된
기본 Table의 Column에 대한 Index를 사용한다.
만약 뷰에대한 정의와 사용자 질의를 병합할수 없다면 Index를 사용하지 않을수 있다.

C. 갱신가능한 Join View
- Join View란 From절에 하나이상의 Table또는 View를 가지며, Distinct, group by, start with,
connect by, rownum, union all, intersect, for update등의 절에서는 사용하지 않는다.

- 갱신가능한 Join View는 둘이상의 기본 Table 및 View를 포함하며 Update/Insert/Delete등의
작업이 가능하다.

- Dictionary View인 all_updatable_columns,윰_updatable_columns, user_updatable_colums
에는 갱신가능한 View의 Column을 나타낸다.

- Join View에 대한 Insert/Update/Delete등의 작업은 한번에 하나의 기본 Table에서만 가능하며,
With Check Option을 사용하여 View를 정의하는 경우에는 반복된 Table의 모든 Join Column과 모
든 Column은 갱신할수 없으며, Insert명령문은 허용되지 않는다.또한 with Check Option을
사용하여 뷰를 정의하고 키예약 Table이 반복되는 경우에는 뷰에서 행을 삭제할수 없다.

D. View생성
 - Create View명령을 사용한다.
예] create view sales_staff as
      select empno, ename, deptno
      from emp
      where deptno =10
      with check option constraint sales_staff_cnst;

    위에서 check option은 뷰가 선택할수 없는 행에 대해서는 Insert와 Update명령문이
    실행되지 않는다는 제약 조건을 갖는다.
    만약 위의 View에 deptno가 30인 행을 Insert하려고 하면 RollBack되고 오류가 발
    생한다.
E. View수정하기
위에서 만든 staff View를 재정의 하는경우
create or replace view sales_staff_view as
      select empno, ename, deptno
      from emp
      where deptno =30
      with check option constraint sales_staff_cnst;
F. View의 삭제
 - drop view sales_staff_view; 

[출처] 오라클자바커뮤니티, 오엔제이프로그래밍

(오라클테이블)Oracle Table...

a. Oracle에서 Table은 Data저장 영역의 기본단위이다.
b. 선택적으로 Table의 각 Column에 규칙을 정할수 있는데 이를 Constraints(무결성제약조건)
이라고 한다.한예로 Not Null은 무결성제약조건 입니다.
c. Cluster화되지 않은 Table을 작성할때 Oracle은 Table의 향후 Data를 보관하기위해
TableSpace에 Data Segment를 자동으로 할당한다.
Data Segment에 대한 저장영역 매개변수를 설정하여 (initial, next parameter등) Data
Segment에 대한 할당된영역(extents)을 제어할수 있다.
Data Segment에 대해 pctfree와 pctused를 이용하여 Data Block의 빈영역에 대해 제어할
수도 있다.
d. 전체행을 단일 Data Block에 Insert할수 있다면 Oracle은 행을 하나의 행조각으로 저장하
나 전체행을 단일 Data Block에 Insert할수 없다면 기존 행을 갱신하여 행이 Data Block의 크기를
증가시키는 경우(Update된 Record가 이전의 Record보다 Size가 커지는 경우) Oracle은 여러 개의
행조각을 사용하여 Data를 저장한다. Oracle이 하나의 행을 두개이상의 행조각으로 저장하는 경우
Block을 통해 Chain화 되며, 체인화된 행조각은 부분의 RowID를 이용하여 서로 체인화 된다. 또한
체인화에 관계없이 각각의 행조각은 행/열 전체또는 일부에 대한 행 헤더 및 Data를 포함한다.

e. 행 헤더는 행조각,(체인화된 행조각의 경우)체인화, 행조각의 열,(Cluster인경우)클러스터
키등을 포함한다.
하나의 Block에 완전히 포함된 Cluster화 되지않은 행에는 적어도 3 Byte의 행헤더가 있으며,
행헤더 정보 다음에 열길이와 Data가 포함된다. 열 길이는 250 Byte이하를 저장하는 열의 경우
1 Byte,그이상인경우 3 Byte가 필요하며 열 Data에 선행한다.
열 Data에 필요한 영역은 Data Type에 따라 틀리며, 가변길이인 경우엔 영역은 증가또는 감소할수
있다.영역을 보존하기 위해 Null은 열길이(0)만을 저장한다. Oracle은 Null Column에 대한
Data를 저장하지 않으며 후행하는 Null의 경우 행헤더가 새로운 행의 시작을 나타내므로 열길이를
저장하지 않는다.(예를들어 Table의 마지막세개의 Column이 Null인 경우 열에 정보를 저장하지
않는다.)
또한 각각의 행은 Data Block헤더의 행 Directory에 2 Byte를 사용한다.

f. Column순서는 Table의 모든 행에 대해 동일 하다.일반적으로 열은 Create Table명령문에
나열된 순서대로 저장되지만 꼭 그렇지는 않다. 예를들어 Long Data Type의 Column이 
있는 Table을 Create하는 경우 항상 이 Column을 마지막으로 저장한다. 또한 alter table
등의 명령으로 Column을 Add하는 경우 새로운 Column을 마지막에 추가한다.
일반적으로 행이 적은 영역을 차지하도록 Null을 자주 포함하는 Column을 마지막에 두
는 것이 좋다 만약 Table이 Long Column을 포함하면 Long Column이 마지막에 위치 하
므로 이러한 이점을 살리기 힘들다.
g. ROWID는 각각의 행조각을 위치나 주소로 식별한다. 일단 행조각에 ROWID를 부여 하
면 행조각은 IMPORT 및 EXPORT Utility를 사용하여 행을 삭제할 때까지 ROWID를 보유 합니다.
행의 Cluster Key값이 변경되면 행은 유일한 ROWID를 유지하면서 새로운 값에 대한 추가
포인터 ROWID를 얻는다.

h. Null은 행의 열에 값이 없음을 나타내는데 Data값을 가진 열사이에 위치하는 경우 Null
 은 열길이(0)을 저장하는데 1 Byte가 필요함

[Table생성 예제]
create table test
(
 id  char(3)      not null,
 name varchar2(12)    null,
 addr varchar2(50)    null,
 constraint pk_test (id) primary key
 using index
 pctfree 10
 pctused 60
 storage
 (initial 100k next 100k)
 tablespace users_idx
)
storage
(initial 200k
next    200k
minextents 1
maxextents 121
pctincrease 0)
tablespace users;

2013년 8월 3일 토요일

Oracle SQL Tuning, Hint, SQL 연산(COUNT STOPKEY

SQL 연산(COUNT STOPKEY

구로디지털 오엔제이프로그래밍실무교육센터
www.onjprogramming.co.kr

COUNT STOPKEY연산은 PSEUDO COLUMNS(의사 컬럼) WHERE절에 나타날 때 실행계획에 나타나는 SQL 연산 입니다.

SQL> select  empno from emp
  2  where rownum < 2;

     EMPNO
----------
      7369

   : 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 1902391507

---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY   |        |       |       |            |          |
|   2 |   INDEX FULL SCAN| PK_EMP |     1 |     4 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------



Oracle SQL Execution Explain Plan실행계획 SQL 연산(FILTER)

SQL 연산(FILTER)

구로디지털 오엔제이프로그래밍실무교육센터


FILTER 연산은 데이터 추출 시 필터링이 일어나고 있음을 알려주는 SQL ROW 연산인데 WHERE 조건 절에서 인덱스를 사용하지 못할 때 발생하는 것입니다. NESTED LOOP 방식으로 해석할 수 있습니다.

아래의 예는 EMP TABLE에서 부서의 최소 급여를 받는 사람들을 추출하는 것입니다.

SQL> SELECT ENAME, SAL, JOB
      FROM   EMPTEST A
      WHERE  SAL = (SELECT MIN(SAL)
                      FROM   EMPTEST B
                      WHERE B.DEPTNO = A.DEPTNO);

Execution Plan
---------------------------------------------------
0       SELECT STATEMENT Optimizer=CHOOSE
1       0  FILTER
2       1     TABLE ACCESS (FULL) OF EMP
3       2     SORT (AGGREGATE)
4       3       TABLE ACCESS (BY INDEX ROWID) OF EMP
5       4         INDEX (RANGE SCAN) OF idx_emp_deptno (NON-UNIQUE) 

ㅍ[ORACLE Hint, 오라클 힌트강좌]ACCESS 경로를 변경하는 힌트(ROWID) ,오라클자바교육,오라클교육

ACCESS 경로를 변경하는 힌트(ROWID)

구로디지털 오엔제이프로그래밍실무교육센터


이 힌트 구문은 ROWID를 이용하여 테이블 스캔이 이루어 지도록 하는 것인데 간단히 예제만 보도록 하겠습니다.

ROWID 힌트를 사용하지 않은 경우 입니다.


[테스트환경]
myemp1 :  2000만건
mydept1 : 5
oracle 11g

-- 먼저 rowid를 알기 위해 데이터 select
SQL>select rowid, empno, sal from myemp1 where rownum < 10

적당한 rowid 값을 입력하여 테스트 하자.


ROWID 힌트를 사용하지 않고 실행하는 경우 index fast full 스캔을 한다.

SQL> select count(empno) from myemp1
  2  where rowid > 'AAASUvAAEAAAMarAAA'
  3    and empno > 1000;

COUNT(EMPNO)
------------
     9999000

   : 00:00:01.59

Execution Plan
---------------------------------------------------------------
|   0 | SELECT STATEMENT      |              |     1 |    17 |  5477   (2)|
|   1 |  SORT AGGREGATE       |              |     1 |    17 |            |
|*  2 |   INDEX FAST FULL SCAN| SYS_C0011302 |   499K|  8299K|  5477  

Myemp1 empno 인덱스를 이용하여 부분 스캔 후 SORT하여 데이터를 추출 한다.


이번에는 실습을 위해 rowid 힌트를 사용해 보자. 너무 느리다.


SQL> select
  2          count(empno) from myemp1
  3  where rowid > 'AAASUvAAEAAAMarAAA'
  4    and empno > 1000  ;

COUNT(EMPNO)
------------
     9999000

   : 00:00:09.93

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT             |        |     1 |    17 | 16947   (1)|
|   1 |  SORT AGGREGATE              |        |     1 |    17 |            |
|*  2 |   TABLE ACCESS BY ROWID RANGE| MYEMP1 |   499K|  8299K| 16947  


이 경우엔 EMP 테이블에서 ROWID'AAASUvAAEAAAMarAAA'보다 데이터를 찾은 empno 1000보다 데이터를 찾는 실행계획을 만들어 냅니다. 어느 방법이 나은지는 곰곰히 생각해 보세요.



[Oracle SQL Tuning]ACCESS 경로를 변경하는 힌트(HASH) - 오라클힌트 이론 실습

ACCESS 경로를 변경하는 힌트(HASH)

구로디지털 오엔제이프로그래밍실무교육센터


인자로 기술한 테이블에 대해 HASH SCAN이 일어나도록 하는 힌트이며 USE_HASH(해시 조인이 일어나도록 하는 힌트)와 구별되며 HASHKEYS parameter를 가지고 만들어진 CLUSTER내에 저장된 테이블에서만 적용 됩니다.

[형식]
/*+ HASH ( table ) */

[]
[먼저 클러스터를 생성]
CREATE CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno NUMBER(1))
HASH IS deptno HASHKEYS 150;
  

[실습 테이블을 만들면서 클러스터 저장하기 위해 옵션 정의]
   CREATE TABLE MYDEPT2 (
      deptno NUMBER(1) PRIMARY KEY,
  dname  VARCHAR2(100) NOT NULL)
   CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno);
  
  
   CREATE TABLE MYEMP2 (
          empno  NUMBER PRIMARY KEY,
         ename  VARCHAR2(100) NOT NULL,
         sal    NUMBER(9),
         deptno NUMBER(1) NOT NULL)
   CLUSTER MYEMP2_MYDEPT2_CLUSTER (deptno);




[테스트를 위한 데이터를 만듭니다.]


insert into mydept2 values (0, '인사팀');
 insert into mydept2 values (1, '회계팀');
 insert into mydept2 values (2, '영업팀');
 insert into mydept2 values (3, '기획팀');
 insert into mydept2 values (4, '교육팀');


commit;


DECLARE
          v_c NUMBER := 1;
BEGIN

          WHILE (v_c <= 10000000) LOOP
                insert into myemp2 values ( v_c, '홍길동'||v_c, mod(v_c, 5), '서울'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '다길동'||v_c, mod(v_c, 5), '부산'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '나길동'||v_c, mod(v_c, 5), '대구'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp2 values ( v_c, '나길동'||v_c, mod(v_c, 5), '광주'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
          END LOOP;
          commit;
END;



  
클러스터 인덱스 만들기 전에 일반 인덱스로 먼저 테스트 해보자.
(무지 느리자)

sQL> create index idx_myemp2_deptno on myemp2(deptno)

SQL> SELECT  /*+ index( E idx_myemp2_dept) */
  2             Count(e.ename)
  3     FROM    MYEMP2 E, MYDEPT2 D
  4     WHERE   D.deptno = E.deptno;

COUNT(E.ENAME)
--------------
      10000000

   : 00:01:15.29

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     3   (0)|
|   1 |  SORT AGGREGATE        |              |     1 |    26 |            |
|   2 |   NESTED LOOPS         |              |     1 |    26 |     3   (0)|
|   3 |    INDEX FAST FULL SCAN| SYS_C0011304 |     1 |    13 |     2  
|*  4 |    TABLE ACCESS HASH   | MYEMP2       |  2050K|    25M|     1  




이번엔 HASH SCAN 위한 힌트를 사용해 보자.
조금 빨라졌다.

SQL> SELECT 
  2             count(E.ename)
  3     FROM    MYEMP2 E, MYDEPT2 D
  4     WHERE   D.deptno = E.deptno;

COUNT(E.ENAME)
--------------
      10000000

   : 00:01:01.54

Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     3   (0)|
|   1 |  SORT AGGREGATE        |              |     1 |    26 |            |
|   2 |   NESTED LOOPS         |              |     1 |    26 |     3   (0)|
|   3 |    INDEX FAST FULL SCAN| SYS_C0011304 |     1 |    13 |     2  
|*  4 |    TABLE ACCESS HASH   | MYEMP2       |  2050K|    25M|     1  



Oracle 11g에서 테스트 했을 때 위의 경우 NESTEDD LOOP로 풀리며 또는 힌트를 사용하지 않더라도 EMP TABLE HASH SCAN을 하는 것으로 나타났습니다.

CLUSTER를 확인 할 수 있는 VIEW는 다음과 같구요,

DBA_CLUSTERS         ALL_CLUSTERS         USER_CLUSTERS

아래에 간단한 HASH CLUSTER TABLE에 대한 설명이 있으니 참고 하세요~

다량의 범위를 자주 엑세스해야 하는 경우나 인덱스를 사용한 처리가 부담이 되는 범위(넓은 분포도), 수정이 자주 발생하지 않는 Column, 대규모 테이블, 여러 개의 테이블이 빈번한 조인을 일으킬 때 CLUSTER INDEX를 사용하시면 되는데 HASH CLUSTER에 테이블을 저장하는 것은 데이타 검색의 성능을 향상하기 위한 선택적인 방법 입니다.

Hash Cluster는 인덱스나 인덱스 Cluster를 가지는 Cluster되지 않은 테이블의 대용이며 인덱스 테이블, 인덱스 Cluster와 함께 오라클은 별도의 인덱스에 저장된 키값을 사용하는 테이블 내의 로우(row)에 위치 합니다.

또한 오라클은 물리적으로 Hash Cluster내의 테이블의 로우에 저장하고 Hash function의 결과에 의하여 검색 하는데 특정 Cluster 키값을 바탕으로 Hash Values라 불리는 분산된 수치 값을 생성하는 Hash Function을 사용 한다