Thread workHard = new Thread()
{ //익명 클래스 기법
  public void run()
  {
        doToughWork(); //이벤트처리및 페인팅 작업등.. 우선 처리 해야할 작업들 (1스레드 임으로 blocking)

        SwingUtilities.invokeLater(new Runnable()
        {
            //메서드의 매개변수로 객체를 생성해서 넘길때도 익명클래스 기법으로 재정의 가능
            public void run()
            {
                updateConponents(); //컴포넌트의 프로퍼티등 상태 수정.. 등의.. 가벼운 작업..
             }
         };
   }
};

workHard.start(); 

=>음..뭐랄까.. 일단 스레드간 병목현상을 없애기 위해서.. 가장 시간이 많이 소요되는 작업을 우선 처리한 후
   그 작업 스레드에서 새로운 스레드를 생성해 다음 작업을 처리시킴... 
   =>서버 소켓의 accept() 후  클라에 대한 i/o용 작업 스레드를 생성해서 start() 시킨것과 같음.

음.. 멀티스레드에서 병목현상이 있다면.. 전에 남궁성선생님 책에서 yield()인가를 쓰면 된다고 했었는데...
아.. yield()는 병목현상이 아니라.. 유휴시간이었던가... 글고 또 다른 방법이 생각났었는데.. 그새 까묵....OTL

하여튼.. 스레드간 순차적인 처리를 하게 한다.

*************************************************************8

음.. 사용자가 스레드 작업을 멈출수 있게.. doToughWork();를 구현

public void doToughWork()
{
  try
  {
      //작업 종료시(모든 객체를 반복해가며 while(){for(객체갯수){doUpdat(); doPaint();}})로 while의 종료조건
      //을 구성하지 말고!  while 업무 종료조건을.. 예전에 nio 헀을당시 스레드 처리 방식처럼..
      
      while(true) //예전 nio땐 클라측 스트림 객체가 not null인 동안
        for(처리할 객체의 갯수만큼)
        {
           if(Thread.interrupted() ) //현재 스레드가 인터럽트 상태인가? 
           {
              throw new IntterruptedException(); <-- 익셉션 발생을 통한 반복문 제어 처리
           }
            객체.update();
            객체.draw();
         }
       Thread.wait(1000); //현재 스레드가 한타임 뛰었으니 1초 휴식 -_-;
  }
  catch(IntterruptedException e)
  {
      //스레드 인터럽트를 알리고
      //객체들 상태가 변화했으면 
      // invokerLater를 호출한다.
   }
}

사용자용 Jbutton의 리스너에

actionPerform(Event e) 인가 에서
{
   workHard.interrrupt(); 를 해주면..
}


(추가)

스윙..컴포넌트 기반의 GUI.. 추후 자바스크립트중 프론트 영역의 MVC처리 , 안드로이드 에서.. 조립및 재사용 단위에

있어서 도움이 되었다.

'자바se api > swing' 카테고리의 다른 글

스윙..  (0) 2014.01.02
이벤트처리 스레드;;  (0) 2014.01.02
propertyEditor vs ConversionService + 토비의 스프링?  (0) 2014.01.02
자바 스윙 겁나 복잡하고 방대함...  (0) 2014.01.02
by givingsheart 2014. 1. 2. 09:28
스윙책에서 이벤트처리 스레드를 강조했기에 (java.awt.EventDispatchThread)

이번 기회에 분석하자 해서 봤더만... 머리아픔..

63 class More ...EventDispatchThread extends Thread {
64 
65     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
66 
67     private EventQueue theQueue; // 이벤트큐 구현 코드는 제일 아래쪽에 (자기=스레드가 처리할 작업거리를 필드로
                                                         갖고있다..
68     private boolean doDispatch = true;
69     private boolean threadDeathCaught = false;
70 
71     private static final int ANY_EVENT = -1;
72 
73     private Vector<EventFilter> eventFilters = new Vector<EventFilter>();//체인오브 리스폰스빌리티처럼,.. 필터개념
//으로 이벤트 검사
74 
75     More ...EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
76         super(group, name);
77         setEventQueue(queue); //aggregation.. 내 경운 전에 worker와 work를 association으로 해서 worker.setWork(work)
78     }
79 
80     /*
81      * Must be called on EDT only, that's why no synchronization
82      */
83     public void More ...stopDispatching() {
84         doDispatch = false;
85     }
86 
//아래가 기본 동작 run()
87     public void More ...run() {
88         while (true) {
89             try {
90                 pumpEvents(new Conditional() {
91                     public boolean More ...evaluate() {
92                         return true;
93                     }
94                 });
95             } finally { //리턴을 해도 finally는 무조건 실행됨.(내가 전에 이것땜에 당황했었음)
96                 EventQueue eq = getEventQueue();
//아래는 run의 while(true) 종료 조건임 이게 finally구문 안에 있는것을 이해할것!
97                 if (eq.detachDispatchThread(this) || threadDeathCaught) {
98                     break;
99                 }
100            }
101        }
102    }
103
104    void More ...pumpEvents(Conditional cond) {
105        pumpEvents(ANY_EVENT, cond);
106    }
107
108    void More ...pumpEventsForHierarchy(Conditional cond, Component modalComponent) {
109        pumpEventsForHierarchy(ANY_EVENT, cond, modalComponent);
110    }
111
112    void More ...pumpEvents(int id, Conditional cond) {
113        pumpEventsForHierarchy(id, cond, null);
114    }
115
116    void More ...pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {
117        pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));
118    }
119
120    void More ...pumpEventsForFilter(Conditional cond, EventFilter filter) {
121        pumpEventsForFilter(ANY_EVENT, cond, filter);
122    }



166    boolean More ...pumpOneEventForFilters(int id) {
167        AWTEvent event = null;
168        boolean eventOK = false;
169        try {
170            EventQueue eq = null;
171            EventQueueDelegate.Delegate delegate = null;
172            do {
173                // EventQueue may change during the dispatching
174                eq = getEventQueue();

//아래는 getDelegate() 메서드에서 뭘하는지 확인 필요..(AppContext는 프로그램을 의미하는 전역
//객체라 생각하는게 편할듯)
//프로그램별로 이벤트 처리 담당하는 녀석들이 set에 들어있나봄.. swing의 컴포넌트들도 그렇던데..
39    public static Delegate More ...getDelegate() {
40        return
41          (Delegate) AppContext.getAppContext().get(EVENT_QUEUE_DELEGATE_KEY);
42    }
175                delegate = EventQueueDelegate.getDelegate();
176
//이벤트 처리할 delegate를 얻었으니.. 큐에서 이벤트 꺼내오기.
177                if (delegate != null && id == ANY_EVENT) {
178                    event = delegate.getNextEvent(eq);
179                } else {
180                    event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
181                }
182
//아래 로직을 보니.. eventOK = false; 코드가 눈에 띄는데.. 여러 필터단에서 해당 이벤트가 
//처리할 이벤트인지를 검증하는듯..
183                eventOK = true;
184                synchronized (eventFilters) {
185                    for (int i = eventFilters.size() - 1; i >= 0; i--) {
186                        EventFilter f = eventFilters.get(i);
187                        EventFilter.FilterAction accept = f.acceptEvent(event);
188                        if (accept == EventFilter.FilterAction.REJECT) {
189                            eventOK = false;
190                            break;
191                        } else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {
192                            break;
193                        }
194                    }
195                }
//필터로도 부족해서 다른 메서드를 통해 이벤트인지를 확인
196                eventOK = eventOK && SunDragSourceContextPeer.checkEvent(event);
197                if (!eventOK) {
198                    event.consume(); //말그대로.. 이벤트를 처리한달까? 소모시키기.. 아래처럼 구현
418    protected void More ...consume() {
419        switch(id) {
420          case KeyEvent.KEY_PRESSED:
421          case KeyEvent.KEY_RELEASED:
422          case MouseEvent.MOUSE_PRESSED:
423          case MouseEvent.MOUSE_RELEASED:
424          case MouseEvent.MOUSE_MOVED:
425          case MouseEvent.MOUSE_DRAGGED:
426          case MouseEvent.MOUSE_ENTERED:
427          case MouseEvent.MOUSE_EXITED:
428          case MouseEvent.MOUSE_WHEEL:
429          case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
430          case InputMethodEvent.CARET_POSITION_CHANGED:
431              consumed = true;
432              break;
433          default:
434              // event type cannot be consumed
435        }
436    }

199                }
200            }

//처리할 이벤트가 아니면.. 무한루프 돌면서 시간 때우기.. (물론 스레드임으로 인터럽트 발생하면 
//다른 스레드에게 실행권 넘어감. 
201            while (eventOK == false);
202
203            if (eventLog.isLoggable(PlatformLogger.FINEST)) {
204                eventLog.finest("Dispatching: " + event);
205            }
206
//아래 부분이 핵심인듯 한데.. 이해가 안됨.. 저 메서드들도 숨어있고..
207            Object handle = null;
208            if (delegate != null) {
209                handle = delegate.beforeDispatch(event);
210            }
211            eq.dispatchEvent(event);
212            if (delegate != null) {
213                delegate.afterDispatch(event, handle);
214            }
215
216            return true;
217        }
218        catch (ThreadDeath death) {
219            threadDeathCaught = true;
220            return false;
221
222        }
223        catch (InterruptedException interruptedException) { //프로그램 내의 모든 스레드를 회수 = 프로그램 종료
224            return false; // AppContext.dispose() interrupts all
225                          // Threads in the AppContext
226
227        }
228        catch (Throwable e) {
229            processException(e);
230        }
231
232        return true;
233    }


