728x90
계층형 게시판( 댓글이 있는 )의 구조와 알고리즘에 대해서 알아보자.
설명을 위해 테이블에는 다음과 같은 컬럼들만 있다고 가정한다.

이해를 돕기 위해 수행되는 쿼리와 수행후 테이블의 row를 그려 넣었다. 

no : 글번호(Primary Key)
title : 글제목
grp : 같은 주제를 갖는 게시물의 고유번호. 
       부모글과 부모글로부터 파생된 모든 자식글은 같은 번호를 갖는다.
seq : 같은 그룹내 게시물의 순서
lvl : 같은 그룹내 계층

[MySQL 관련 명령어]
alter table board auto_increment = 1; 
-- 자동증가값 사용시 최초값 셋팅
 
set last_insert_id = 0;
-- 마지막으로 사용된 auto_increment 값 초기화

select last_insert_id() 
-- 마지막으로 사용된 auto_increment 값 반환


예제)
1) 게시판에 첫번째 글이 올라 올때
  

insert into board( title, grp, seq, lvl ) 
values('안녕하세요', (select last_insert_id()+1), 1, 0);
 no title grp seq lvl
 1 안녕하세요 1 1 1
새글(글 등록)의 경우,
no 는 AutoIncrement 로부터 받아온 값
grp는 no와 동일한 값 
seq는 1
lvl은 0 이된다.


2) 두번째, 세번째 글이 올라올때

insert into board( title, grp, seq, lvl ) 

values('날씨가 맑습니다', (select last_insert_id()+1), 1, 0);

no title grp  seqlvl 
1안녕하세요 
 2날씨가 맑습니다 
 3모임이 있습니다 


3) 첫번째 글에 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 1;

insert into board( title, grp, seq, lvl ) 

values('반가워요', 1, 1+1, 0+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 
댓글의 경우, ( 부모글 : '댓글이 달린 바로 상위글' 원본글일수도 있고 댓글일 수도 있음 )
grp 는 부모글의 grp 값
seq 는 부모글의 seq+1
lvl 은 부모글의 lvl+1 이 된다.

댓글을 삽입하기 이전에
한 글에 대한 댓글이 여러개인 경우 우선순위를 맞춰주기 위해서 
부모글과 동일한 그룹 번호에 있으면서 
부모글의 seq 번호보다 큰 게시물의 seq 번호를 모두 1만큼 증가시킨다


4) 첫번째 글의 댓글에 댓글이 올라올때 
(즉, 네번째 글의 댓글이 댓글이 삽입된 후)

update board

set seq = seq + 1

where grp = 1

and seq > 2;

insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 2+1, 1+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다



5) 첫번째 글의 두번째 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 1;


insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 1+1, 0+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다
 6 환영합니다


6) 여섯번째 게시물에 댓글이 올라올때

update board

set seq = seq + 1

where grp = 1

and seq > 2;


insert into board( title, grp, seq, lvl ) 

values('감사합니다', 1, 2+1, 1+1);

 no titlegrp seq lvl 
 1 안녕하세요
 2날씨가 맑습니다 
 3 모임이 있습니다3
 4반가워요 
 5 감사합니다
 6 환영합니다
 7 감사합니다

검색(select) 할 때는 grp를 내림차순으로
seq를 오름차 순으로 정렬하면 된다. 
인덱스는 기본키와 grp+seq의 복합 인덱스를 설정하면 된다.

select * from board order by grp desc, seq asc;

[검색결과]
no title     grp seq lvl
--------------------------------------------
3 모임이 있습니다 3 1 0
2 날씨가 맑습니다 2 1 0
1 안녕하세요 1 1 0
6 환영합니다 1 2 1
7 감사합니다 1 3 2
4 반가워요        1 4 1
5 감사합니다 1 5 2




아래 예는 오라클에서 테이블을 구성하고 검색해 볼 수 있는 환경을 위한 SQL 이다. 

오라클은 AutoIncrement 기능이 없기때문에 sequence 를 이용한다.

<DDL> 예제
 

drop table board;


create table board(

no int primary key,

title varchar2(45),

grp int,

seq int,

lvl int);


drop sequence board_no_seq;


create sequence board_no_seq start with 1 increment by 1;


create index board_grp_seq on board(grp desc, seq asc);


