Framework/Another Lore2009. 4. 23. 02:05


[Example Code]
  DatabaseSequence dseq = new DatabaseSequence(session.getGlobalStore().getNamespace(), DBController.getTestInstance()) ;
  Sequence seq = new CacheSequence(dseq) ;
  
  IDString seqId = IDString.seqId("seq_name") ;
  seq.reset(seqId) ;
  
  long i = seq.nextVal(seqId) ;
  assertEquals(1, i) ;

  assertEquals(1L, seq.currVal(seqId)) ;
  assertEquals(2L, seq.nextVal(seqId)) ;
  assertEquals(3L, seq.nextVal(seqId)) ;
  
  seq.reset(seqId) ;
  assertEquals(0, seq.currVal(seqId)) ;
  for (int j = 1; j < 111; j++) {
   assertEquals(1L *j, seq.nextVal(seqId)) ;
   assertEquals(1L *j, seq.currVal(seqId)) ;
  }

<interface Sequence>
 public void reset(IDString seqName);
 public long currVal(IDString seqName);
 public long nextVal(IDString seqName);


적합한 PK의 역할을 할 수 있는 컬럼(들)이 없거나 그 컬럼(들)의 length가 길때 Sequecne는 꽤 유용하다.

다만 DB의 sequence는 몇가지 불편한 점이 있다.
이를테면 parent - child 구조의 data를 하나의 트랜잭션으로 입력하려고 할때 parent의 PK가 sequence 라면

parent가 입력되기 전까지 sequence를 모른다.
child는 parent의 PK를 알아야 입력이 가능하다. 라는 명제가 충돌한다.

그나마 오라클 같은 경우 sequence는 별도의 세그먼트 이기 때문에

현재 사용하는 sequence의 next value를 알아와서 그 값으로 parent와 child의 값을 설정한후 입력한다.
가 가능하지만..

다른 DB의 경우 이를테면 MSSQL의 경우 seq는 table에 IDENTITY형으로 종속되어 있기 때문에
하나의 트랜잭션으로 유지하기 위해 꽤 번거로운 짓을 많이 해야 한다.


AL에서는 그래서 별도의 Sequence 객체를 제공하는데.
원리는 간단하다. key, value 의 하나의 테이블을 만들고 key에는 sequnceName을 value에는 currValue를 저장하고 nextValue를 요청했을 경우 value+1로 업데이트 하고 해당 value를 던져주면 된다. 이렇게 구현할 경우 필요할 경우 sequece를 아주 간단하게 만들수 있다. 

예컨데 이런 SQL 이다. 

    function reset(v_seqName varchar2)
    return number
    is
    begin
        update sequence_tblc set seqValue = 0 where seqName = v_seqName ;
   
        return SQL%ROWCOUNT ;
    end ;

    function currVal(v_seqName varchar2)
    return number
    is
        v_result number ;
    begin
        select NVL(max(seqValue), -1) into v_result from sequence_tblc where seqName = v_seqName ;
       
        If v_result = -1 then
            insert into sequence_tblc(seqName, seqValue) values(v_seqName, 0) ;
            return 0 ;
       
        end if ;
        return v_result ;
    end ;
   
    function nextVal(v_seqName varchar2)
    return number
    is
        v_result number ;
    begin
        update sequence_tblc set seqValue = seqValue+1 where seqName = v_seqName returning seqValue into v_result;
       
        IF SQL%ROWCOUNT = 0 Then
            insert into sequence_tblc(seqName, seqValue) values(v_seqName, 1) ;
            return 1 ;
        End if ;
       
        return v_result ;
    end ;

다만 이렇게 사용하면 Sequence를 사용하기는 매우 편하지만 nextVal을 호출할때마다 DB Call이 일어난다. 그리고 Table update 방식은 DB sequence 방식보다 무겁다.

AL에서는 그래서 DB의 sequnce의 아이디어를 그대로 사용한다. AL.Sequnece의 nextVal을 호출하면 실제로는 +20으로 업데이트하고 20개의 값을 queue에 저장해둔다. queue가 비어 있지 않으면 queue값을 poll 해주고 20개를 모두 소모해 비어 있으면 다시 +20을 해주고 반복한다.

'Framework > Another Lore' 카테고리의 다른 글

AL : NodeType  (0) 2009.04.23
AL : Lock  (0) 2009.04.23
자동화 테스트 - 자바스크립트  (0) 2009.04.17
와~~~  (0) 2009.04.09
AL - Extreme  (0) 2009.04.04
Posted by bleujin