**************************************************************


235    private void More ...processException(Throwable e) {
236        if (eventLog.isLoggable(PlatformLogger.FINE)) {
237            eventLog.fine("Processing exception: " + e);
238        }
239        getUncaughtExceptionHandler().uncaughtException(this, e); //분석하고 싶은데 메서드 못찾겠음..
240    }




***************************************************************


//우선순위큐로 이벤트들을 모아놓고, 스레드 세이프하게 fifo방식으로 처리
101 public class More ...EventQueue {
102 
103     // From Thread.java
104     private static int threadInitNumber;
105     private static synchronized int More ...nextThreadNum() {
106         return threadInitNumber++;
107     }
108 
109     private static final int LOW_PRIORITY = 0;
110     private static final int NORM_PRIORITY = 1;
111     private static final int HIGH_PRIORITY = 2;
112     private static final int ULTIMATE_PRIORITY = 3;
113 
114     private static final int NUM_PRIORITIES = ULTIMATE_PRIORITY + 1;
115 
116     /*
117      * We maintain one Queue for each priority that the EventQueue supports.
118      * That is, the EventQueue object is actually implemented as
119      * NUM_PRIORITIES queues and all Events on a particular internal Queue
120      * have identical priority. Events are pulled off the EventQueue starting
121      * with the Queue of highest priority. We progress in decreasing order
122      * across all Queues.
123      */
124     private Queue[] queues = new Queue[NUM_PRIORITIES]; //스레드 우선순위별로 관리하는듯
125 
126     /*
127      * The next EventQueue on the stack, or null if this EventQueue is
128      * on the top of the stack.  If nextQueue is non-null, requests to post
129      * an event are forwarded to nextQueue.
130      */
131     private EventQueue nextQueue; //자신을 가리켜? 뭐지?? 연결리스트인가? 이벤트큐 연결 리스트 자료구조?
132 
133     /*
134      * The previous EventQueue on the stack, or null if this is the
135      * "base" EventQueue.
136      */
137     private EventQueue previousQueue; //이전을?? 
138 
139     /*
140      * A single lock to synchronize the push()/pop() and related operations with
141      * all the EventQueues from the AppContext. Synchronization on any particular
142      * event queue(s) is not enough: we should lock the whole stack.
143      */
144     private final Lock pushPopLock; //스레드 세이프 (동시에 pop 불가 = 하나의 이벤트당 하나의 스레드)
145     private final Condition pushPopCond;
146 
147     /*
148      * Dummy runnable to wake up EDT from getNextEvent() after
149      push/pop is performed
150      */
151     private final static Runnable dummyRunnable = new Runnable() {
152         public void More ...run() {
153         }
154     };

생략..



*****************************************************************8


249    private static class More ...HierarchyEventFilter implements EventFilter {
250        private Component modalComponent;
251        public More ...HierarchyEventFilter(Component modalComponent) {
252            this.modalComponent = modalComponent;
253        }
254        public FilterAction More ...acceptEvent(AWTEvent event) {
255            if (modalComponent != null) {
256                int eventID = event.getID();
257                boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&
258                                     (eventID <= MouseEvent.MOUSE_LAST);
259                boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&
260                                      (eventID <= ActionEvent.ACTION_LAST);
261                boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);
262                /*
263                 * filter out MouseEvent and ActionEvent that's outside
264                 * the modalComponent hierarchy.
265                 * KeyEvent is handled by using enqueueKeyEvent
266                 * in Dialog.show
267                 */
268                if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {
269                    /*
270                     * Modal internal frames are handled separately. If event is
271                     * for some component from another heavyweight than modalComp,
272                     * it is accepted. If heavyweight is the same - we still accept
273                     * event and perform further filtering in LightweightDispatcher
274                     */
275                    return windowClosingEvent ? FilterAction.REJECT : FilterAction.ACCEPT;
276                }
277                if (mouseEvent || actionEvent || windowClosingEvent) {
278                    Object o = event.getSource();
279                    if (o instanceof sun.awt.ModalExclude) {
280                        // Exclude this object from modality and
281                        // continue to pump it's events.
282                        return FilterAction.ACCEPT;
283                    } else if (o instanceof Component) {
284                        Component c = (Component) o;
285                        // 5.0u3 modal exclusion
286                        boolean modalExcluded = false;
287                        if (modalComponent instanceof Container) {
288                            while (c != modalComponent && c != null) {
289                                if ((c instanceof Window) &&
290                                    (sun.awt.SunToolkit.isModalExcluded((Window)c))) {
291                                    // Exclude this window and all its children from
292                                    //  modality and continue to pump it's events.
293                                    modalExcluded = true;
294                                    break;
295                                }
296                                c = c.getParent();
297                            }
298                        }
299                        if (!modalExcluded && (c != modalComponent)) {
300                            return FilterAction.REJECT;
301                        }
302                    }
303                }
304            }
305            return FilterAction.ACCEPT;
306        }
307    }


by givingsheart 2014. 1. 2. 09:27


1.db드라이버님께 커넥션 얻기
2.커넥션님으로부터 쿼리객체 얻기
3.쿼리에 세팅
4.쿼리 발송
5.(blocking)리절트셋 얻기 or 익셉션
6.감사한 마음으로 리절트셋님, 쿼리 객체님 , 커넥션 객체님 bye
7.내 app에서 편하게 쓸라면
List<object[]> records=new ArrayList<object[]>();
while(resultSet.next())
{    
int cols = resultSet.getMetaData().getColumnCount(); <--metadata가 포인트!(패킷다루기
 ) 예전에.. 전체 집합에서 특정 조건에 해당하는 집합을 리턴하는 메서드를 만들때.. 방법이 1.조건
에 맞는 집합의 크기를 센후, 리턴할 집합을 할당후, 다시 전체를 조회하면서 리턴할 집합에 값을
넣기, vs 2.내가 1이 신경질나서 연결리스트로 리턴할 집합을 할당후.. 걍 추가.. (당근 성능 떨어
짐.)  vs 3.위의 방법 처럼 메타 데이터 사용!  vs 4.db 내장 프로시저를 사용.. ex) select
count(column_pk) from tableName 해서 레코드의 수를 알아내고 그만큼 할당.. 퍼포먼스는
어떤지 모르겠음.
    Object[] arr = new Object[cols];
    for(int i=0; i<cols; i++){
      arr[i] = resultSet.getObject(i+1);
    }    