<DML> 예제


[첫번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[두번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[세번째 게시물 입력 - 새 글 입력]

insert into board

values(board_no_seq.nextval, board_no_seq.currval, 1, 0);


[네번째 게시물 입력 - 첫번째 게시물의 답글]

(답글이 올라오는 경우에는 답글에 부여 할 seq를 먼저 확보해준다.)

update board

set seq=seq+1

where grp=1 and seq > 1;


insert into board

values(board_no_seq.nextval, '반가워요', 1, 2, 1);


[다섯번째 게시물 입력 - 네번째 게시물의 답글]

update board

set seq=seq+1

where grp=1 and seq > 2;


insert into board

values(board_no_seq.nextval, '감사합니다', 1, 3, 2);


[여섯번째 게시물 입력 - 첫번째 게시물의 두번째 답글]

update board

set seq=seq+1

where grp=1 and seq > 1;


insert into board

values(board_no_seq.nextval, 1, 2, 1);


[일곱번째 게시물 입력 - 여섯번째 게시물의 답글]

update board

set seq=seq+1

where grp=1 and seq > 2;


insert into board

values(board_no_seq.nextval, '감사합니다', 1, 3, 2);



[게시판을 검색하는 경우, grp로 내림차순, seq로 오름차순으로 정렬하면 됩니다.]

select case when lvl=0 then no

when lvl>0 then null end no

, rpad('+', lvl, '-')||title title

from board

order by grp desc, seq;


[검색결과]

no    title 

----------------

3 모임이 있습니다 

2 날씨가 맑습니다 

1 안녕하세요  

+환영합니다  

+-감사합니다  

+반가워요 

+-감사합니다 


출처 : http://hdm6337.tistory.com/entry/%EA%B3%84%EC%B8%B5%ED%98%95-%EA%B2%8C%EC%8B%9C%ED%8C%90-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8C%93%EA%B8%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

Posted by 앗뜨거
,
728x90

<c:set var="checkDate" var='${request.getParameter("Date")}' />

이렇게 받아온 CheckDate를

 

javascript의 변수인

var chDate 라는 변수가 있을 때

checkDate값을 chDate에 넣어주고 싶습니다.


이런질문이있었다 


답은


var chDate = '<c:out value="${checkDate}"/>';  이렇게 하면된다.

Posted by 앗뜨거
,
728x90

<c:forEach items="${gamelist}" var="b" varStatus="status">
   [${status.index}]: ${gamelist[status.index]}
   <TR>
    <TD>${b.gameid}</TD>
    <TD>${b.displaytype}</TD>
    <TD>${b.displayno}</TD>
    <TD>${b.gamelink}</TD>
    <td><c:if test="${b.ishidden=='T'}"><span style="color:red">Hidden</span></c:if></td>
    <td>${b.lang}</td>
    <td><a href="javascript:edit(${b.bid})">[Edit]</a></td>
   </TR>
  </c:forEach>

.index는 0부터 시작하고

.count는 1부터 시작한다.



출처 : http://jsonlee.tistory.com/52

Posted by 앗뜨거
,
728x90

sqlMapper를 작성할 때 #과 $ 기호의 차이점은 아래와 같다.


# : 매개변수로 전달받은 파라메터를 그대로 삽입한다.

ex) 만약 아래와 같이 SQL이 작성되어 있다고 네임 스페이스는 test.select 라고 하자.

    select * from MEMBER where name = #{name}

    호출시 인자 전달 방법은 아래와 같다.

    getSqlSession.selectOne("test.select", "이지형");


$ : key와 value로 이루어진 Map 형태로 전달된다.

    select * from MEMBER where name = ${name}

    이라고 하면 파라메터 타입을 HashMap으로 넘겨줘야하며 

    name(key)에 해당하는 값(value) SQL 구문에 넣어주게 된다.

    HashMap<String, String) map = new HashMap<String, String>();

    map.put("name", "이지형");

    getSqlSession.selectOne("test.select", map);






1. #는 쿼리가 수행될 때, 다음과 같이 된다 

SELECT * FROM USER 

WHERE 
col = ?  


parameter : [값]


?에 bind된 값이 들어가게 된다. 

이 쿼리의 컴파일 된 내용을 재사용 할 수 있고, 파라미터에 따라 대입해주므로 효율적이다.
내부적으로 preparedStatement 객체에서 ? 에 들어갈 파라미터의 값을 set 해줌으로써 사용이 된다.
 
preparedStatement는 한번 수행한 쿼리를 캐싱하는 객체


사용 용도 >>

#일 경우, 에 사용한다.

myBatis : 컬럼명 = #{값}   
iBatis : 컬럼명 = #값#

* 쿼리에 작은 따옴표가 붙게 된다.


2. $는 쿼리가 수행될 때, 다음과 같이 된다

SELECT * FROM USER
WHERE 
col = 



값이 넣어진 쿼리 자체로 수행이 된다.(상수)
즉, 문장 전체가 preparedStatement가 된다.

사용 용도 >>

$일 경우는 컬럼명이 동적으로 바뀌어야 할 때 사용한다. 또는 테이블명.

myBatis : ${컬럼명} = #{값}   
iBatis : $컬럼명$ = #{값}

* 쿼리에 작은따옴표가 붙지 않는다. 
값에 $를 사용하면 스트링의 경우 작은따옴표로 감싸지지 않기 때문에 에러 발생한다.


이렇게 사용하지 않으면 unknown column 이나 There is no readable property named  등등의 에러가 뜨게 된다


출처 : http://warmz.tistory.com/744
   http://marobiana.tistory.com/60


'프로그래밍 > ibatis' 카테고리의 다른 글

iBatis 복수 parameter넘기는법  (0) 2014.11.18
Mybatis 기본 사용법  (0) 2014.10.28
[스크랩]resultMap, resultClass, parameterClass  (0) 2014.10.14
Posted by 앗뜨거
,
728x90

DAO용도인 .JAVA 파일에 다음과 같은 메서드를 만들어 넣는다 단지 map한개만 만들어서 보내고 싶은 파라미터 다 집어 넣으면 된다. 변수 이름과 key값은 같은게 좋을 듯 하다. 

그리고 그냥 MAP만 한개 던저주면 게임 끝이다.

아 이 얼마나 쉬운가 이거 어찌 하나 몇시간 생각했었는데. 혹시 되나하고 해봤는데 되니까 참 .. iBatis 레퍼런스 찾아봐도 되는데 이리 하면 기억에 오래 남아서 머리 싸매고 고민하는게 난 좋다 ㅎㅎㅎ(멍청한 짓인가) 이 프레임워크 만든사람이 나보다 똑똑한 사람일텐데 파라미터 하나 복수로 넘길수 없는 걸 만들었을리 없다는 확신이 있었다. ㅋㅋㅋㅋㅋ

public ArrayList getTimePriceList(String contractCode,String sdate,String edate,String stime,String etime) throws SQLException {
         HashMap map = new HashMap();
         map.put("contractCode", contractCode);
         map.put("sdate", sdate);
         map.put("edate", edate);
         map.put("stime", stime);
         map.put("etime", etime);
         
   list=(ArrayList)sqlMap.queryForList("getTimePriceList",map);  
   return list;
  }

SQL을 지정한 XML에서 다음과 같이 parameterClass를 맵으로 하면 된다. 꼭 MAP이 아니라 list 나 table도 되는지는 귀찮아서 안해봤다. 뭐 되지 않을까 싶다 안되면 되는거 쓰면 되니까 뭐 문제는 없을 듯하다. 
어짜피 parameter넘길뿐인데 뭐든 어떠냐 잘 넘어가기만 하면 되지 ㅎㅎㅎ

<select id="getTimePriceList" parameterClass="java.util.HashMap" resultClass="timeprice">
    <![CDATA[SELECT contractCode,date,time,close,sum(vol) as sumvol from timeprice 
    where 
    contractCode=#contractCode# 
    and date>=#sdate# 
    and date<#edate# 
    and time>=#stime# 
    and time<#etime# 
    group by close order by close
    ]]></select>


출처 : http://hedging.tistory.com/entry/iBatis-%EB%B3%B5%EC%88%98-parameter%EB%84%98%EA%B8%B0%EB%8A%94%EB%B2%95

'프로그래밍 > ibatis' 카테고리의 다른 글

[MyBatis] $ 과 # 차이점  (0) 2014.11.18
Mybatis 기본 사용법  (0) 2014.10.28
[스크랩]resultMap, resultClass, parameterClass  (0) 2014.10.14
Posted by 앗뜨거
,
728x90