records.add(arr);
}

8.로우(레코드=인스턴스=Object[]) 단위로 쉽게 관리가 가능

9.감사한 마음으로 종료 bye





by givingsheart 2014. 1. 2. 09:26
by givingsheart 2014. 1. 2. 09:25


툴작업중 내 서브프레임들 (dbinfo, ddl, dml, dql, console만 빼고) 각각이 사용자가 입력한 문자열들을 save/load 지원을 
해줘서 xml파일로 관리하기로 마음먹고.. 지난번에 작업해둔.. property.loadFromXml인가를 사용하려 하다가.. 

propertyEditor라는 것을 접하게 되었고 검색을 해보았다. 이번 작업도.. 스프링과 매치되는 부분이 있다니..
황당할 따름이다. 툴 작업이라.. 스레드에 전혀 관심을 안두었던 내게.. 약간의 찜찜함을 남겨준다.

property를 이용해 xml로 쏘고 읽는건 해봤으니.. 약점이 있더라도 propertyEditor를 적용해봐야겠다.

구글에서 propertyeditor sample or example 로 검색을 해봐야겠다. 아..서점도 가야하는데..

스프링 jre 다운 받기


(토비라는 유명한 분 블로그인듯)


Example 10.6: The YesNoDialogAlignmentEditor Class

package oreilly.beans.yesno;
import java.beans.*;
import java.awt.*;

public class YesNoDialogAlignmentEditor extends PropertyEditorSupport 
{  
// These two methods allow the property to be edited in a dropdown list.  
// Return the list of value names for the enumerated type.  

public String[] getTags() 
{    
return new String[] { "left", "center", "right" };  
}  
// Convert each of those value names into the actual value.  

public void setAsText(String s) 
{    
if (s.equals("left")) setValue(new Integer(YesNoDialog.LEFT));    
else if (s.equals("center")) setValue(new Integer(YesNoDialog.CENTER));    
else if (s.equals("right")) setValue(new Integer(YesNoDialog.RIGHT));    
else throw new IllegalArgumentException(s);  
}  
// This is an important method for code generation.  

public String getJavaInitializationString() 
{    
switch(((Number)getValue()).intValue()) 
{    
default:    
case YesNoDialog.LEFT:   return "oreilly.beans.yesno.YesNoDialog.LEFT";    
case YesNoDialog.CENTER: return "oreilly.beans.yesno.YesNoDialog.CENTER";    
case YesNoDialog.RIGHT:  return "oreilly.beans.yesno.YesNoDialog.RIGHT";    }  
}

}

위를를 보니 어떻게 써야할지.. 약간 감은 잡겠다
클래스 PropertyEditorSupport 그중.. 내가 써봐야 할것은.. 아래 메서드 이리라..

PropertyEditor 는, 프로퍼티치를 편집하는 완전한 커스텀 컴퍼넌트를 제공할 수가 있습니다. PropertyEditor 는, 에디터의 컴퍼넌트와 제휴해, PropertyChange 이벤트를 트리거해 프로퍼티치의 변경을 통지합니다.

getCustomEditor 를 호출하는 고레벨인 코드에서는, 컴퍼넌트를 보다 큰 프로퍼티 시트에 짜넣거나 독자적인 다이얼로그에 배치하거나 할 수가 있습니다.


정의:
인터페이스 PropertyEditor 내의 getCustomEditor


반환값:
사용자가 현재의 프로퍼티치를 직접 편집할 수 있도록(듯이) 한다 java.awt.Component. 지원되지 않는 경우는 null



'자바se api > swing' 카테고리의 다른 글

스윙..  (0) 2014.01.02
스윙의 기본적인 멀티스레드 처리방식  (0) 2014.01.02
이벤트처리 스레드;;  (0) 2014.01.02
자바 스윙 겁나 복잡하고 방대함...  (0) 2014.01.02
by givingsheart 2014. 1. 2. 09:24

자바 병렬프로그래밍

http://book.naver.com/bookdb/book_detail.nhn?bid=4683550


이펙티브 자바


클린 코드



swing 도 공부할게 많은데..



디비,스프링,네트웍... 두껀 교재를 산다해도 공부는 못할듯...

ps. 자바에 대한 깊이 있는 통찰

ps2. 개별적으로 내 블로그를 만들어서 관리해야겠다.
게시판을 이용하니.. 자료나, 공부했던것을 카테고리 별로.. 정리에 한계를 느낀다.

아래 형식의 블로그 처럼 만들고 싶다.


by givingsheart 2014. 1. 2. 09:23

간단하게 swing으로 구현? 이 말이 부끄러워진다..


예전에 간단하게 awt gui 기반에서 text 필드에 사용자가 디비 드라이버 정보, 접속url, id,pw 등을 입력하고 버튼을 
누르면, 모든 컴포넌트의 값을 읽어와 루트element에 setproperty 하는 형식으로 값들을 넣고.. 그걸 documnet에 넣어서
dbinfo.xml로 출력해주는 간단한 코드였다.

사실 awt의 기능들을 충분히 사용해보지 않은 상태로(예전엔 awt 클래스들을 디자인 패턴의 관점에서 분석만 했었고..)

현재 제대로 된 dbConnect정보,ddl,dml,dql 을 사용자가 입력하고, 실제 db와 연동시키려는 툴을 만들기 위해
툴의 디자인을 고민했었다. 

1.처음의 기본 디자인은.. 각각의 입력(커넥션,ddl,dml,dql) 페이지를 JPanel로 구분해서.. 메인 툴 프레임에 
예전에 했던대로 gridLayout을 설정해 위에서부터 순서대로 판넬을 포함 시키는 방법. add(component)

(여기서 문제가 발생. 메인 프레임이 800,800 사이즈라.. 각각의 서브 판넬이 800,200 식으로 나눠 가졌으나.. 
개별적 작업 공간이 크기도 부족했을 뿐더러.. 작업 공간이 섞여있어서 직관적이지 못했다.)

2.두번째 디자인은 메인 툴 프레임에  <-  -> 버튼을 추가해서 해당 페이지로 이동하고 작업하는 방식이었다.

첫번째 문제가 현재 겹쳐있는(위치값 동일) 패널에 대해 ->버튼을 클릭시 위치를 이동시켜서 화면 밖으로 
빼고, 다음 패널이 사용자의 입력을 받을 수 있게끔 하는 것이었는데.. 포커스 문제,위치 이동과 복귀등 생각보다 
복잡했다.(물론 시간 투자해 억지로 매달리면 구현은 가능했을테지만..)

두번째 문제가 툴 사용자가 실제 db정보를 입력하고 그것이 제대로 작동하는지 피드백을 받아볼 필요가 있었고
ex) "127.0.0.1 oracal xxx 에 접속 성공"  "create memberInfo( id number(3), name vchar2(20), address ...)
memberInfo 테이블 생성 성공"  "selete * memberInfo 성공" "결과 001,가길동,강북  002,나길동,강남" ...

이 처리를 위해서 이클립스의 콘솔창의 개념이 필요했다. (현재까지 총 5개의 구분되는 컨테이너 컴포넌트=판넬 필요)
+ 콘솔용 판넬은 db커넥션 정보 입력용 패널, ddl 입력용 패널, dml 입력용, dql 입력용 패널에서 공유되어야할 필요가
있었다.

3.그 다음 디자인이.. 메인 프레임 안에.. 각각 독립적인 정보입력용 프레임 4개 + 결과 출력용 프레임 1개를 넣는 방식
이었다. mainFrame.add(new MyFrame("ddl")); 요런 식으로.. (물론... 실행을 시키면 프로그램 창(프레임)이 2개나 
띄워졌지만.. 뻑=익셉션이났다.. 디버깅을 안해서 정확한 이유는 모른다. OTL)

나는 여전히 3번 방식이 객체 지향적이며 무엇보다 내가 원했던.. 사용자가 작업을 하면서 명확해질수 있게끔 돕는 것이
라 생각해.. 이 아이디어를 포기 할수 없었다. 그렇기에 정보를 찾아봤다.

4.LayerdPane 개념 습득. 
swing에 관하여 조금 더 인터넷 서치를 하던중..(내실 없이 아주 거지같은 광고용 블로그에도 당하고.. 욕나옴 -_-;)
알게된 개념으로서.. 아주 오래전 2d 슈팅or액션 게임 만들던때 사용하던 2d화면에 배경별(멀고,가깝고),오브젝트별,캐릭터별 
층을 구분하고 아래부터 먼저 draw 해주는 개념이었다. 

이걸 이용한다면.. 콘솔창의 문제를 제외하곤 애초에 생각했던 2번문제.. <- -> 버튼으로 작업공간 이동이 쉽게 풀릴듯 하여.. 작업을 시작하려 하였으나..

5.Intenal(내부)Frame 개념 습득..
요 클래스가 내가 3번에서 뻑이 났던.. 문제를 해결해주는 개념이었다.. (나처럼 메인 프레임 안에.. 독립적인 프레임을
만들길 원하는 수요가 있어서 java가 만들어 줬나보다. 

멋도 모르고 JFrame을 상속받은 내 메인 프레임에 ddl = new JInternalFrame(); mainFrame.add(ddl); 
요런식으로 해봤더니.. 원하던대로.. 뻑도 안나고 내부의 독립적인 프레임이 생성이 되었다. (이때의 감동이란 ㅠㅠ)

6.샘플 소스코드 입수
... 그렇다.. 이미 java의 고급 개발자들이 우리에게 은혜를 베푸시어.. core api 외에도 샘플 소스코드를
만들어주셨는데.. 왜 이생각을 못했을까? (예전에 한번, 콘솔용 겁나 복잡해진 사용자 컨트롤 처리 로또 프로젝트를 실패
하고, 하루만에 접은 gui 기반 동물 농장 프로젝트를 통해.. "다음에는 샘플 코드부터 작업을 시작하자고 생각했었는데.."

채팅이나, nio 채팅의 경우도.. 거의 맨땅에서 작업하느라 효율이 안좋았는데.. 왜 그랬을까?.. 왜그랬을까..?

에서.. internalFrame 샘플 코드를 받아본 나는.. 다시 한번 새로운 충격에 빠졌다..


7.방황하는 시간..

아래처럼 구현하는 것이.. 스윙 패키지의 기능을 90% 이상 뽑아내는 것이리라..
(내가 구현했던 것들이.. 아주 먼지처럼 느껴졌다.. 내가 한건.. gui 패키지 사용의 겉핥기..)

import javax.swing.JInternalFrame;
import javax.swing.JDesktopPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JFrame;
import javax.swing.KeyStroke;

import java.awt.event.*;
import java.awt.*;

/*
 * InternalFrameDemo.java requires:
 *   MyInternalFrame.java
 */
public class InternalFrameDemo extends JFrame
                               implements ActionListener {
    //내경우 JFrame을 상속받아.. add 처리만 하려 했는데.. 아래의 JDesktopPane 이란 관리용 클래스...
    //내가 구현하려던 mainFrame 클래스는 각각의 서브 프레임(db입력용,dml,ddl,dql,콘솔창용)에 대해
    //중앙 컨트롤(사용자의 개별적 입력 이벤트를 전달받아.. 처리후 각각의 서브 프레임에게 명령 전달 하는 
    //메디에이터 클래스의 개념.. ) 한마디로 씬or 페이지 매니저를 만들려고 했었는데.. 이미 만들어져 있었다.
    //즉.. 메인 프레임에서 컨테이너 관리적인 측면을 또 다른 객체에게 위임한 상태..
    //글고 중요한건 아니지만.. 내경운 지금까지 해당 컴포넌트에 대한 리스너를 component.addXXListerner( new
    // xxxAdapter(){익명 클래스 기법으로 재정의}; ) 식으로 처리했는데.. 위처럼 implements를 시키는 것에 대해
    // 고민이 필요할듯 하다.
/*
<명세>

멀티 문서 인터페이스 또는 가상 데스크탑을 생성하는 컨테이너입니다. JInternalFrame 객체를 생성해,JDesktopPane 에 추가합니다. JDesktopPane  JLayeredPane 를 확장해, 오버랩의 가능성이 있는 내부 프레임을 관리합니다. 또, 현재의 Look & Feel (L&F)에 대해서 UI 클래스에서 설정된 DesktopManager 의 인스턴스에의 참조도 유지합니다. JDesktopPane 는 경계를 지원하지 않습니다.  

이 클래스는 일반적으로,JInternalFrames 의 부모로서 사용되어 플러그 인 가능한 DesktopManager 객체를JInternalFrames 에 제공합니다. L&F 별로 구현되는 installUI 로,desktopManager 변수의 적절한 설정을 실시합니다. JInternalFrame 의 부모가 JDesktopPane 의 경우, 클로즈나 사이즈 변경등의 동작의 대부분을 desktopManager에 위양 합니다.  

상세와 사용예에 대해서는, 「The Java Tutorial」의「How to Use Internal Framesy」를 참조해 주세요.  

*/

    JDesktopPane desktop; //요것을 멤버 필드로 보관하는 이유는 좀 있다가..

    public InternalFrameDemo() {
        super("InternalFrameDemo");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 50;
       //내경운 일단 빠른 구현을 위해서 setSize인가로 800,600을 떄려 넣었다. 아래가 정석이다.ㅠㅠ
       //툴킷의 경운 .. 사용자의 native한 gui 데스크탑 환경이라 생각하면 된다.(os)
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        //메인프레임을 클래스 멤버필드로 관리하기에.. 아래처럼 서브프레임을 만드는 행위를 메서드로 뺄수 있게 되었다.
        //서브프레임을 동적으로 넣었다, 뺐다 할수 있다.  미리 고정된 .. mainFrame.add(subFrame1); ... 요럴 필요가 없음.
        //생성하려는 서브 프레임이 동일하다면.. 아래처럼 쓰면 될테고.. dml,dql,,ddl,console,dbinfo처럼 제각각 특징이 
        //있다면 상속받아서.. 다형성을 이용해야 한다.
        createFrame(); //create first "window" 
        
        //메디에이터? 관리용 객체(JDesktopPane)을 만들었으니 메인 Frame에 세팅하는 작업이 필요.
        setContentPane(desktop);
        //아래의 경운.. 내가 만들툴의 디자인상 각각의 서브 프레임이 사용자의 입력 데이터를 개별적으로 save/load
        //하는데 사용이 가능할듯. JMenuBar crateMenuBar()로서 메서드 단위로 개념을 분리시켰다.
        setJMenuBar(createMenuBar());

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
    }

    protected JMenuBar createMenuBar() {
        //이처럼 모듈별로 쪼개는것은 중요하다. 내가 구상한 디자인 경우에도.. ddl 프레임에서 setColumn() 이란 메서드로서
       // 반복적이고 몇개가 될지 모르는 테이블의 컬럼 정의를 메서드로 추출하려 했었으니까..
       //ex)사용자가 테이블에 대해 하나의 컬럼 정의를 완료하고 add 버튼을 누르면 다음 컬럼 정의할수 있고
       //또는 delete를 누르면 이미 정의된 컬럼 날아가고.. confirm 누르면 확정되어 데이터를 실제로 조립하고...
        JMenuBar menuBar = new JMenuBar();

        //Set up the lone menu.
        //정말..멋진 디자인이다. 메뉴바 객체에 메뉴들을 추가한다.. 컨테이너의 개념...
        JMenu menu = new JMenu("Document");
        
       //놀라울 따름이다.. 해당 메뉴객체에 키보드 alt+D 이벤트를 연결하는 작업이 이처럼 간단하다.
        menu.setMnemonic(KeyEvent.VK_D);
        menuBar.add(menu);

        //Set up the first menu item.
        //마찬가지이다. 하나의 메뉴객체는 또한 내부에 이것 저것 아이템을 가지고 있을테니.. 나는 정말로
        //자바가 제공하는 gui 프레임 워크를 1%도 이해를 못하고선.. 혼자서 대충 만들수 있다느니..하고 자만했다.
        //얼마나 직관적이고 일관성있는 인터페이스 인가?
        JMenuItem menuItem = new JMenuItem("New");
        menuItem.setMnemonic(KeyEvent.VK_N);
        //일반적인 키 이벤트야 비트마스크로 추출하는건 알고 있으니 넘어가고..
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_N, ActionEvent.ALT_MASK));

        //아래의 menuItem.setActionCommand("new"); menuItem.addActionListener(this);... 화룡점정이다.
        //내가 만들던 파일매니저의 서브시스템중 워커 팩토리를 구현할때 다형적인 워커와 클래스를 해쉬맵으로 
        //key,value로 묶어서 문자열로 매핑한 것을 상기하자.  

/* 리마인드용 내가 구현했던 코드 조각
workerMap = new HashMap<String,Class<?>>();
Properties pro = new Properties();
//TODO:경로까지 지정을 할까;;
pro.loadFromXML(new FileInputStream("worker.xml"));
for(Entry<Object,Object> entry : pro.entrySet())
{
try
{
workerMap.put((String)entry.getKey(), Class.forName((String)entry.getValue()));
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}


public FileWorkerImpl getWorker(String workerName)
{
assert workerName != null : "workerName 뷁:" + workerName;
assert !" ".equals(workerName): "workerName 뷁:" + workerName;
FileWorkerImpl worker = null;
try
{
worker = (FileWorkerImpl)workerMap.get(workerName).newInstance();
}
catch (InstantiationException | IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return worker;
}
*/
        //다시 생각해봐도 정말 아름다운 디자인으로, 커맨드 패턴 + 옵저버 패턴(이벤트 디스패처+리스너)의 멋진 활용
        //내가 전에 최고 수준의 코딩 기법을 따라하고 싶다고 노래를 불렀었는데.. 자바 샘플 소스중.. swing 포함 gui
        //부분.. 정말로 멋지다. 내가 아래처럼 설계하고 구현할수 있게끔 훈련된다면 얼마나 좋을까 ㅠㅠ 샘플 소스 코드
        //매일 하나씩 분석해야겠다.
        menuItem.setActionCommand("new");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        //Set up the second menu item.
        //중복 됨으로 분석 생략
        menuItem = new JMenuItem("Quit");
        menuItem.setMnemonic(KeyEvent.VK_Q);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_Q, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("quit");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        //메뉴바 란.. 하나의 프레임 속에선 서브 컴퍼넌트이지만.. 그 자신도 내부에 메뉴들과 그에 속한 아이템들을
        //갖는 객체.. 이 메뉴바란 객체를 구성하는걸 메서드 단위로 뺀 모듈화.. 배워야한다..ㅠㅠ 
        return menuBar;
    }

    //React to menu selections.
    //위에서 작업해준.. 액션이벤트란 커맨드를 문자열로 매핑하고, 액션 리스너 클래스의 actionPerformed() 메서드를
    //재정의 하여.. 아래처럼 간단하게 구현이 가능하다. 명령에 따른 처리를 메서드 단위로 추출한 것도 포인트.
    //사실.. 아래의 작업을 더 추상화하면.. 내가 파일시스템에 구현했듯.. 팩토리 + 워커를 상속계층으로 만들어
    //동일한 인터페이스인 work()로서 추상화하면.. 더 간단해진다. 
    //ex) Worker worker =  workerFactory.getInstance().getWorker("copy");
    //      Work work = workFactory.getInstance().getWork("file", srcPath, destPath);
    //      worker.setWork(work);  한마디로.. 디자인 패턴에 빠져.. 워커도 추상화, 워크도 다형적으로 추상화 해버렸다..
    //      worker.work();
    // 근데 실제로 위처럼 구현하게 되면.. 코드는 이뻐지지만, 명시적이지 않다. 예전에 코드컴플리트에서도 지적했듯
    // switch() case 문 또는 if else() 문으로 아래처럼 명시적으로 처리가 되면.. 추상화할 필요가 없다는데.. 동의한다.
    // 아래는 참으로 명시적이다.
    public void actionPerformed(ActionEvent e) {
        if ("new".equals(e.getActionCommand())) { //new
            createFrame();
        } else { //quit
            quit();
        }
    }

    //Create a new internal frame.
    protected void createFrame() {
        MyInternalFrame frame = new MyInternalFrame();
        frame.setVisible(true); //necessary as of 1.3
        //아까 JDeskTopPane(서브 프레임들의 메디에이터)을 멤버 필드로 보관한 효과가 여기서 나타남..
        desktop.add(frame);
        try {
            frame.setSelected(true); //요건 정확힌 모르겠으나.. 해당 프레임에 포커스 이동시키는 걸테지..
        } catch (java.beans.PropertyVetoException e) {} //요 빈 어쩌구 예외 클래스는 당황스럽다.. 지금은 걍 패스
    }

    //Quit the application.
    protected void quit() {
        System.exit(0);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread. 
       위의 의미는 정확히 이해는 못하겠다.
       단지 이벤트 디스패팅 스레드란 단어를 보니.. 예전에 컴포넌트에 이벤트가 발생햇다는 것을 감지하는 이벤트 디스패처
       (내가 awt 분석떄 자주본 놈.. eventmulitcaster였나?)이 떠오른다. 
       대충 해석을 하면.. 멀티스레딩에 안전하게 gui객체를 생성하기 위해서 이벤트 감시자에게 불려가는 콜백 메서드를
       정의하는것 같은데.. 생소할 따름이다.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        InternalFrameDemo frame = new InternalFrameDemo();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

//아래를 보니.. 이해가 된다.. 위의 creatrAndShowGUI()가 특별한 의미가 있었던건 아닌.. 걍 init()메서드
//였구나..
//그보다 더욱 중요한건.. invokerLater의 매개변수로 스레드(=Runnable() + run()재정의를 익명클래스 기법을
//통해 생성과 동시에 재정의 처리) 객체를 생성하고.. run() 내부에서 InternalFrameDemo 란 gui 객체를 생성했다는 점이다.
//만약 내가 툴 프로그램을 멀티스레딩으로 처리했다면..  JFrame을 상속받은 툴 프로그램 객체에 Runnalbe을
//implements 하고 내부에 Thread 객체를 둔 다음에.. 생성자에서 thread = new Thread(this); start(){thread.start();}
//run(){} 을 구현했을 것이다. 위와 비교해 아래는 얼마나 깔끔한가..(제대로 이해는 못했지만..)
    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}


ps.음.. 일단.. 멋진 코드를 보면서 감동도 받았지만, 현재 내 초라한 능력에 위축도 된다.. 툴 프로그래밍 진도가 예상보다 
늦어질지도 모른다.(자바가 제공하는 패키지를 백분 활용하여 작업을 한다는 것의 난이도를 느꼈기 때문이다.) 위와 같은 코딩 
스타일을 몸에 익혀야 할것이다. 

불행중 다행이라면.. 아직 완전히 이해는 못했지만.. 학원 1달차 부터.. 꾸준히 디자인 패턴 관련 글과 자료를 공부해 놓아서
여러 패턴들이 눈에 보이고... 왜 그렇게 설계를 했을지.. 약간의 짐작과 이해가 가능하다는 점이다. 그런고로 app를  oop를 
활용해 제대로 구현하기 위해선 디자인 패턴에 대한 이해는.. 선택이 아닌, 필수이다. 디자인 패턴은 개발중의 여러 복잡한 
이슈를 해결하기 위한 솔루션이다.

ps2.오늘 점심땐 중고 서점 가서 db책,swing책,멀티스레드책(+@스프링)


'자바se api > swing' 카테고리의 다른 글

스윙..  (0) 2014.01.02
스윙의 기본적인 멀티스레드 처리방식  (0) 2014.01.02
이벤트처리 스레드;;  (0) 2014.01.02
propertyEditor vs ConversionService + 토비의 스프링?  (0) 2014.01.02
by givingsheart 2014. 1. 2. 09:11

조인을 할때 where절에서 1. 특정 칼럼(인덱스..pk,중복키,결합키등 조건을 지정.. 우선순위는 점조건->선분조건)을 정함으로서 

dmbs가 해당 테이블에서 어떠한 로우에 엑세스해서 임시메모리에 올릴지 알려줘서 dbms가 실제 파일 데이터를 엑세스할 범위를 좁히고 , 2.추출된 임시 테이블의 로우(or인스턴스들) 에 대해 조인을 할 부모 테이블 전체(모든 row) 조회할때, 해당 컬럼의 값을 조건 연산자로 추가(일반적으로 교집합 AND) 해줌으로서 내가 전달 받을 결과인 n개의 테이블에서 추출한 교집합 resultset를 만들어 내는것!

(ex) 직원 테이블을 자식 테이블로 해서 뒤에 지정할 조건에 일치하는 모든 직원의 사번과 이름을 가져오는데  .. 조건1.부서가
 "경리부"일인 모든 직원들에 대해(직원테이블과 부서테이블의 AND 교집합인 임시 테이블.. 해당 부서 테이블에 엑세스할때도 인
덱스정보(fk가 pk이냐..uk이냐..중복키이냐에 따라 다양한 결과 발생) -> 조건2. 조건 1에서 추출한 임시 테이블에 대해 연봉이 "5000만원" 이상일것(직급,호봉별로 연봉이 정해져 있다면 연봉 테이블이 존재할테고.. 테이블을 어떻게 설계했느냐에 따라 다를테지만, 또한 1에서 추출한 임시 테이블에 대해 AND 교집합)


*************************************************
인덱스를 결정한다에 대해 고민을 더 해보자.. 

예를 들어
파일에 dataMatrix[ROW][COL] 이 있을때..

해당 데이터를 어떻게 접근해야 디스크 i/o 효율이 좋을까? 행단위 , 열단위?
for(int row = 0; row < rows.size; row++) <-- 엑세스 단위로서 outter
    for(int col = 0; col < cols.size; col++) <-- 엑세스 단위로서 inner
        data = dataMatrix[row][col];    VS  data = dataMatrix[col][row]; 

위의 고민이 테이블간 조인에서 outter, inner 의 결정에 따른 퍼포먼스적 고민이라 생각한다.

(etc)
배열의 경우는 생성한 인스턴스들의 주소가 물리적으로 연결된 자료구조이지만, 연결리스트의 경운 인스턴스 간에 
물리적으로는 제각각의 위치이지만, 논리적으로 연결된 자료구조이며, 맵,셋등의 계열은 인스턴스 간에 물리적으로 
제각각의 위치이지만, 그것이 저장된 실제 주소를 배열로서(인덱스) 관리하는 자료구조이며, 트리의 경우(이진 밸런스의 경우)
엔 배열 자체의 시작점 -> 종료점(0~50000인덱스)까지 해당 index를 찾는 접근 방법이 아닌, 내가 찾는 인덱스가 
31234 라면   0~25000까지의 노드, 25000~50000까지의 노드중 우측 노드로 분할 정복하여 다음 단계(재귀)
에서는 25000~37500까지의 노드, 37500~50000까지의 노드중 좌측 노드로 분할 정복하여 다음 단계(재귀)
에서는 25000~31250까지의 노드, 31250~37500까지의 노드중 좌측 노드로 분할 ...(생략) 

식으로 자료의 양이 많아질경우 퍼포먼스가 자료의 수에 대해 log 자료의 수 로서 일정 값에 수렴하게 된다. (로그 = 루트의
개념 vs 지수 = 제곱근의 개념)


******************************************************

파일에 대한 엑세스를 최소화 한다는 것에 대해 고민을 해보자.

파일을 읽어와 메모리에 적재할때 i/o최소화를 통한 효율 상승을 위해 인접 블럭 단위로 크게 읽어와 메모리에 적재한다.

이 개념은 resultSet을 만들때 selete 절을 어떻게 구성할 것이며, from절에서 조인하려는 테이블에 대해 제한 조건을 줄것
이며, where 절에선 from절에서 추출한 임시 테이블에 AND 서브쿼리의 결과를 통해 얻어진 

추후 생각나면 정리.. 급한일 생김 -_-;


by givingsheart 2014. 1. 2. 09:09
java로 생각한 초간단 조인의 개념 

Class 직원
{
int id;
int department_id;
String name; 
직원(int id){ this.id = id;}
void setDeparment_id(int department_id){ this.department_id = department_id; } <-- null 허용 + agreegation아 아닌, 
                                                                                                                     association 이기에 setter
}

컨테이너 클래스 직원List
ArrayList<직원> list직원 =  new ArrayLsit<직원>(100);

for(int id=0; id<list직원.size; id++)
list.append( new 직원(id, (int)(Math.rand()*10 + 1) );  //유일한 직원 인스턴스 생성해서 컨테이너에 추가


Class 부서
{
int id;
String address; 
부서(int id){ this.id = id;}
}

컨테이너 클래스 부서List
ArrayList<부서> listB =  new ArrayLsit<부서>(10);

for(int id=0; id<list부서.size; id++)
list.append( new 부서(id));   //부서 종류별 유일한 인스턴스 생성해서 컨테이너에 추가


컨테이너 클래스 list직원이 컨테이너 클래스 list부서에 대하여
참조할수 있는 필드(fk = department_id)를 바탕으로 비교 연산을 수행한다.

=이중 반복문

Set<Entry<직원이름,부서주소>> set = new Set<Entry<직원이름,부서주소>>();  //리절트셋

for(직원 a : list직원)    <-- from 절 
                (1) 개념 간단화를 위해 생략
      for(부서 b : list부서)  <-- from 절
         if( a.departmet_id == b.id)  <-- where 절 중 equal 비교 연산    <-- 만약 요 조건절이.. 유일키(uk)가 아닐경우.. 
                                                                                                  리스트 생성후 한번 더 루프
          set.add( a.name + b.address) ; <-- 여기가 select 절에서 선언한 리절트셋 형태
                                                
      (1)물론 요 라인에서 selete절에 포함시킨 내가 얻어올 컬럼들 1~컬럼수 만큼 반복문이 포함될테고..
          if( a.id == 3) <-- 이건 selete절에서 인라인 쿼리(특정 조건에 맞는 로우를 추출)인가를 사용햇을때 일테고.. 
                              3번 직원(물론 모든직원을 검색할지, 특정 3번 직원을 검색할지는.. 상황따라)       
      (2)카티션 곱이란..
      if(a.departmet_id == b.id) 가 빠졋을 경우..  직원의 인스턴스(row=레코드) 갯수 * 부서의 인스턴스(row=레코드) 갯수만큼의
      return 결과가 발생함.  return 결과는 resultSet 개념이고.. 

이게 중첩 루프 조인인듯 하고..(아님 말고 -_-;) 그 외에 해쉬 조인, 머지 소트 조인의 경우는 아직 모르겟다 ;;
일단 해쉬는 문자열등 긴 데이터를 ->(가급적 중복안되는) 짧은 숫자로 사상시키는 건데..
머지 소트는 기억 진짜 안남;; 

selete 쿼리에서.. selete 절의 의미는! 테이블도, 컬럼도, 조건도 뭣도 아닌.. 말 그대로 dbms에게 파일에서 메모리로 읽어올
타입(리절트셋 테이블)에 대한 선언이며, 또한 dbms 에게 리턴할 값에 xx 작업 명령을 한다는 의미인것 같다.

from 절은 실제 파일에 접근할 위치를 지정하는 것이고
where 절은 접근한 파일들에 대해 조건(제약=추출)을 거는 것이고..

왜 selete만 dql 이고,.. 그외에 insert , update, delete 는 dml인지를 이해해야한다! ddl은 논외


그럼으로 아래의 코드는 이해되어야 한다.

insert /*+ append */ into t1 
  아래는 values 대신 .. 서브 쿼리를 사용한다.
  select  rownum,    <-- selete 절은 내게 리턴할 결과 값의 형태(templet)에 대해 내가 지정할수 있는 구문.
  mod(rownum, 1000),      <-- 1000으로 나눈 나머지
  floor((rownum-1)/1000),   <-- 소숫점 버리기: 로직이 멋짐.. 예전 floor 할때 + 좌로 시프트하고 + 0.5 한후에 
                                                                                           우측으로 시프트하고 (int)로 형변환 했던 방법
  lpad('x', 1000, 'x')  <-- LPAD 함수설명 LPAD함수는 문자열이 일정 길이(byte)가 될 때까지 왼쪽에 특정 문자를 덧붙인다.
                                     구문 LPAD(char1,n, [,char2] ) 
  from   <-- from 절이 실제로 파일의 물리적 주소에 접근할 위치 지정
    all_source a1, all_source a2 
       where rownum <= 1e6;     <-- 물리적 주소에 접근해서 메모리(selete절)로 읽어들일지 말지의 조건문이지만
                                              당연하게도 카티션 곱이 일어난다.
****************************************************


(etc)쿼리 최적화 관한 오라클 문서

*******************************************************
오늘 오라클 내장 메서드를 배우던중에..

의문점이. 데이터에 대한 조회 업무 외의 작업인.. 데이터 가공 to_char(format) to_date(format)

등의 업무가.. dbms의 몫인가?  db에 요청하는 app측의 몫인가에 대한 의문이었다.

이건 거의 예전에 프로젝트했던.. word 객체가 .. 다형적 타입의 format 객체를 주입받아(stratergy= 동적으로
객체의 행동을 바꿔줄수 있음.. 인터페이스는 그대로)패턴..  자신의 print에서 {format.printf(msg) 처럼 포맷 
객체에게 일을 시키는 느낌인데} 

또한 위의 느낌은.. jsp 페이지에서 ejb 또는 사용자 정의 태크or jsp 내장 태그를 이용해..
프리젠테이션과 비지니스를 분리하는 것과 같은 느낌 아닌가???

하여간.. 아직 책임영역.. dbms가 자신의 존재 이유인..데이터의 관리에 과연.. 프리젠테이션 처리가 필요할지에 
대한 위의 의문은 안풀렸고... <-- 선생님 말씀으론 가급적 내장 함수 안쓰고  app가 가공하는게 낫다고 하심!


*************************************************************************
(etc)오라클이 제공하는 사용자 정의 함수의 장점 설명..



SELECT 절에 붙는 논리적 테이블(hdd가 아닌 메모리)인 리절트셋 = 값에 대해서.. (char_to()등으로 표현까지 정해줄수있다)
FROM 절은 접근할 물리적 테이블을 지정할수 있는 키워드 이고(cf:DUAL 은 더미 테이블.. 의미 없다)
WHERE 절은 물리적 테이블에 대한 접근 조건이랄까? .. 한마디로 hdd에 대해 memory로 가져올 조건을 지정할수 있고

그외에 아래는 값들의 집합의 표현을 어떻게 지원할 것인지에 대한 것들..
GROUP BY 절은 위에 WHERE 절을 통해 추출할 SELETE 뒤의 논리적 테이블에 대해서.. 그것을 특정 컬럼에 대해서
그룹화해서 논리적 테이블을 구성하겠다는 키워드이고..
HAVAING 의 경우 그룹 메서드를 통해 추출한 그룹화된 값들에 대해  논리 조건등을 추가로 설정할 수 있는 키워드



*************************************************************

조인의 경우..

 SELECT e.first_name, e.last_name, e.salary, d.department_name
      FROM hr.employees e, hr.departments d
       WHERE d.department_name IN ('Marketing', 'Sales')
       AND e.department_id = d.department_id;
       
    이 쿼리의 플랜은 
      ------------------------------------------------------------------------------------------------
      | Id  | Operation                    | Name              | Rows  | Bytes | Cost(%CPU)| Time      |
      -------------------------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT             |                   |    19 |   722 |     3   (0)| 00:00:01 |
      |   1 |  NESTED LOOPS                |                   |       |       |            |          |
      |   2 |   NESTED LOOPS               |                   |    19 |   722 |     3   (0)| 00:00:01 |
      |*  3 |    TABLE ACCESS FULL         | DEPARTMENTS       |     2 |    32 |     2   (0)| 00:00:01 |
      |*  4 |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |
      |   5 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |    10 |   220 |     1   (0)| 00:00:01 |
      -------------------------------------------------------------------------------------------------
 
      Predicate Information (identified by operation id):
      ---------------------------------------------------
         3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
         4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")


***************************************************************
아참. 깜박했는데. DBMS의 경우 일반적으로 제일 잦은 연산인 데이터에 대한 빠른 접근 = 조회
를 위해.. 자료 구조중 이진트리(b tree) 형식으로 접근 주소 인덱스 테이블을 구성하는듯 하다. 
(밸런스드 형태..) (물론 각각의 데이터들의 실제 메모리상 위치야 제각각 일테지만..주소만 인덱스를 사용해
트리형태로 구성해주면.. ok지~)

그렇기에 서치가 빠르고, 아.. 머리가 안돌아간다.. 나중에 좀 더 생각해볼것! 
(인덱스의 이해, 조건절을 제대로 구성한 다는 것이 어떠한 의미일지에 대해..)

내가 원하는 결과를 얻기위해 특정 테이블을 선택하고.. 다른 n개의 테이블을 조인해야 할때..

테이블을 조인하는 '순서'에 따라.. fatorial(n) 의 경우의 수가 발생하고
각 테이블마다 인덱스 사용의 true/false에 따라.. 2의 n승의 경우의 수가 발생하고
조인 방식의 종류인.. 해쉬조인,중첩루프조인,머지소트 조인;;; 에 따하 3의 n승의 경우의 수가 발생한다고
한다.. OTL 


1.인덱스 접근 방식
    (1) range 스캔 (possible duplicated column key)
    (2) unique 스캔 (pk,uk.. 영어도 못하는데.. 걍 한글로 쓰자 -_-;)
    (3) full 스캔
    (4) fast full 스캔
    (5) skip 스캔 (!=)
    (6) min/max 스캔
    (7) index Join


(etc)http://prayyou.egloos.com/viewer/1799600   이해가 안간다.. 속상하다 ㅠㅠ

보통 매우 큰 인덱스를 Range/Full/Skip scan을 한 후 테이블 Access를 수항하면, 엄청난 양의 Single Block Read가 발생합니다. 

클러스터링 Fact에 따라, 
Index Leaf Block 의 Rowid 갯수에 따라 Table lookup 발생하면서 Table Block Read가 발생합니다. (내 예측이 맞았는듯.. 인덱스는 이진 트리로 구성하고..거기에 실제 파일 데이터를 연결 리스트or 리스트

형식으로 배치한듯..)
순차적 수행 플랜의 경우, 쿼리 성능은 Single Random table Read가 얼마나 빠른가에 좌우 되었습니다.

만약 단일 블록 하나를 읽는데 5ms 이 필요하다면, 1000 block을 읽는데 약 5초 정도가 소요됩니다. 
다만 여기에서도 
스토리지 시스템이 동시 IO 요청을 처리할 수 있으며, 최종 사용자 세션이 필요한 블록을 동시에 수행하는 어떤 방법이나, 병렬로 처리할 수 잇따면
OS와 스토리지와의 연결 상에서 부하가 될 수 있겠지만 사용자는 더 짧은 시간에 결과를 받아 볼 수 있습니다.



오라클은 어떻게 IO를 최적화했는가?

현재까지 제가 아는 한, 오라클은 12.1 버전 이전에서도 몇가지 교묘한 방법으로 IO를 다루어 왔습니다. 아래는 그 몇몇가지 방법입니다.

- Nested Loop Join 에해서 오라클에 사용자에 대한 몇가지 전략이 사용됨 : NL-Join Batching 과 Table Access를 Join 밖으로 이동시켰습니다.

     --NL-JOIN Batching (http://docs.oracle.com/cd/E11882_01/server.112/e41573/optimops.htm#PFGRF94642)
     
     
11g에서는 Physical IO의 지연을 감소시키기 위하여 NL Join 에 대한 새로운 방식을 소개합니다. 
     Table Block 이나, index Block이 Buffer Cache에 존재하지 않지만, Join 에 필요한 경우 Physical IO가 필요합니다. 
     오라클 데이터베이스 11g는 한번에 하나씩 처리하는 대신 여러 Physical IO 요청을 묶어 Vector IO를 사용하여 처리할 수 있습니다.

     


이전 버전의 Exeution Plan에서 한 line으로 나타났던 Nested Loop Join의 Row source가 두번의 Nested Loop Join Row source로 나타나게 되었습니다. 
     이 경우, Oracle 데이터베이스는 첫번째 NL Join Row source를 Inner 쪽 인덱스와 Outer 쪽 Table에 Join 으로 할당합니다. 
     두번째 Row Source는 index에 저장된 Rowid를 포함한 첫번째 join 결과 set과 Inner 쪽 Table사이의 Join 에 할당합니다.
     
     즉, 
     SELECT e.first_name, e.last_name, e.salary, d.department_name
      FROM hr.employees e, hr.departments d
       WHERE d.department_name
 IN ('Marketing', 'Sales') <-어제 봤던 부분..  IN(a or b)키워드= 풀스캔..
       AND e.department_id = d.department_id;
       
    이 쿼리의 플랜은 
      ------------------------------------------------------------------------------------------------
      | Id  | Operation                    | Name              | Rows  | Bytes | Cost(%CPU)| Time      |
      -------------------------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT             |                   |    19 |   722 |     3   (0)| 00:00:01 |
      |   1 |  NESTED LOOPS                |                   |       |       |            |          |
      |   2 |   NESTED LOOPS               |                   |    19 |   722 |     3   (0)| 00:00:01 |
      |*  3 |    TABLE ACCESS FULL         | DEPARTMENTS       |     2 |    32 |     2   (0)| 00:00:01 |
      |*  4 |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |
      |   5 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |    10 |   220 |     1   (0)| 00:00:01 |
      -------------------------------------------------------------------------------------------------
 
      Predicate Information (identified by operation id):
      ---------------------------------------------------
         3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
         4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
         
         
         
        로 수행됩니다. 

   이 경우, HR.department Table의 row 는 첫 번째 Join의 Outer Side로되며, 첫번째 Join의 Inner Side는 Index EMP_DEPARTMENT_IX가 됩니다.
      첫 번째 Join 의 결과집합은 다시 두번 째 Join 의 Outer Side가 되며, Hr.Employee Table은 Inner Side가 됩니다. 
      
   이전 버전의 실행계획과 동일하게 표시되는, 두번째 Join row source가 할당되지 않는 경우는 다음과 같습니다. 
      - Inner Side에서 필요한 모든 컬럼이 Index 상에 있어 Table Access가 필요없는 경우. 이 경우, Oracle은 오직 한번만 Join 한다 <--이게 핵심인듯하다. 조인을 위해 첫번째 선택해주는 인덱스에 대해 loop를 돌 필요가 없다면..
그만큼 퍼포먼스상 이익이 있다.  => 자주 사용될 테이블을 미리 만들어 둔다는게 이런 의미였구나..  특정 직원에 대한 연봉 정보를 자주 조회할 도메인일때 이것을 직원테이블에서 id와 이름 + 특정 조건 으로 새롭게 테이블을 구성해두면.. 나중에 이것을 
급여 테이블과 조인 연산시에.. 이중 반복문이 아닌, 단일 반복문이 될것이다. selete *(아스타리스크)를 사용하도록 노력할?
것!  .. 물론 쓸데 없는 데이터를 파일에서 읽어오게 되면.. 그 성능 하락이 더 크다... 외부 i/o는 적을수록 빠른것! (선생님의 
명언!!!)
 
      - 이전 버전과 Row 의 순서가 다르게 리턴될 수 있다. 따라서, Oracle DB가 특정한 순서로 Row를 추출해야 되는경우, 예를 들어, Order by Sort를 제거할 필요가 있을경우
        기존의 NL Join 방식을 사용할 수 있다.
      - OPIMIZER_FEATURES_ENABLE 초기 파라메터가 11g 이전 버전으로 set 되어 있는 경우, 기존의 NL Join 을 수행한다. 


http://prayyou.egloos.com/viewer/1799600



*******************************************************************

statement vs preparestatement


http://translate.googleusercontent.com/translate_c?depth=1&hl=ko&prev=/search%3Fq%3Dstatement%2Bvs%2Bpreparedstatement%26newwindow%3D1%26espv%3D210%26es_sm%3D93&rurl=translate.google.co.kr&sl=en&u=http://stackoverflow.com/questions/3271249/difference-between-statement-and-preparedstatement&usg=ALkJrhg7XYWCDIhZNBVwbSd1ll4UI_YUqg



DiverManger.getConnection() 에서 하는 짓..


//  Worker method called by the public getConnection() methods.
    private static Connection getConnection(
        String urljava.util.Properties infoClassLoader callerCLthrows SQLException {
        /*
         * When callerCl is null, we should check the application's
         * (which is invoking this class indirectly)
         * classloader, so that the JDBC driver class outside rt.jar
         * can be loaded from here.
         */
        synchronized(DriverManager.class) {
          // synchronize loading of the correct classloader.
          if(callerCL == null) {
              callerCL = Thread.currentThread().getContextClassLoader();
           }
        }
        if(url == null) {
            throw new SQLException("The url cannot be null""08001");
        }
        println("DriverManager.getConnection(\"" + url + "\")");
        // Walk through the loaded registeredDrivers attempting to make a connection.
        // Remember the first exception that gets raised so we can reraise it.
        SQLException reason = null;
        for(DriverInfo aDriver : ) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.drivercallerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(urlinfo);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }
            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }
        }
        // if we got here nobody could connect.
        if (reason != null)    {
            println("getConnection failed: " + reason);
            throw reason;
        }
        println("getConnection: no suitable driver found for "url);
        throw new SQLException("No suitable driver found for "url"08001");
    }


by givingsheart 2014. 1. 2. 09:08

http://www.okjsp.net/seq/237333



추가로 java.util.observer 인터페이스, 
java.lang.object 의 notify() 메서드,


Runaable Obj A---------------------------->
                     event X
                              Runaable Obj B------------------------->
                                          event Y
                                                    Runaable Obj C------------------->


를 객체 지향적으로 처리하고 싶기 때문이다.

아직 개념이 부족해.. 컨셉 자체도 명확하지 않다. 단지 내 객체들간에 이벤트 드라이븐 
방식의 처리를 위해 옵저버 인터페이스를 이해할 필요가 있었고, 또한 Object 클래스에
정의된 notify() 에 대한 이해가 거의 없기 때문이다.


난 아래 링크의 글을 정확히 이해할수없다


(추가)
이벤트를 기반으로 한 비동기 프로그래밍 문제이다. 자바스크립트의 핵심 개념이 된다.
비동기 처리할 부분(비동기 함수 사용) VS 순차적 제약이 필요한 부분(해당 함수 내에서 아..
..어찌 해결하는지 까먹음.. ) 





by givingsheart 2014. 1. 2. 09:03