Limit 연산자를 이용하면 쿼리 결과 개수를 제한할 수 있다.

1
select * from 테이블명 Limit 개수(정수);



예) cookie_sales 테이블에서 first_name별로 그룹을 만들어 sales컬럼의 합계가 가장 높은 순으로 
     출력하되, 2개까지만 출력한다.

1
2
3
4
select first_name, sum(sales) from cookie_sales
group by first_name
order by sum(sales) desc
Limit 2;

결과

 first_namesales 
 Britney107.91 
 Paris98.23 





Limit의 조금 다른 사용법

아래처럼 두 개의 정수가 들어간다면 완전히 다른 의미가 된다. 

Limit 0, 4 
                  0은 시작할 레코드의 번호이다. (SQL은 0이 처음)
                  4는 반환할 결과의 수이다. 


예를 들어 음악 챠트에서 20위에서 30위까지 보고 싶다고 하면 
Limit 19,10 으로 하면 된다~



출처: http://warmz.tistory.com/259

Posted by 앗뜨거
,
728x90



스크립트 부분
1
2
3
4
5
6
7
function onlyNumber()
        {
            if ((event.keyCode < 48) || (event.keyCode > 57))
            {
                event.returnValue = false;
            }
        }




사용할부분


1
<input type="text" id="txtMobile2" size="4" onkeypress="onlyNumber()"/>



onkeypress 에 넣어주면 키보드 입력시 숫자만 들어가고 나머지는 입력이 되지 않는다.

Posted by 앗뜨거
,
728x90

Oracle에서 제공하는 SQL Developer를 사용할 경우


기본 Date 출력 포맷은 RR/MM/DD 로되어있다 ( 예> 12/11/01 )

Date 포맷을 시간단위까지 보고 싶다면 어떻게 해야 할까?

SQL Developer 환경설정을 통해서 적용 할 수 있다

도구 ( Tools ) -> 환경설정 ( Preference ) 로 들어간 후

왼쪽 리스트에서 데이터베이스 ( Database ) -> NLS 로 들어간다

오른쪽 설정 창에 날짜 형식 (Date Format) 이 있을 것이다

여기서 바꿔주면 된다




이 출력 포맷은 SELECT문으로 출력되는 Column 뿐만 아니라

테이블을 Export할 때도 적용된다



출처 : aslike.egloos.com/2976365


Posted by 앗뜨거
,
728x90

Eclipse의 자동빌드는 수시로 이러나기 때문에

Workspace에 Project / 소스가 많을 경우 이클립스의 속도가 저하되는 경우가 많다.

그러므로 소스 작성시에는 자동빌드(오토빌드)를 꺼두고
 
작성 소스을 완료하고 실행시에 빌드를 시킨다

설정하기

Project - Bulid Automatically


수동빌드

Ctrl + B
or
Project - Bulid All



출처 : http://ehbread.tistory.com/11

Posted by 앗뜨거
,
728x90

<img src="한글.jpg" ......../> 로 태그를 쓰면 




이런식으로 이미지가 깨져서 나오게 된다.





해결방법은 여러가지가 있겠으나


내가 이해하기 쉽고 간단하게 하는법이 있어서 쓰게됐다.



나같은경우는 



여기 서버를 열어서


이부분을 찾습니다. 끝부분에 URIEncoding="utf-8" 을넣어주면

 


 해결완료!!!



그런데 혹시 이것도 해결이 안된다면 하나더 추가 해주면 됩니다.


DTO.java  파일에서 


그림을 저장하는 setter 의 인코딩을 해주면되요


예를들면 이런식으로


1
2
3
4
5
6
7
8
9
10
11
12
13
public void setG_image1(String g_image1) 
    {
        try 
        {
            this.g_image1 = URLEncoder.encode(g_image1,"utf-8");
        } 
        catch (UnsupportedEncodingException e) 
        {
            e.printStackTrace();
        }
        this.g_image1 = g_image1;
    }
 


이렇게 둘다 해주면 거의 될꺼에요 혹시 안되면 서버를 완전히 종료후 클린시켜주고 다시 실핼시킨후 브라우져에서 F5를 한번눌러보세요~

Posted by 앗뜨거
,