---------------------------------------------------------------------------------------------------------------------------------------------------------------
1 . trustForm 
 화일 이름 : D:\Workspace\Project\ALP\ALP_GSW\WebSource\xfm\test\test.xfm


---------------------------------------------------------------------------------------------------------------------------------------------------------------
2. actionInfo
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\Config\AS_VHRP_serviceinfo.xml


---------------------------------------------------------------------------------------------------------------------------------------------------------------
3. Facade
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\JavaSource\alp\as\hkmc\vhrp\service\GrnRoWorkInpFacade.java

 public RoListCdto[] selectRoList(String startDt, String endDt, AdminSessionInfo baseInfo) throws BizException {
  LogonInfo logonInfo = LoginHelper.getLogonInfo(baseInfo);
  return GrnRoWorkInp.getInstance().selectRoList(startDt, endDt, logonInfo);
 }       


---------------------------------------------------------------------------------------------------------------------------------------------------------------
4. biz
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\JavaSource\alp\as\hkmc\vhrp\service\GrnRoWorkInp.java

 public RoListCdto[] selectRoList(String startDt, String endDt, LogonInfo logonInfo) throws BizException {
  return GrnRoMainDao.selectRoList(startDt, endDt, logonInfo);
 }


---------------------------------------------------------------------------------------------------------------------------------------------------------------
5. dao( DAO ) 
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\JavaSource\alp\as\hkmc\vhrp\dao\GrnRoMainDao.java

 public static RoListCdto[] selectRoList(String startDt, String endDt, LogonInfo logonInfo) throws BizException {
         RoListCdto[] resArrCdto   = null;
         PreparedStatementWrapper psw  = null;

  try { 
   StringBuffer sql = new StringBuffer();
   sql.append("\n   select ASN_CD     ");
   sql.append("\n             ,RO_NO     ");
   sql.append("\n            ,VIN      ");
   sql.append("\n           ,CSMR_NM     ");
   sql.append("\n           ,I_CDT      ");
   sql.append("\n   from t_ro_info     ");
   sql.append("\n   WHERE ASN_CD = ?    ");
   sql.append("\n         AND i_cdt between ? and ? ");


   psw = new PreparedStatementWrapper(logonInfo.getCoScnCd() + AsConstants.DATA_SOURCE_NAME, sql.toString());

   int index = 1;

   psw.setString(index++,"MA0D96");  
   psw.setString(index++,startDt);    
   psw.setString(index++, endDt);    

   DBManager db = new DBManager();
   List dbData = db.selectList(psw, RoListCdto.class.getName());

   if(dbData.size() > 0) {
   resArrCdto = (RoListCdto[]) dbData.toArray(new RoListCdto[dbData.size()]);
   }

  } catch(SQLException se) {
   logger.error(se.getMessage());
   throw new BizException(AsConstants.SYSTEM_ID, "AS0001");
  } finally {
   if(psw != null)
   psw.release();
  }
   return resArrCdto;
  } 


---------------------------------------------------------------------------------------------------------------------------------------------------------------
6. dto( VO )
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\JavaSource\alp\as\hkmc\vhrp\dto\RoListCdto.java


---------------------------------------------------------------------------------------------------------------------------------------------------------------
7. jsp 
 화일이름 : D:\Workspace\Project\ALP\ALP_GSW\WebSource\jsp\test_selectRoList.jsp

 
<%--
***************************************************************************************************
* JSP 페이지 태그 선언
***************************************************************************************************
--%>
<%@page contentType="text/xml; charset=EUC-KR"%>
<%@page import="alp.as.hkmc.vhrp.dto.RoListCdto"%>
<%@page import="alp.as.hkmc.util.XmlGenHelper"%>
<%@page import="com.ebstorm.jframework.foundation.message.MsgParameter"%>
<%--
***************************************************************************************************
* 변수 선언 및 선행 로직
***************************************************************************************************
--%>

<%
    XmlGenHelper xml = new XmlGenHelper(0);
    try {

 //메소드 이름을 작성합니다.
     RoListCdto[] result = (RoListCdto[]) request.getAttribute("test_selectRoList");
        
 // 컬럼 이름 작성(반환받는 곳의 이름)
        String[] column = {
      "asnCd"
       ,"roNo"
       ,"vin"
       ,"csmrNm"
       ,"iCdt"                
     };
 
        // 노드 스트림의 위치를 작성합니다. 
 int pNode = xml.add (0, "res", "");
        
 //소스가 있는 곳을 작성합니다.
        xml.setSourceClassName("alp.as.hkmc.vhrp.dto.RoListCdto");
        xml.genXml(pNode, "grid", column, result);

        MsgParameter param = new MsgParameter();

        param.add( result.length );
        xml.setMessage("AS0002", param);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        out.println(xml.getXmlString());
    }
%>


Posted by 사라링

TrustForm 2.0 이 지원 하는 XForms 이벤트

이름내용(발생 시점)적용
xforms-model-construct모델, processor가 모두 초기화 되고 나는 시점, 즉 document가 load되는 시점model
xforms-previousShift+Tap키 또는 마우스 클릭등으로 인해 포커스 이동 전Input, secret, textarea,
button, select controls
xforms-nextShift+Tap키 또는 마우스 클릭등으로 인해 포커스 이동 후Input, secret, textarea,
button, select controls
xforms-focus(DOMFocusIn)포커스 받았을때 (DOMFocusIn과 동일)Input, secret, textarea,
button, select controls
xforms-help포커스가 있고 F1이 눌려졌을때Input, secret, textarea,
button, select controls
xforms-hint컨트롤 위에 마우스가 놓여져 있을때(툴팁 발생시)Input, secret, textarea,
button
xforms-refreshrefresh 될때model
xforms-revaliaterevalidate 될때model
xforms-recalculaterecalculate 될때model
xforms-reset 
(resetInstance 액션에 해당)
reset 될때model
xforms-submitsubmit을 보내려고 할때submitInfo
xforms-activate기본 액션..(버튼 클릭시)기본 액션.. button
xforms-value-changed값이 바뀌었을때Input, secret, textarea,
xforms-selectselect 되었을때select controls
xforms-deselectdeselect 되었을때select controls
xforms-valid스키마정보 또는 타입이 일치했을때Input, secret, textarea,
xforms-invalid스키마정보 또는 타입이 일치하지 않았을때Input, secret, textarea,
DOMFocusIn(xforms-focus)포커스 받았을때(xforms-focus와동일)Input, secret, textarea,
button
DOMFocusOut포커스를 잃었을때Input, secret, textarea,
button
xforms-readonlyrevalidation 후 현재 상태가 readOnly일때Input, secret, textarea,
xforms-readwrite현재 상태가 readwrite 일때Input, secret, textarea,
xforms-required현재 상태가 required 일때Input, secret, textarea,
xforms-optional현재 상태가 optionalInput, secret, textarea,
xforms-enabled현재 상태가 enabledInput, secret, textarea,
xforms-disabled현재 상태가 disabledInput, secret, textarea,
xforms-submint-done서밋을 보내고 올바른 값을 받았을때submitInfo
xforms-submit-error서밋을 보내지 못하거나 올바른 값을 받지 못했을때model
xforms-link-error 
(xlink:href 의 경우)
링크될 파일이 없거나 파일이름이 잘못되어 파일 또는 URL 정보를 찾지 못할때model

※ select controls : radio, checkbox, listbox, combo

Posted by 사라링

<script type="javascript" ev:event="onclick">
     <![CDATA[
      if(iviewer_myList.currentStyle.width < 630 ) {
       iviewer_myList.attribute("width") = "630px";
      }else {
       iviewer_myList.attribute("width") = "228px";
      }
      butCha.attribute("left") = iviewer_myList.currentStyle.left + iviewer_myList.currentStyle.width -2;
      changeGroup.attribute("left") = iviewer_myList.currentStyle.left + iviewer_myList.currentStyle.width + butCha.currentStyle.width;
      body.dispatch("onwindowresize");
     ]]>
    </script>
   </button>
  </group>
  <script type="javascript" ev:event="onwindowresize">
   <![CDATA[
   if(iviewer_myList.currentStyle.width < 630 ){
    changeGroup.attribute("width") = group_workspace.currentStyle.width - 255;
   }else{
    changeGroup.attribute("width") = group_workspace.currentStyle.width - 670;
   }
   switch1_change.attribute("height") = group_workspace.currentStyle.height - 390;
   ]]>
  </script>

'트러스트폼' 카테고리의 다른 글

트러스트폼의 화면 구성도  (0) 2012.07.12
트러스트폼 이벤트  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 엘리멘트  (0) 2012.07.12
Posted by 사라링

//----------------------★그리드의 전체체크
<!--//</instance>밑에//-->

<script type="javascript" ev:event="xforms-ready">
 <![CDATA[
  
//캡션 영역에 체크박스를 설정한다
  datagrid1.fixedcellcheckbox(0, datagrid1.colRef("save"), false) = true;
 ]]>
</script>

//그리드안의col도
<col ref="save" type="checkbox"/>

//----------------------★그리드의 컬럼,데이터들 문자열숨김
ellipsis = true;
//(CSS에 적용하려면 ellipsis : true;)

//----------------------★그리드의 마지막컬럼을 width에 딱맞게
extendlastcol = scroll;
//(CSS에 적용하려면 extendlastcol : scroll;)


//----------------------★radio컨트롤의 switch사용
<switch id="switch1" style="left:30px; top:30px; width:205px; height:70px; "> 
   <case id="case1" selected="true"> 
       <input id="input1" style="left:50px; top:25px; width:100px; height:20px; "/> 
   </case> 
   <case id="case2"> 
       <button id="button1" style="left:45px; top:25px; width:100px; height:20px; "> 
           <caption>button1</caption> 
       </button> 
   </case> 
</switch>

 <select1 id="select11" ref="/root/select" appearance="minimal" style="left:250px; top:35px; width:100px; height:20px; "> 
  <choices> 
      <item> 
          <label>case1</label> 
         <value>1</value> 
      </item> 
      <item> 
          <label>case2</label> 
          <value>2</value> 
      </item> 
  </choices> 
  <script type="javascript" ev:event="xforms-select"> 
      <![CDATA[ 
      if ( root.select.text == 1 ) 
      { 
          model.toggle("case1"); 
      } 
      else if ( root.select.text == 2 ) 
      { 
          model.toggle("case2"); 
      } 
      ]]> 
  </script> 
 </select1>


//----------------------★datagrid컨트롤의 핸드폰번호output의 출력방법(999-9999-999)
for(var i = 1 ;  i <= model.getValue("/dbio_total_count_") ;i++)
{ 
 
//alert(model.getValue("/root/dis/data/dis_CnncIntMPatMultiDto/CnncIntMPatListDto/cnncIntMPatDTO["+i+"]/thmoRvnRt"));
 jc_datagrid.valueMatrix(i,col) = "";
}
//for
 /*parseFloat(numstring) 
 numstring 인수는 부동 소수점 숫자를 포함한 문자열입니다.  
 parseFloat 메서드는 numstring에 포함되어 있는 숫자에 해당하는 숫자 값을 반환합니다. 
 numstring의 접두사를 부동 소수점 숫자로 구문 분석할 수 없으면 NaN(숫자 아님)이 반환됩니다. 
 parseFloat("abc")    // NaN을 반환합니다.
 parseFloat("1.2abc") // 1.2를 반환합니다.
 */

//----------------------★input컨트롤의 format을 정하고싶을때

 input1.attribute("format") = "999999-9999999";
 input1.refresh();
 
 

//----------------------★라디오버튼이바뀔때 초기화
<script type="javascript" ev:event="xforms-value-changed">
 <![CDATA[       
  if (radio1.value == 1) 
  { 
   model.resetInstanceNode("/root/dis/data/dis_CsSrchInListDTO/csSrchInDTO");
   model.refresh();
  } 
  else if (radio1.value == 2) 
  { 
   model.resetInstanceNode("/root/dis/data/dis_CsSrchInListDTO/csSrchInDTO");
   model.refresh();
  }   
 ]]>
</script> 
 
 
 
//----------------------★엔터키이벤트
<script type="javascript" ev:event="onkeyup">
 <![CDATA[
  if(event.keyCode == 13) 
  {
   model.setFocus("button1");
   button1.dispatch("DOMActivate");
  }
 ]]>
</script>
 


<!-- 체크박스 라디오 이미지를 쓰시오 checkimage="checkedRadioImage.bmp" uncheckimage="unCheckedRadioImage.bmp"-->


//----------------------★그리드 저장버튼 클릭 시 빈 row 삭제 코드
var _grid = datagrid1;      //그리드 ID

for(var i=_grid.rows-_grid.fixedRows; i>=_grid.fixedRows; i--) 
{
 var nodePath = _grid.nodeset+"["+i+"]/*";
 if(model.getXPathValue("count-non-empty("+nodePath+")") == "0") 
 {
  _grid.deleteRow(i, false);
 }
}
_grid.refresh();


//----------------------★switch tab button
<!--//스위치//-->
<switch id="switch1" style="left:25px; top:25px; width:960px; height:500px; ">
 <case id="case1" selected="true">
  <iviewer id="iviewer1" src="JC60301_btn1.xrw" style="left:0px; top:0px; width:100%; height:600px; "/>
 </case>
 <case id="case2">
  <iviewer id="iviewer2" src="JC60301_btn2.xrw" style="left:0px; top:0px; width:100%; height:600px; "/>
 </case>
</switch>
<!--//스위치//-->


//----------------------★그리드의 체크
//save 하지 않을 행들을 확인한다 (체크되지 않은 행들)
var exportfalserows = "";
for(var i=datagrid1.fixedRows;i<datagrid1.rows;i++)
{
 if(datagrid1.valueMatrix(i, datagrid1.colRef("save")) == "false")
 {
  if(exportfalserows != "")
   exportfalserows += ","+i;
  else
   exportfalserows += i;
 }
}


//----------------------★콤보-공통코드 일부만 셋팅하기
combo1.nodeset="/root/comboData/masterNm/item[value='01' or value='02' or value='03']"

//01로 시작하는 item의 필터링 xpath식은 아래와 같이 해주시면 됩니다.
item[starts-with(value, '01')]

/*
위와 같이 해 주시면 01로 시작하는 item만을 가져올 수 있고, 
두번째 질문과 같이 시작하는 문자가 정해져 있지 않다면
위의 xpath식의 빨간 색 부분을 미리 변수에 담아두어서 콤보의 nodeset을 동적으로 바꿔주시면 됩니다.
*/

var str = "G";

combo1.choices.itemset.attribute("nodeset") = "/root/comboData/item[starts-with(value, '" + str + "')]";


//----------------------★데이터그리드 숫자row
rowheader="seq"

//----------------------★데이터그리드 merge하기(같은속성-데이터,컬럼,타이틀끼리)
mergecells="byrowrec"

/* bycol : 상하만 머지를 한다.
 byrow : 좌우만 머지를 한다.
 bycolrec : 상하좌우를 모두 머지한다. 상하 머지를 우선 적용한 후 좌우 머지를 한다.
 byrowrec : 상하좌우를 모두 머지한다. 좌우 머지를 우선 적용한 후 상하 머지를 한다.
 byrestriccol : 상하만 머지를 한다. 첫번째 열부터 순서대로 머지를 한다. 머지를 할 영역은 이전 열의 머지 결과에 의해 결정된다.
 byrestricrow : 좌우만 머지를 한다. 첫번째 행부터 순서대로 머지를 한다. 머지를 할 영역은 이전 행의 머지 결과에 의해 결정된다
*/

//----------------------★데이터그리드의 데이터의 내용에 따라 높이 자동조절(텍스트가 길어지면 다음줄로)

autoresize="true"
//셀 내용의 길이에 따라 행의 높이를 자동으로 조절하도록 설정하는 속성


//----------------------★데이터그리드 부분합계구하기
datagrid1.subtotalposition="below"; 
//추가된 행의 위치는 
   "above": 상단에 삽입
   "below": 하단에 삽입

//datagrid.subtotal(SubtotalType type, Integer groupColumn, Integer totalColumn, [String format], [String style], [Integer captionColumn], [String caption], [Boolean fillText]);

/*
SubtotalType type : sutotal 타입 
     - "average" : 평균 값
     - "clear" : 모든 subtotals를 클리어 한다.
     - "count" : 행의 갯수
     - "max" : 가장 큰 값
     - "min" : 가장 작은 값
     - "percent" : 모든 더해진 값의 퍼센트
     - "sum" : 더한 값
Integer groupColumn : subtotal 계산을 할 때 데이터를 분류하는 기준이 되는 열의 index 
Integer totalColumn : subtotal 을 수행할 값들이 있는 열의 index 
[String format] : subtotal 행의 포맷 
[String style] : subtotal 행의 스타일 
[Integer captionColumn] : subtotal 행의 제목을 표시할 열의 index. default 는 groupColumn 과 동일하다.
[String caption] : subtotal 행의 제목. default 는 groupColumn 의 이전행의 텍스트와 동일하다. 
[Boolean fillText] : 첫번째 열부터 그룹 열 전까지 이전 행의 텍스트를 subtotal 행에 복사할 지 여부. true 로 설정되면 이전 행의 데이터가 복사되어 merge 상태가 이어질 수 있다. default 는 false (이전행의 값을 복사하지 않음) 
     - true
     - false 
*/ 


//----------------------★탭버튼 그룹으로 관리하기
group="case1" 
//group이 같은 버튼들 중 하나가 선택 되면 다른 버튼들은 선택이 해제된다.

groupalign="user"   
/*그룹 버튼들의 모양을 지정하는 속성이다.
top 으로 설정하면 페이지의 위쪽에 적용할 수 있는 모양으로 자동으로 바뀌고, bottom 으로 설정하면 페이지의 아래쪽에 적용할 수 있도록 모양이 바뀌게 된다
*/

//----------------------★창 열때 윈도우사이즈 고정하기
//창 사이즈고정
window.width = "500";
window.height = "500";

//----------------------★데이터그리드 특정  컬럼만 이벤트 실행
<script type="javascript" ev:event="onclick">
 <![CDATA[
  if(datagrid1.isCell(event.target))  
  {
   if(datagrid1.col == "8")          
   {
    alert("팝업열기");
    
   }
  }
 ]]>
</script> 


//----------------------★데이터그리드 헤더 타이틀 줄바꿈
해당그리드의 col선택하고 Alt + Enter

단위&#xA;(원)
(Alt + Enter)치면 된다
//"\n"


//----------------------★데이터그리드 로딩시 설정
//컬럼체크박스bool
datagrid1.fixedcellcheckbox(0,0) = true;   
   
//로딩시그리드빈줄삭제
model.removeNodeset(datagrid1.nodeset);
//datagrid1.deleteRow(datagrid1.fixedRows);


//----------------------★컨트롤에 단축키 지정하기
accesskey="ctrl+a"
/*
지정된 컨트롤에 접근하기 위한 단축키를 설정할 수 있다.
기본적으로 accesskey 속성에 지정한 키를 누르면 해당 컨트롤에 onaccesskey 이벤트와 DOMActivate 이벤트가 순차적으로 발생한다.
형식 : [namedkey | keycode()] + …
* named key
insert, delete, home, pageup, pagedown, end, backspace, pause, print, enter, tab, escape, up, down, left, right, ctrl, alt, shift
f1..f12, 0..9, a..z  (a..z 는 대소문자 구분없이 사용하고, alt 키는 지원하지 않는다)
* keycode function
keycode(code) : 주의 keycode() 에서 keycode 와 ( 를 붙여 써야한다.
*/

//----------------------★그리드 컬럼 정렬하기
datagrid.colsort(0) = "asc";
/*"asc" : 오름차순으로 소팅되도록 설정
- "desc" : 내림차순으로 소팅되도록 설정
- "none" : 소팅대상에서 제외되도록 설정 
*/

//----------------------★그리드 정렬
explorerbar 
/* sort : 사용자가 열의 헤더를 클릭, 각 열의 데이터를 정렬 할 수 있다.
ㅁ move : 사용자가 열의 헤더를 드래그하여 위치를 재배열 할 수 있다.
ㅁ sortshow : sort 기능을 하며 헤더에 작은 화살표시로 정렬 방식을 표현 (오름차순, 내림차순)
ㅁ sortmove : sort, move 기능을 동시에 한다.
ㅁ sortshowmove : shortshow, move 의 기능을 동시에 한다.
*/


//----------------------★그리드 정렬후 이벤트
<script type="javascript" ev:event="onaftersort">
     <![CDATA[
      
//정렬해도 인덱스 맞게 가져오는
      datagrid1.gridToInstance();  
     ]]>
</script>


//----------------------★후처리시 조건값에 따라 그리드 체크박스 disabled처리
for(var i=1; i<datagrid1.rows; i++)
{
 datagrid1.isReadOnly(i, 0, i, 0) = true;
 
//datagrid.isReadOnly(row(줄시작점),col(컬럼시작점),row(줄끝점),col(컬럼끝점) = true; 
}



//----------------------★콤보에 선택된 인덱스 반환
var index = combo1.focusIndex;
/*리스트DTO의 값을 단일DTO로 value값을 넣어줘야할 때 유용하게 
현재 포커스를 가진 아이템의 인덱스를 반환한다.  초기에는 focusIndex가 -1로 셋팅 되어 있다. 
포커스가 다른 컨트롤로 이동하더라도 combo의 focusIndex는 마지막에 포커스가 간 아이템의 인덱스를 저장한다 
*/

ex)
<script type="javascript" ev:event="xforms-value-changed">
      <![CDATA[
       var index = companyCb.focusIndex + 1;
       
//instance는 1부터 시작하니까

       msgNm.value = companyCb.label;       
       msgCtText.value = model.getValue("/root/dis/data/dis_ShmsMagListDTO/shmsMagDTO["+index+"]/msgCt");
       //msgCtText.value = companyCb.value;
       
       model.refresh();
      ]]>
     </script>


//----------------------★인스턴스 보기
// 인스턴스 보기
window.viewInstance();


//----------------------★그리드 타이틀 사이즈 셋팅
// 인스턴스 보기
datagrid1.rowHeight(1) = 40;
/*그리드 특정 행의 높이 값을 설정하거나 반환한다.
데이터 행과 fixed row 모두 제어가 가능하다.
rowHeightMax property 와 rowHeightMin property 에 설정되어 있는 최대 최소 값 범위 내에서 설정을 해야 하면, 
이 범위를 벗어났을 경우에는 최대 또는 최소 값으로 설정이 된다*/


'트러스트폼' 카테고리의 다른 글

트러스트폼 이벤트  (0) 2012.07.12
트러스트폼 버튼 엑션(늘리고 줄이고)  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 엘리멘트  (0) 2012.07.12
트러스트폼 xml 기본 문법  (0) 2012.07.12
Posted by 사라링


1. 
편집  공통 단축키 
 

이름

단축키

설명

미리 보기

(Application)

F6

xrw 문서 미리보기 수행

(Application을 통하여 수행)

미리 보기

(Browser)

F5

xrw 문서 미리보기를 수행

(Browser를 통하여 수행)

새로 만들기

Ctrl+N

빈문서 만들기

(만들어진 문서의 이름은 순서에 따라 ‘Form1, Form2, Form3, …….’과 같이 자동으로 설정됩니다.)

열기

Ctrl+O

xrw 파일 열기

저장

Ctrl+S

현재 작업 중인 문서를 저장

다시실행

Ctrl+Y

취소한 작업을 취소 이전의 상태로 복구

(반복해서 실행하면 최근에 취소한 작업이 차례대로 다시 복구됩니다.)

실행취소

Ctrl+Z

문서에 가장 최근 편집한 작업을 취소

(반복해서 실행하면 최근 작업이 차례대로 취소됩니다.)

전체 창 토글

F4

전체 속성 창을 화면에 표시하거나 숨김



3. 코드 보기 단축키  

이름

단축키

설명

들여쓰기 

Tab

Tab 사이즈 정보만큼 들여쓰기

(문장이 끝나서 다음 줄로 넘어갈 때 강제로 엔터를 치면 다음 문장의 맨 앞은 위 문장의 들여쓰기 효과가 그대로 남아있게 됩니다.)

내어 쓰기

Shift+Tab

Tab 사이즈 정보만큼 내어 쓰기

왼쪽 단어단위 이동

Ctrl+

왼쪽으로 커서 이동시 단어 단위로 이동

오른쪽 단어단위 이동

Ctrl+

오른쪽으로 커서 이동시 단어 단위로 이동

함수 매개변수 정보 표시

Ctrl+Space

함수의 매개변수 정보를 표시

잘라내기

Ctrl+X

선택된 영역내의 소스코드 잘라내어 클립보드에 저장

복사하기

Ctrl+C

선택된 영역내의 소스코드 복사하여 클립보드에 저장

붙여넣기

Ctrl+V

클립보드에 저장된 소스코드를 붙여넣기

찾기

Ctrl+F

소스코드 내의 단어 찾기

찾아 바꾸기

Ctrl+H

선택된 문자열을 다른 문자열로 바꾸기

전체선택

Ctrl+A

소스코드 전체를 선택하기

주석처리

Ctrl+L

선택한 소스코드에 주석처리하기




2. 디자인 보기 단축키

이름

단축키

설명

텍스트편집

F2

선택한 컨트롤의 속성 중 TEXT의 내용을 변경

복사

Ctrl+C

선택한 컨트롤을 복사하여 클립보드에 저장

잘라내기

Ctrl+X

선택한 컨트롤을 잘라내어 클립보드에 저장

붙여넣기

Ctrl+V

클립보드에 저장된 컨트롤을 문서에 붙여넣기

모두 선택

Ctrl+A

현재 문서의 모든 컨트롤을 선택

컨트롤 이동

컨트롤을 위쪽으로 5px 이동

컨트롤을 아래쪽으로 5px 이동

컨트롤을 왼쪽으로 5px 이동

컨트롤을 오른쪽으로 5px 이동

컨트롤 1px 단위  이동

Shift+

컨트롤을 위로 1px 이동

Shift+

컨트롤을 아래로 1px  이동

Shift+

컨트롤을 왼쪽으로 1px  이동

Shift+

컨트롤을 오른쪽으로 1px  이동

컨트롤 크기 조절

Ctrl+

컨트롤의 높이를 5px 줄임

Ctrl+

컨트롤의 높이를 5px 늘림

Ctrl+

컨트롤의 가로 폭을 5px 줄임

Ctrl+

컨트롤의 가로 폭을 5px 늘임

컨트롤 1px 단위 크기 조절

Ctrl+Shift+

컨트롤의 높이를 1px 줄임

Ctrl+Shift+

컨트롤의 높이를 1px 늘림

Ctrl+Shift+

컨트롤의 가로 폭을 1px 줄임

Ctrl+Shift+

컨트롤의 가로 폭을 1px 늘임

종횡비 유지 컨트롤 크기 조절

Shift+[drag]

현재 컨트롤의 종횡비 (가로세로 비율)을 유지 하면서 크기를 변경

컨트롤 연속 생성

Ctrl+[click]

컨트롤 메뉴에서 선택된 컨트롤을 마우스 클릭 때마다 선택한 컨트롤과 같은 종류의 컨트롤을 생성

컨트롤 드래그 복사

Ctrl+[drag]

컨트롤 클릭 후 <Ctrl>키를 누른 상태에서 드래그 하면 선택된 컨트롤이 복사됨

컨트롤 같은 폭 으로

W

여러 컨트롤 선택 후 W

(선택된 컨트롤 들을 기준 컨트롤과 같은 폭으로 변경)

컨트롤 같은 높이로

H

여러 컨트롤 선택 후 H

(선택된 컨트롤들을 기준 컨트롤과 같은 높이로 변경)

컨트롤 같은 크기로

S

여러 컨트롤 선택 후 S

(선택된 컨트롤들을 기준 컨트롤과 같은 폭과 높이로 변경)

왼쪽 맞춤

L

여러 컨트롤 선택 후 L

(선택된 컨트롤들을 기준 컨트롤 왼쪽에 맞춤)

위쪽 맞춤

T

여러 컨트롤 선택 후 T

(선택된 컨트롤들을 기준 컨트롤 위쪽에 맞춤)

오른쪽 맞춤

R

여러 컨트롤 선택 후 R

(선택된 컨트롤들을 기준 컨트롤 오른쪽에 맞춤)

아래쪽 맞춤

B

여러 컨트롤 선택 후 B

(선택된 컨트롤들을 기준 컨트롤 아래쪽에 맞춤)

컨트롤간 

폭 맞춤

M

여러 컨트롤 선택 후 M

(선택된 컨트롤들의 폭을 일정하게 변경)

컨트롤간

높이 맞춤

N

여러 컨트롤 선택 후 N

(선택된 컨트롤들의 높이를 일정하게 변경)

컨트롤

정방향 이동

Shift+[drag]

컨트롤 클릭 + Alt키를 누른 후 상하좌우로 평행하게 이동

컨트롤 선택

(소스코드 이동 무시)

Shift+[click]

컨트롤을 클릭하면 ‘코드 보기’로 전환 시 선택한 컨트롤과 무관하게 이전에 편집하던 코드 위치가 이동 되지 않음

(스크립트 작성 시 다른 컨트롤 ID를 확인할 때 사용)

컨트롤 선택

(소스코드 이동)

[click]

컨트롤을 클릭하면 소스보기로 전환 시 소스코드 상에 선택한 컨트롤의 코드위치로 이동됨

다음 컨트롤 선택

Tab

디자인 보기에서 다음 컨트롤 선택

이전 컨트롤 선택

Shift+Tab

디자인 보기에서 이전 컨트롤 선택


출처 : TrustForm 4.0 Help

'트러스트폼' 카테고리의 다른 글

트러스트폼 버튼 엑션(늘리고 줄이고)  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 엘리멘트  (0) 2012.07.12
트러스트폼 xml 기본 문법  (0) 2012.07.12
트러스트 폼이란?  (0) 2012.07.12
Posted by 사라링


copyNode 
src노드의 모든자식노드들은 des노드의 하위에 복사

노드를 복사하여 반영시키는 인스턴스의 노드들을 변경시키므로 refresh 함수를 사용하여 변경된 인스턴스를 반영시켜야한다


setValue
model.setValue(String ref, String value, [Boolean cdata]);

String ref            : node 에 해당하는 XPath 식 또는 노드 객체 
String value        : 값 
[Boolean cdata] : CDATA Section을 사용해서 값을 입력할지 여부를 설정 
     - true
     - false 

맵핑된 컨트롤에 데이터를 반영하기위해서는 setValue함수를 사용한 후에 refresh 함수를 사용하여 반영시켜야한다

'트러스트폼' 카테고리의 다른 글

트러스트폼 버튼 엑션(늘리고 줄이고)  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 xml 기본 문법  (0) 2012.07.12
트러스트 폼이란?  (0) 2012.07.12
Posted by 사라링

  
XML
eXtensible Markup Language의 약자로 새로운 Markup 언어를 정의하기 위해 W3C에서 만든 메타 언어입니다. 
HTML과는 달리 새로운 태그를 정의하여 확장하고 데이터를 기술할 수 있는 특징을 가지고 있습니다.

XML 특징
 -유연하고 개방적인 표준 기반 형식을 채택함으로써 뛰어난 상호 운영성을 제공
 -기존 Web 기술(인터넷기반의 프로토콜 및 메커니즘)과 함께 사용 가능
 -프로그래밍 언어에 대해 독립적이고 여러 Application을 사용 가능하도록 지원
 -Unicode 기반

XML Document의 종류
 Well-formed document (잘 짜인 문서)
- XML 1.0 recommendation 스펙을 준수하여 작성된 문서를 의미
- TrustForm System에서는 Business Data를 저장하는 개념인 인스턴스를 구성하는 용도로 사용됨
 Valid document (유효한 문서)
- Well-formed document이면서 동시에 XML로 개발된 특정 Markup 언어에 맞게 작성된 문서를 의미
- TrustForm System에서는 XForms의 Host language 개념으로 XML 기반의 XHTML이 사용됨


XForms
HTML Form을 대체하기 위해 W3C에서 만든 XML 기반의 차세대 Form 기술입니다

XForms 특장점
 -Next generation of HTML forms
 -Richer and more flexible than HTML forms
 -Will be the forms standard in XHTML 2.0
 -Platform and device independent
 -Separates data and logic from presentation
 -Uses XML to define form data
 -Stores and transports data in XML documents
 -Contains features like calculations and validations of forms
 -Reduces or eliminates the need for scripting
 -W3C Recommendation

XForms 동작방식
 단독으로 수행되지 않고 다른 Markup 언어(Host language) 내부에 위치하여 사용됨
 Host language 내부에 XForms을 적용함으로써 다양한 클라이언트를 수용할 수 있음
 TrustForm System에서는 Host language로 XHTML이 사용됨

XForms 동작방식
 단독으로 수행되지 않고 다른 Markup 언어(Host language) 내부에 위치하여 사용됨
 Host language 내부에 XForms을 적용함으로써 다양한 클라이언트를 수용할 수 있음
 TrustForm System에서는 Host language로 XHTML이 사용됨

XForms 구성요소
 Model : Data section
- Form 내부에서 사용되는 데이터를 저장하고, 가공하거나 서버로 전달하는 역할
 UI controls : Presentation section
- User Interface를 구성하는 컨트롤
 Event handlers : Logic section
- User Interface에서 발생하는 이벤트를 처리하는 부분으로써 TrustForm System에서는 JavaScript나 VBScript 언어를 사용가능

XForms 문서구조
-HTML Form과 마찬가지로 화면을 구성하는 기본적인 컨트롤에 대한 정의가 있으며, XML 데이터를 서버와 통신하는 방법에 대한 정의도 함께 있습니다. XForms 문서는 크게 Data부분과 UI부분으로 구분됩니다.
 Head 영역
           -  Head 구간은 데이터와 관련된 객체들과 Global Script가 위치하게 됩니다
    Body 영역
           - Body 영역은 각 컨트롤 및 컨트롤의 이벤트를 처리하는 스크립트가 함께 오게 됩니다

XPath
XML 문서의 데이터 부분을 참조하기 위한 W3C의 표준 문법 규약으로 XML Element를 참조하기 위하여 파일 시스템에서 사용되는 개념과 유사한 경로(Path)를 사용합니다. 
XForms 스펙에서 분리된 데이터와 UI 컨트롤을 맵핑하기 위한 용도로 사용됩니다.

XPath 특장점
 -XML 문서의 특정 부분을 자유 자재로 접근할 수 있는 기능 제공
 -파일 시스템의 디렉터리 구조와 유사한 개념으로 절대경로와 상대 경로를 지원
 -Node, Date, Time, String, Number, Boolean 데이터타입과 관련된 Method들을 제공
 -XML DOM 트리를 구성하는 노드나 노드셋에 접근하기 위해 Location Path와 XPath Method로 구성된 XPath expression을 사용하여 데이터에 접근하거나 검색할 수 있음



XML 기본 문법
 
인스턴스는 처음에 설명한 것과 같이 XML 문법을 사용합니다. 따라서 인스턴스를 구성하기 위해서는 기본적인 XML 문법에 대해서 알아야 합니다. 
물론 TrustForm에서 제공하는 기능인 인스턴스 창을 이용하여서 구성하면 간단한 인스턴스는 XML 기본문법을 몰라도 사용가능합니다. 
그러나 좀 더 복잡하고 많은 데이터를 다루기 위해서는 기본적인 XML 문법을 이해하고 인스턴스를 설계해야합니다.

 

1. XML 기본문법

XML 문법 중 가장 기본문법은 “Well-Formed XML”입니다.

Well-Formed XML 이란 XML 1.0 Spec에 정의된 특정문법규칙을 따르는 XML입니다.

 

XML 1.0 Spec은 다음과 같습니다.

1. 모든 Start-Tags는 하나의 End-Tags와 짝으로 구성되어야만 합니다.

2. Tag는 겹쳐서 쓸 수 없습니다.

3. XML 문서는 하나의 Root Element만을 갖습니다.

4. Element 이름은 Element 이름 작성규칙을 따릅니다.

5. XML은 대소문자를 구분합니다.

6. XML은 Tag안의 공백을 유지합니다.

 

1 <root> 
2       <name> 
3               <first>John</first> 
4               <middle>Fitzgerald Johansen</middle> 
5               <last>Doe</last> 
6       </name> 
7 </root>

 

위의 XML 문서는 Well-Formed XML 문서입니다. 위의 XML 문서를 살펴보면서 Well-Formed XML에 대해서 알아보겠습니다.

XML 문서를 보면 “<”와 “>”로 이루어진 부분이 있습니다. 이 부분이 Element입니다. Element는 XML 문서 내에서 데이터를 표현하기 위한 태그정의와 데이터를 말합니다. 위의 XML 문서에서 Element는 <root>, <name>, <first>, <middle>, <last>가 있습니다. 각각의 Element는 Start-tag와 End-tag로 이루어져 있습니다. Start-tag에 ‘/’를 붙여주면 End-tag가 됩니다.

 

1 <root> <name> <first> <middle> <last> <- Start-tag 
2 </last> </middle> </first> </name> </root> <- End-tag

 

위와 같이 Start-tag와 End-tag는 겹쳐지지 않고 순서대로 사용됩니다. 만약 위의 소스에서 <first>와 <middle> 사이에 </name>가 온다면 위의 XML 문서는 Well-Formed XML이 아닙니다.(2번 위반)

 

1 <root> <name> <first> </name> <middle> <last> 
2 </last> </middle> </first> </root>

 

또 다음과 같이 <root> Element가 XML 문서의 모든 Element를 포함하고 있지 않는다면 Well-Formed XML이 아닙니다.(3번 위반)

 

1 <root> 
2 </root> 
3 <name> 
4   <first>John</first> 
5   <middle>Fitzgerald Johansen</middle> 
6   <last>Doe</last> 
7 </name>

 

위의 XML 문서는 Root Element가 <root>와 <name> 두개가 존재하고 있습니다. (Root Element는 대부분 <root>로 사용하지만 꼭 <root>를 사용할 필요는 없습니다.) 위의 XML 문서에서 <root></root>를 제거하면 Well-Formed XML 조건을 만족하게 됩니다.

마지막으로 Element는 사용자가 정의할 수 있습니다. 즉 사용자가 임의로 이름을 붙여서 작성할 수 있습니다. 그러나 Element를 작성하는 데는 일정한 형식이 있습니다. Element 이름 작성 규칙에 대해서는 다음 장에서 자세하게 알아보겠습니다.

이와 같이 기본적인 XML 문법을 만족해야만 XML 문서로 사용할 수 있습니다.

 

2. Element

XML 기본문법을 살펴보면서 간단하게 Element에 대해서 알아봤습니다. Element는 XML 문서 내에서 데이터를 표현하기 위한 태그정의와 데이터를 의미합니다. XML문서에서 Element의 이름은 사용자가 정의할 수 있습니다. 즉 <이름>, <나이>, <주소> 와 같은 것들이 XML 문서에서 모두 유효한 Element입니다. 그러나 Element를 정의할 때 Element 이름 작성규칙에 따라 정의해야만 합니다. 이를 위반하면 Well-Formed XML이 아니므로 XML 문서로 사용할 수 없습니다.

Element 이름 작성규칙은 다음과 같습니다.

1. 시작문자는 문자 또는 ‘_(Under Line)’만이 올 수 있습니다.

2. 첫 문자 다음에는 ‘-’, ‘.’, 숫자가 올 수 있습니다.

3. ‘:’ 문자를 포함할 수 없습니다.(NameSpace의 예약어임)

4. 대소문자 구분 없이 ‘XML’또는 ‘xml’로 시작할 수 없습니다.

5. ‘<’ 문자 뒤에 공백허용이 안됩니다. ‘>’앞에는 공백이 허용됩니다.

(주의! Empty Element인 ‘/>’ 사이에는 공백이 허용되지 않습니다.)

 

Element 이름 작성규칙에 대하여 올바르게 작성된 Element와 틀리게 작성된 Element의 간단한 예를 보면서 알아보겠습니다.

 

올바른 이름 작성규칙 적용의 예

<First.Name></First.name>

<First-Name></First-Name>

 

잘못된 이름 작성규칙 적용의 예

<XML-FirstName></XML-FirstName> (4번 규칙 위반)

<1.FirstName></1.FirstName> (1번 규칙 위반)

<First=Name></First=Name> (2번 규칙 위반)

<First Name></First Name> (5번 규칙 위반)

 

3. Empty Element

Empty Element란 내용이 없는 Element를 의미합니다.

 

1 <name> 
2   <first>John</first> 
3   <middle></middle> 
4   <last>Doe</last> 
5 </name>

 

위의 XML에서 <middle> Element와 같이 내용이 없는 Element인 경우

축약된 형태로 표현이 가능합니다.

다음의 두 XML은 동일한 의미를 갖습니다.

 

1 <middle></middle> 
2 <middle/>

 

4. Attribute

이번에는 Attribute에 대해서 알아보겠습니다. Attribute란 Element의 내용을 보충해 주는 속성입니다. 속성의 사용은 사용자가 정의하기에 따라서 달라질 수 있습니다. 다음 예를 살펴보면 속성의 사용이 어떤 의미를 갖는지를 알 수 있습니다.

 

1 <root> 
2   <cd serial="AB1102"> 
3       <title>CD1</title> 
4       <artist>Singer</artist> 
5       <date>20051215</date> 
6   </cd> 
7 </root>

 

위의 XML 문서는 CD의 정보를 보여주고 있습니다. <cd> Element를 살펴보면 Attribute로 “serial”을 포함하고 있습니다. 이 ‘serial' 속성은 특정 Application에서는 필요로 하지만 또 다른 Application에서는 필요로 하지 않을 수도 있습니다. 위의 ’serial'을 <cd> Element에 속한 다른 Element들과 같이 <serial> Element로 사용할 수 있지만 위와 같이 Attribute로 사용해서 ‘serial' 정보가 특정 Application에서만 사용되는 정보로 구분할 수가 있습니다.

 

Attribute도 Element와 같이 작성 규칙을 갖고 있습니다. Attribute의 작성규칙에 대해서 알아보겠습니다.

1. Start-Tag에 사용합니다.

2. 반드시 Name과 Value가 존재해야 합니다.

3. Element 이름 작성규칙을 따라야 합니다.

4. 하나의 Element안의 Attribute는 유일해야 합니다.

 

올바르게 작성된 Attribute와 틀리게 작성된 Attribute의 예를 살펴보면서 설명하겠습니다.

올바른 Attribute 예

<Name NickName="SmileMan">John</Name>

 

잘못된 Attribute 예

<Name>John</Name NickName="SmileMan"> (1번 규칙 위반)

<Name NickName>John</Name> (2번 규칙 위반)

<Name NickName="SmileMan" NickName="SuperMan">John</Name> (4번 규칙 위반)

 

잘못된 Attribute 예에 대해서 몇 가지만 살펴보겠습니다. 두 번째 예는 Attribute가 Attribute 이름만 있고 값이 존재하지 않는 경우입니다. 이렇게 값이 존재하지 않는 Attribute를 사용할 때는 Value 부분을 쌍 따옴표(“”) 또는 홀 따옴표(‘’)를 사용해서 값이 없는 Attribute라는 것을 명시해 줘야 합니다. 세 번째 예는 하나의 Element에 동일한 이름을 갖는 Attribute 두개가 동시에 사용된 경우입니다. 이런 경우 두개의 Attribute를 구분할 수 없게 되므로 에러가 발생하게 됩니다.

 

5. 주석

XML 문서에서도 주석을 사용할 수 있습니다. 주석 역시 간단한 작성규칙이 있습니다. 주석의 작성규칙은 다음과 같습니다.

1. <!-- 문자열로 시작해서 --> 문자열로 종결됩니다.

2. Tag 안에는 사용할 수 없습니다.

3. “--” 문자를 사용할 수 없습니다.

 

다음은 주석이 사용된 예입니다.

 

1 <root> 
2   <!-- 다음은 이름을 나타내는 Element입니다.--> 
3   <name> 
4       <first>John</first> 
5       <middle>Fitzgerald Johansen</middle> 
6       <last>Doe</last> 
7   </name> 
8 </root>

 

6. Element 내용(PCDATA와 CDATA)

PCDATA와 CDATA에 대해서 알아보겠습니다. 이 두 데이터 타입은 Element의 내용을 표시할 때 사용되는 개념입니다. 다음 예를 보면서 두 데이터 타입에 대해서 알아보겠습니다.

 

1 <name> 
2   <first>John</first> 
3   <middle>Fitzgerald Johansen</middle> 
4   <last>Doe</last> 
5 </name>

 

<first>John</first>는 하나의 Element입니다. 이 Element에서 Start-Tag와 End-Tag사이에 있는 ‘John’이 PCDATA입니다. 이와 PCDATA는 Element의 태그사이에 있는 문자열부분으로 파싱된 문자 데이터(Parsed Character DATA)입니다.

PCDATA에서 사용할 수 없는 예약된 문자들이 있습니다. 예를 들면 “<”와 “&과 같은 문자입니다.

 

1 <비교문>x < 7 && x > 5</비교문>

 

위의 <비교문> Element는 Well-Formed XML이 아닙니다. 그 이유는 <비교문> Element의 내용인 PCDATA가 올바르지 않게 작성되어 있기 때문입니다. XML 처리기는 Element의 내용인 ‘x<7 && x>5’ 부분을 처리하면서 “< 7 && x >”를 하나의 태그로 인식하려고 할 것입니다. 이 부분은 Element 이름 작성규칙 중 5번(공백문자를 포함)을 위반하고 있습니다. 또 이 부분을 넘어간다고 해도 ‘&&’에서 예약어를 사용해서 또 에러가 발생합니다.

이러한 데이터를 Element의 내용으로 사용하는 방법은 두 가지가 있습니다. 첫 번째 방법은 위의 문자들을 이스케이프 문자를 사용해서 표현해주는 방법입니다. 두 번째 방법은 CDATA를 사용하는 방법이 있습니다.

 

6.1. 이스케이프 문자

앞에서 본 것과 같이 두 문자가 발생시키는 오류를 피하려면 ‘<’ 문자를 ‘&lt;’로 바꿔 쓰고 ‘&’ 문자를 &amp;로 바꿔서 쓰면 됩니다. 이렇게 하면 위에서 작성한 XML이 Well-Formed XML이 됩니다.

 

1 <비교문>x &lt; 7 &amp;&amp; x > 5</비교문>

 

XML 처리기는 위에서 사용한 이스케이프문자를 화면에 보여줄 때는 ‘&lt;’와 ‘&amp;’를 ‘<’와 ‘&’ 문자로 바꿔서 보여주게 됩니다.

‘&lt;’와 ‘&amp;’는 엔터티 레퍼런스(entity reference)라고 합니다. XML에는 다음과 같은 엔터티들이 정의되어 있습니다.

 

‣ &amp;  - & 문자

‣ &lt;     - < 문자

‣ &gt;     - > 문자

‣ &apos;  - ' 문자

‣ &quot;  - " 문자

 

6.2. CDATA

만약 이스케이프 문자를 많이 사용하게 되면 문서가 이해하기 힘들어지게 됩니다. 이럴 경우에는 CDATA 섹션을 사용할 수 있습니다.

CDATA 섹션은 파싱되지 않는 데이터(Character DATA)를 의미합니다. 즉 CDATA 섹션에 작성된 텍스트는 XML 처리기가 파싱하지 않습니다.

위에서 작성한 XML 문서를 다음과 같이 CDATA 섹션을 사용하면 Well-Formed XML이 됩니다.

 

1 <비교문><!CDATA[x &lt; 7 &amp;&amp; x > 5]]></비교문>


 

CDATA 섹션은 "<![CDATA["로 시작해서 “]]>”로 끝납니다. 이 사이에 있는 문자열은 모두 사용자가 작성한 그대로 화면에 표시됩니다.

이 CDATA 섹션은 TrustForm을 사용하면서 자주 볼 수 있습니다. 스크립트를 작성할 때 스크립트의 처리부분을 CDATA 섹션을 사용해서 작성합니다.

 

1 <script type="javascript"> 
2   <![CDATA[ 
3   function myFunc(){ 
4       alert("이곳은 스크립트의 CDATA 섹션입니다"); 
5   } 
6   ]]> 
7 </script>

   

위와 같이 스크립트를 사용할 때는 XML 처리기가 스크립트를 파싱하지 않게 CDATA 섹션을 사용해서 분리시킵니다.

 
 
 
출처 : TrustForm4.0  Help

'트러스트폼' 카테고리의 다른 글

트러스트폼 버튼 엑션(늘리고 줄이고)  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 엘리멘트  (0) 2012.07.12
트러스트 폼이란?  (0) 2012.07.12
Posted by 사라링

트러스트 폼이란?

2012. 7. 12. 10:16

트러스트폼 시스템


컴스퀘어 (02-2051-2742, www.comsquare.kr)
● 종류 | X-인터넷 플랫폼 
● 특징 | UI가 미려하며 개발이 용이하다. 
● 평가 | ★★★★

X-인터넷의 개념이 세간에 발표된 지도 어느덧 10년이 다 됐다. 이 기간 동안 X-인터넷은 RIA와 같은 시장을 형성하면서 지속적으로 발전해 왔지만 초기 기대에 비해 시장의 반응은 훨씬 싸늘했다. 그 원인을 마케팅이 부족했기 때문이라고 분석하기도 한다. 그럼에도 국내에서는 금융, 공공을 비롯해 조금씩 시장이 확산되는 추세다. 국내 대표 X-인터넷 업체 중 하나인 컴스퀘어의 트러스트폼 시스템도 현대자동차, 행정자치부, LG카드 등 다양한 분야에서 사용되고 있다. 트러스트폼 시스템은 기존의 C/S 시스템 환경의 장점을 수용하고 새로운 웹 개발 환경에 능동적으로 대처하기 위한 X-인터넷 기반의 웹 개발 솔루션으로 복잡하고 난해한 기업용 애플리케이션 개발에 최상의 개발 환경을 제공하는 웹 개발 툴과 운영환경 솔루션이다.

트러스트폼 시스템의 활용 범위
트러스트폼 시스템은 복잡한 업무용 애플리케이션 UI의 신속한 개발과 유지보수를 위해 C/S와 WEB 아키텍처의 장점을 결합하여 만든 UI 개발 및 운영 솔루션으로 대용량 데이터 처리와 빈번한 트랜잭션이 요구되는 시스템, 복잡한 UI 기능과 로직 처리가 필요한 시스템, 다수의 Legacy 및 Backend 시스템 연동이 필요한 경우에 효과적이다. 이런 특징으로 인터넷을 통해 서비스 되는 업무시스템이나 금융/기업/공공기관 등 복잡한 UI 처리가 필요한 업무시스템, 보험청약서, 대출/카드신청서, 견적/발주서 등의 문서교환 업무시스템에서 주로 사용되고 있다.

특히 개발 및 운영 측면에서 개발 생산성 향상을 위한 Tool 도입이 필요한 경우 혹은 화면 개발과 Business Logic 개발 작업의 분리가 필요한 경우, 빈번한 시스템 변경 및 개선 작업이 예측되는 경우 등에 효과적이다.

트러스트폼은 서버 독립적인 솔루션으로 기존 WEB, WAS 서버 구성에 트러스트폼 서버 라이브러리만 탑재하는 것으로 운용이 가능해 서버 제품에 대한 추가 구입 비용이 들지 않는다. 또한 J2EE와 닷넷 서버에 대한 서버 라이브러리를 제공하고 멀티 벤더 브라우저와 독립 애플리케이션 뷰어도 제공한다.

자체 개발한 리포팅툴로 UI와 보고서 업무를 동시에 지원할 수 있으며, 트러스트폼과 동일한 구조로 즉시 개발에 적용할 수 있고, 뷰어의 크기도 가벼워 운영에 부담을 주지 않는다. 컴스퀘어는 연매출의 20% 이상을 지속적으로 연구개발비로 투자하면서 신뢰할 수 있는 품질을 확보하는 데 최선을 다하고 있다. 그 결과 매년 100% 이상 성장하고 있다. 뿐만 아니라 국제 표준규격 기반으로 UI와 데이터를 구조적으로 완벽하게 분리해 개발된 소스코드의 가독성이 탁월하여 생산성이 높고, 최적화된 소스 코드로 코드 사이즈 최소화했다는 점도 주목할 만하다.

강력한 UI와 개발 용이성
사용자 입장에서 X-인터넷을 선호하는 가장 큰 이유는 표현력이 풍부한 UI 때문이다. 또한 클라이언트의 리소스를 활용하여 가장 큰 효과를 볼 수 있는 부분도 화면을 제어하는 기술이다. 트러스트폼도 엑셀같은 스프레드시트와 유사한 Datagrid와 Multilinegrid를 제공하며, 임포트와 이뷰어 컴포넌트를 이용해 중복되는 UI 영역을 모듈화할 수도 있다. 차트를 활용한 분석화면과 미려한 리포트를 구현할 수 있는 환경도 특징적이다. 로우 및 컬럼을 추가, 삭제하거나 컬럼별 데이터 정렬 / 컬럼 이동 및 고정 / 입력 데이터의 길이에 따른 셀 크기 자동 변경 / 데이터 검색 / Row 또는 Column Cell Merge 등이 가능하다.

컴스퀘어는 X-인터넷은 실행적인 측면을 강조하고 있지만 트러스트폼은 편리한 개발환경을 제공하는 데에도 많은 연구개발을 진행해 왔다. 개발이 쉽고 빠르게 이루어져야 사용자의 요구사항이 신속하게 반영되고 유지보수도 원활하다는 점을 생각해 봤을 때 편리한 개발환경은 반드시 필요하다고 강조한다. 트러스트폼 기반의 UI개발은 서버로직과 관계없이 화면을 개발할 수 있다. 또한 Tech 설계에서의 산출물(IO정의서, 화면 요건정의서 등)을 기반으로 서버의 비즈니스 로직과 화면 개발을 완벽하게 분리, 병행하여 진행할 수 있어 수많은 JSP, Servlet 및 EJB로 이루어진 적용업무시스템 구현 생산성을 향상시켜 줄 수 있다고 강조했다.

네트워크 효율 향상

일각에서는 X-인터넷을 도입할 때 가장 적합한 방법과 기준으로 XML, MDI, Grid 등을 거론한다. 하지만 기술적 접근보다는 실행적 측면으로 접근하는 것이 낫다. 내가 필요로 하는 최종 애플리케이션의 성격을 고려하여 그에 대한 구현과 기능지원이 원활하게 이루어질 수 있고 추후 확장 가능한 구조가 최상인 것. 즉 기대 효과를 고려해야 한다는 의미다. 트러스트폼의 경우 HTML 방식 대비 개발/운영 비용이 획기적으로 개선되며, 응답속도와 네트워크 트래픽이 향상된다. 서버의 비즈니스 로직은 그대로 두고 화면부분만 Trustform을 적용하였을 때를 비교하면, DB 튜닝을 하였을 경우 평균 1.3초의 응답속도 개선에 불과하지만, 트러스트폼을 적용하였을 경우 평균 8.1초의 응답속도가 개선됐다. 벤치마크 테스트 결과 HTML & JAVA APPLET 기반 환경에서 트러스트폼 시스템 도입 후 도입 전에 비해 네트워크 트래픽은 약 69% 감소하고 패킷량은 약 79% 감소하는 결과를 얻었다.

또한 트러스트폼에서 만든 결과물을 프레젠테이션 부분과 데이터부분을 분리하여 운영할 수 있어 화면의 변경가 빈번하지 않지만 매일 사용하는 기업의 업무시스템은 화면의 프레젠테이션 부분을 사용자 PC에 내려놓고 서버와 데이터 트랙잭션만 발생시킴으로서 응답속도와 트래픽 사용량 등을 획기적으로 개선할 수도 있을 것이다.  조규희 기자 khcho@imaso.co.kr

트러스트폼 시스템의 특징

프로트-엔드와 백-엔드 시스템간의 Seamless한 XML 데이터 통신

XForms code의 생성
   - XML 기반의 차세대 web form 국제표준규격 
   - XForms 지원 모든 브라우져/뷰어에서 source code 재사용  
   - UI, Data의 분리로 source code의 식별성 탁월 
   - Online, Offline에서 화면의 컨트롤 가능 
   - 전자정부의 화면으로 탁월 
   - E-Commerce에서의 모든 문서는 XForms 기반으로 전환 예측 

화면에서의 데이터 재사용 가능
   - 다양한 화면 및 프린팅 등에 서버 트랜잭션 없이 활용

HTML 웹 방식보다 최대 98% 네트워크 트래픽 절감

컴포넌트 조립 방식의 뷰어 배포로 사용자 시스템 자원 최소화


'트러스트폼' 카테고리의 다른 글

트러스트폼 버튼 엑션(늘리고 줄이고)  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 단축키  (0) 2012.07.12
트러스트폼 엘리멘트  (0) 2012.07.12
트러스트폼 xml 기본 문법  (0) 2012.07.12
Posted by 사라링

jQuery.slide()

2012. 7. 10. 14:10

.slideUp( [duration] [, callback] )Returns : jQuery

개요 : 슬라이드를 이용해 요소를 숨깁니다.

  • .slideUp( duration [, callback] )
  • duration 시간 값
  • callback 콜백 함수
  • .slideUp( [duration] [, easing] [, callback] )
  • duration 시간 값
  • easing 특수한 효과 함수
  • callback 콜백 함수

.slideUp() 함수는 요소의 height 값을 조작해서 움직임을 만들어 냅니다. 보이게 처리할 때 display 속성값을 jQuery 의 데이터 캐쉬에 저장 해두었다가 나중에 display 를 초기값으로 복원해줍니다. 만일 요소의 display 스타일 속성값이 inline 이었다면, display 속성값이 inline 으로 복원된다는 의미입니다.

시간값(Duration)의 기본값은 밀리세컨드이고, 값이 크면 느린 효과가 나타납니다. 물론 반대는 빨라지겠죠. 'fast' 와'slow' 문자열을 지원하는데, 각각은 200 과 600 밀리세컨드를 의미합니다.

이미지를 예로 보겠습니다.

<div id="clickme">
  Click here
</div>
<img id="book" src="book.png" alt="" width="100" height="123" />
$('#clickme').click(function() {
  $('#book').slideUp('slow', function() {
    // Animation complete.
  });
});
  

   

시작과 끝 효과 ( Easing )

.animate() 인자 중에 남은 하나는 속도 늦추는 함수(easing function)에 대한 내용입니다. 이 easing 함수는 속도에 대한 내용입니다. 움직임이 한쪽 끝에 닿았을때 처리되는 행동패턴에 대한 내용입니다. jQuery에서 easing 은 기본으로 swing 을 사용합니다. swing은 끝점에 가서 속도가 살짝 느려집니다. 또 하나는 속도를 그대로 유지하는 linear입니다. easing 함수들을 정상적으로 사용하려면 plug-ins 들이 필요합니다. 대부분 jQuery UI suite 쪽에 정의되어 있습니다.

콜백 함수 ( Callback Function )

애니메이션이 완료된 후 사용될 콜백함수입니다. 이 콜백함수는 인자를 전달할 수 없지만, this 를 이용하여 애니메이션이 일어난 요소 자체를 전달할 수는 있습니다. 만일 여러개의 요소에 움직임 효과를 주었다면 각각의 애니메이션 효과가 일어난 뒤에 개별적으로 콜백함수가 실행이 됩니다.

jQuery 1.6 버전부터는deferred.done() 와 함께 .promise() 함수를 사용하여 모든 움직임이 끝난 후 한번만 콜백함수를 실행할 수 있게 되었습니다. ( .promise() 함수 예제 링크 ).

.slideUp() 을 포함하여 모든 jQuery effect 들은, 글로벌 세팅인 jQuery.fx.off = true로 조절할 수 있습니다. 더 많은 정보를 원하시면 jQuery.fx.off를 참고하십시오.

예 제  
모든 div 태그를 슬라이드 업 합니다.

<!DOCTYPE html>
<html>
<head>
  <style>
  div { background:#3d9a44; margin:3px; width:80px; 
    height:40px; float:left; }
  </style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  Click me!
  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <div></div>
<script>
  $(document.body).click(function () {
    if ($("div:first").is(":hidden")) {
      $("div").show("slow");
    } else {
      $("div").slideUp();
    }
  });

  </script>

</body>
</html>

미리보기

슬라이드 업 되면서 사라집니다.

 

예 제  
부모 p 태그를 슬라이드 업하고 완료되면 메시지 처리를 합니다.

<!DOCTYPE html>
<html>
<head>
  <style>
 div { margin:2px; }
</style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  <div>
  <button>Hide One</button>
  <input type="text" value="One" />

</div>
<div>
  <button>Hide Two</button>
  <input type="text" value="Two" />

</div>
<div>
  <button>Hide Three</button>
  <input type="text" value="Three" />

</div>
<div id="msg"></div>
<script>
  $("button").click(function () {
    $(this).parent().slideUp("slow", function () {
      $("#msg").text($("button", this).text() + " has completed.");
    });
  });

</script>

</body>
</html>

미리보기

콜백 함수 사용이 핵심이네요.

 

슬라이드 업은 뭔가를 숨길때 hide 와 자웅(?)을 다툴수 있겠네요. ^^

그럼 즐프하세요.

※ 본 예제는 http://www.jquery.com 에 있는 내용임을 밝힙니다.

Posted by 사라링

26-2.여러 가지 생성자

26-2-가.디폴트 생성자

디폴트 생성자(또는 기본 생성자라고도 한다)란 인수를 가지지 않는 생성자이다. 생성자는 오버로딩이 가능하므로 여러 개를 둘 수 있는데 그 중 인수가 없는 생성자를 디폴트 생성자라고 부른다. 즉 인수 목록이 void인 생성자인데 Position 클래스의 경우 디폴트 생성자의 원형은 Position()이 된다. 다음 예제의 Position 클래스는 디폴트 생성자 하나만 정의하고 있다.

 

  : DefConstructor

#include <Turboc.h>

 

class Position

{

private:

     int x;

     int y;

     char ch;

 

public:

     Position() {

          x=0;

          y=0;

          ch=' ';

     }

     void OutPosition() {

          if (ch != ' ') {

              gotoxy(x, y);

               putch(ch);

          }

     }

};

 

void main()

{

     Position Here;

    

     Here.OutPosition();

}

 

디폴트 생성자는 호출부에서 어떤 값으로 초기화하고 싶은지를 전달하는 수단인 인수가 없다. 인수를 받아들이지 않기 때문에 객체의 멤버에 의미있는 어떤 값을 대입하지는 못하며 주로 모든 멤버를 0이나 -1 또는 NULL이나 빈문자열로 초기화한다. 여기서 0이라는 값은 실용적인 의미를 가지는 값이라기보다는 단순히 아직 초기화되지 않았음을 분명히 표시하는 역할을 한다. 어떤 값인지 알지도 못하는 쓰레기값보다는 그래도 0이라도 대입해 놓는 것이 더 나은데 이렇게 하면 멤버 함수에서 이 값을 사용하기 전에 초기화 되어 있는지를 점검할 수 있기 때문이다.

 

if (ptr == NULL) { ... }

if (value == 0) { ... }

 

디폴트 생성자가 포인터 변수를 NULL로 초기화해 놓으면 멤버 함수가 이 변수를 사용하기 전에 NULL인지 조사해 보고 NULL이면 그때 초기화를 할 수 있다. 즉 디폴트 생성자의 임무는 쓰레기를 치우는 것이며 멤버의 초기화는 이 멤버를 사용하는 멤버 함수가 호출될때까지 연기된다. 위 예제의 Position() 디폴트 생성자는 x, y는 0으로 초기화하고 ch에는 공백 문자를 대입하며 OutPosition 함수는 ch가 공백 문자를 가질 때 이 객체가 아직 초기화되지 않은 것으로 판단하고 문자 출력을 하지 않는다. 디폴트 생성자가 있는 객체를 선언할 때는 다음과 같은 여러 가지 방법을 사용할 수 있다.

 

① Position Here;

② Position Here=Position();

③ Position *pPos=new Position;

④ Position *pPos=new Position();

⑤ Position Here();

 

①번 형식이 가장 간단하며 예제에서 사용한 방법이다. 생성자에게 전달할 인수가 없으므로 타입 다음에 객체 이름만 밝히면 된다. 기본 타입의 int i; 선언문과 형식이 동일하다. ②번 형식은 디폴트 생성자를 명시적으로 호출하는 구문인데 효과는 동일하다. ③, ④번은 객체를 동적으로 생성할 때 new연산자와 함께 사용하는 방법인데 ③번이 더 일반적이다.

그러나 ⑤번 형식은 허용되지 않는다. 왜냐하면 이 선언문은 Position 객체를 리턴하고 인수를 가지지 않는 Here 함수의 원형을 선언하는 것이지 객체 선언문이 아니기 때문이다. 생성자로 전달할 인수가 없으면 아예 괄호도 없어야 한다. 일반 함수는 인수가 없을 때 빈 괄호를 써 함수임을 분명히 표시하지만 객체 선언문의 경우는 반대로 생성자의 인수가 없을 때 괄호를 생략해 함수가 아님을 분명히 해야 한다. 잘 이해가 안되고 순간적으로 헷갈린다면 정수형으로 바꿔 생각해 보자.

 

int func;        // 이건 변수

int func();     // 요건 함수

 

만약 클래스가 생성자를 전혀 정의하지 않으면 어떻게 될까? 이 경우 컴파일러가 자동으로 디폴트 디폴트 생성자(그러니까 컴파일러가 기본적으로 정의하는 디폴트 생성자)를 만든다. 컴파일러가 만들어주는 디폴트 생성자는 아무 것도 하지 않는 빈 함수이다. 이 때 객체의 초기화 방식은 일반 변수와 같은 규칙이 적용되는데 전역이나 정적 객체라면 모든 멤버가 0으로 초기화되고 지역 객체라면 초기화되지 않는 쓰레기값을 가진다.

생성자가 없을 경우 컴파일러가 디폴트 생성자를 만들기 때문에 생성자를 전혀 정의하지 않아도 객체를 선언할 수 있는 것이다. 위 예제에서 Position() 디폴트 생성자를 삭제하면 컴파일러가 내부적으로 다음과 같은 디폴트 생성자를 만들 것이다.

 

Position()

{

}

 

비록 아무 것도 하지는 않지만 생성자가 있으므로 Position Here; 선언문으로 Here 객체를 선언할 수 있다. 그러나 이 객체는 쓰레기값을 가지고 있기 때문에 OutPosition이 어떤 동작을 할 것인지는 예측할 수 없다. 일반적으로 예측할 수 없는 동작은 항상 말썽의 소지가 되며 이런 잠재적인 말썽의 소지를 없애기 위해 디폴트 생성자를 직접 정의하고 모든 멤버의 쓰레기를 치우는 것이다.

컴파일러가 디폴트 생성자를 만드는 경우는 클래스가 생성자를 전혀 정의하지 않을 때 뿐이다. 다른 생성자가 하나라도 정의되어 있으면 컴파일러는 디폴트 생성자를 만들지 않는다. 다음 코드를 보자.

 

class Position

{

public:

     int x;

     int y;

     char ch;

 

     Position(int ax) { x=ax; }

     void OutPosition() { ... }

};

 

정수 하나를 인수로 취하는 생성자가 정의되어 있으므로 이 클래스는 디폴트 생성자를 가지지 않는다. 이 경우 Position Here; 선언문은 적절한 생성자를 찾을 수 없으므로 에러로 처리될 것이다. 별도의 생성자를 제공했다는 것은 클래스를 만든 사람이 이 객체는 이런 식으로 초기화해야 한다는 것을 분명히 명시한 것이므로 컴파일러는 이 규칙을 어긴 코드에 대해 사정없이 에러로 처리한다. 이 객체는 개발자의 의도에 따라 반드시 Position Here(12); 형식으로 생성해야 한다.

만약 Position Here; 형태로 꼭 객체를 선언하고 싶다면 Position(int) 생성자를 없애 컴파일러가 디폴트 생성자를 만들도록 내 버려 두든가 아니면 Position() 디폴트 생성자를 오버로딩해야한다. 생성자가 인수를 가지고 있더라도 디폴트 인수 기능에 의해 디폴트 생성자가 되는 경우도 있다. 다음과 같은 원형을 가지는 생성자는 인수없이도 호출할 수 있으므로 디폴트 생성자를 겸한다.

 

Position(int ax=0, int ay=0, char ach=' ')

 

디폴트 생성자가 없는 클래스는 객체 배열을 선언할 수 없다. 왜 그런지 다음 예제로 이유를 알아보자.

 

  : NoDefCon

#include <Turboc.h>

 

class Position

{

public:

     int x;

     int y;

     char ch;

 

     Position(int ax, int ay, char ach) {

          x=ax;

          y=ay;

          ch=ach;

     }

     void OutPosition() {

          gotoxy(x, y);

          putch(ch);

     }

};

 

void main()

{

     Position There[3];

}

 

이 예제의 Position 클래스는 디폴트 생성자를 정의하지 않으며 세 개의 인수를 취하는 생성자만 정의되어 있다. 개발자가 별도의 생성자를 정의했으므로 컴파일러는 디폴트 생성자를 만들지 않는다. 따라서 Position형의 객체를 만들려면 Position A(1,2,'A'); 식으로 생성자에게 세 개의 인수를 전달해야 한다. 그렇다면 main의 Position There[3]; 선언문은 어떻게 처리될까?

Position형의 객체 3개를 배열로 생성하되 이때 각 객체의 생성자가 호출될 것이다. 그러나 선언문에 인수가 없기 때문에 호출할만한 생성자를 찾을 수 없으며 에러로 처리된다. Position There[3]; 선언문이 처리되려면 인수를 취하지 않는 디폴트 생성자(컴파일러가 만든 것이든 개발자가 직접 정의한 것이든)가 반드시 있어야 하는 것이다. 다음과 같은 선언문이 가능하리라 생각해 볼 수도 있다.

 

Position There[3]={{1,2,'x'},{3,4,'y'},{5,6,'z'}};

 

구조체 배열처럼 ={ } 다음에 각 배열 요소의 초기값을 나열하는 형식이다. {1,2,'x'} 초기식에 있는 값을 클래스 선언문에 나타나는 멤버의 순서대로 대입하면 될 것처럼 보인다. 객체 배열을 초기화할 때도 이런 문법이 지원된다면 좋겠지만 이 문장은 에러로 처리된다. 왜 컴파일러가 객체 배열에 대한 이런 편리한 초기식을 지원하지 못하는지 생각해 보자.

객체는 단순히 정보의 집합인 구조체보다는 훨씬 더 복잡하기 때문에 단순한 대입만으로는 초기화할 수 없다. 생성 단계에서 둘 이상의 입력값을 계산한 결과가 초기값이 될 수도 있고 Person 예제처럼 인수의 길이만큼 메모리를 동적으로 할당해야 하는 경우도 있다. 또한 멤버가 프라이비트 영역에 있을 경우 외부 선언문에서 함부로 멤버값을 변경하는 것도 허락되지 않는다. 이런 능동적인 동작을 하려면 결국 객체 초기화를 위해 생성자가 호출되어야 하는 것이다.

그렇다면 초기식의 값을 그대로 생성자의 인수로 전달하면 되지 않을까? 초기식에 {1,2,'x'}라고 되어 있으니 Position(1,2,'x') 생성자를 호출하면 일단 될 것처럼 보이지만 이것도 불가능하다. 왜냐하면 생성자가 반드시 모든 멤버를 선언된 순서대로 다 받아들여야 한다는 제약이 없기 때문이다. Position(char ach, int ax, int ay) 요런 식으로 생성자가 정의되어 있다면 컴파일러가 초기식의 값과 생성자 인수와의 대응관계를 잘못 판단하게 될 것이고 객체는 제대로 초기화되지 않는다.

그래서 컴파일러는 애매한 초기식으로부터 대충 비슷해 보이는 생성자를 호출하는 쓸데없는 서비스를 하기보다는 차라리 에러로 처리하는 것이 더 깔끔하다고 생각하는 것이다. 만약 객체의 배열을 선언하면서 각 객체를 꼭 초기화하려면 다음과 같이 ={ }괄호안에서 생성자를 일일이 호출해야 한다.

 

void main()

{

     int i;

     Position There[3]={Position(1,2,'x'),Position(3,4,'y'),Position(5,6,'z')};   

     for (i=0;i<3;i++) {

          There[i].OutPosition();

     }

}

 

이 선언문은 초기식에서 명시적으로 생성자를 호출했고 생성자로 전달되는 인수의 순서를 컴파일러가 분명하게 알 수 있으므로 문법적으로 문제도 없고 애매하지도 않다. 객체 배열을 선언하면서 초기화할 때는 이 방법이 정석이며 초기식없이 선언만 하려면 반드시 디폴트 생성자가 정의되어 있어야 한다.

생성자가 없을 때 컴파일러가 디폴트를 만드는 것처럼 파괴자의 경우도 디폴트가 있다. 컴파일러가 만드는 디폴트 파괴자도 생성자의 경우와 마찬가지로 아무 일도 하지 않는 빈 함수이다. 그래서 뒷정리를 할 필요가 없는 클래스라면 디폴트 파괴자를 그냥 사용하는 것도 가능하다. 즉, 파괴자가 없어도 된다는 얘기인데 사실 파괴자는 필요없는 경우가 훨씬 더 많다. 생성자가 특별한 처리를 하지 않고 단순히 멤버 변수에 값만 대입한다면 뒷정리를 할 필요가 없다. Position은 파괴자가 전혀 불필요한 클래스이다.

 

'JAVA' 카테고리의 다른 글

펌) immutable 이란  (0) 2013.10.15
grid I U D 포멧 JAVA 셋팅 [티폼 기준]  (0) 2013.06.27
Swing - windowBuilder 설치 하기.  (0) 2012.06.13
패키지 컴파일러  (0) 2012.05.15
자바로 컴퓨터 종료  (0) 2012.05.15
Posted by 사라링

contextConfigLocation

2012. 7. 4. 12:44

스프링에서는 설정파일에서 모든 것을 명시해주기 때문에 설정파일이 중요한데
설정파일 안에는 dataSource, bean(dao, service) 등 필요한 모든 객체가 다 들어있다.
그럼 이 설정파일들은 어떻게 해서 컨테이너 안에서 동작을 하는지? 어떻게 xml 설정파일을 읽는지 
스프링 프레임웍이 어떻게 동작하는지 궁금하다.

가장 기본은 web.xml 파일에 스프링 설정 파일을 명시해주면 된다는 것.
스프링 설정파일을 읽어 들이기 위해서 org.springframework.web.context.ContextLoaderListener 가
필요하다. 이 리스너가 동작해야 설정파일을 읽어들이고 필요한 객체들을 등록하고 만드는 것이다.
그럼 리스너는 동작을 하는데 설정파일의 위치를 알려주어야 할 것이 아닌가 그래서
<context-param> 안에 contextConfigLocation 이라고 해서 위치를 지정해 주는 것이다.
하나의 파일이든 여러개든 명시해서 읽어올 수 가 있다.


그럼 이제 그 방법을 자세히 보자.
                                                                               출처 : 
http://mars0717.egloos.com/1326159

계층별로 나눈 xml 설정파일이 있다고 가정할 때,
web.xml에서 모두 load되도록 등록할 때 사용.
서블릿이전에 서블릿 초기화하는 용도록 쓰이며, 
contextConfigLocation라는 파라미터를 쓰면, 
Context Loader가 load할 수 있는 설정파일을 여거개 쓸 수 있다.

web.xml에 저 문장이 빠지게 되면 default로,
/WEB-INF/applicationContext.xml (spring 설정파일) 을 쓰게 된다.

[web.xml]

<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
           /WEB-INF/mars-ibatis.xml 
           /WEB-INF/mars-service.xml 
      </param-value>
</context-param>

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

'스프링3.0' 카테고리의 다른 글

MyBatis  (0) 2012.07.03
스프링 3.0 + ibatise  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

MyBatis

2012. 7. 3. 14:20

Deprecated. (구버전, 교체됨)

Version 3를 사용하세요~

 

MyBatis에서 특정 테이블의 컬럼목록 가져오기

가끔 특정 테이블의 컬럼의 목록을 구할 필요가 있을 때가 있다. DBMS에서 테이블의 정보를 구해오는 것은 각각의 DB마다 상이하다. (예. 오라클의 경우는 딕셔너리 테이블에서 가져올 수 있다) JDBC의 메타데이터를 이용하면 쉽게 가져올 수 있다.

참고 : Get column names of a table using ResultSetMetaData

그럼 MyBatis를 사용해서 DB Mapper를 사용하는 경우 별도의 JDBC 연결 설정을 만들어서 이용해야 하나?

그러면 DB 접속 환경이 한군데가 변하게 되면 MyBatis 및 JDBC 모두 변경을 해야 한다. 이것은 중복이다. DRY원칙 위반이다. 설정값을 하나로 이용하는 방법도 있지만 이것 역시 귀찮다.

 

쉬운방법으로는 SqlSessionFactory에서 openSession() 메소드를 통해 세션을 연 다음 SqlSession 인터페이스에서

getConnection() 메소드를 이용하여 java.sql.Connection을 가져오면 JDBC의 기능을 온전히 이용할 수 있다.

말로만 설명하면 어려우니 예제를 보여주겠습니다.

  1. SqlSession session = sqlMapper.openSession();   // sqlMapper는 SqlSessionFactory 타입입니다.
  2. try {
  3. Statement statement = session.getConnection().createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM someTabe WHERE 0=1");
    ResultSetMetaData metadata = resultSet.getMetaData();
    int columnCount = metadata.getColumnCount();
  4. ArrayList<String> columns = new ArrayList<String>();
    for (int i = 1; i < columnCount; i++) {
     String columnName = metadata.getColumnName(i);
     columns.add(columnName);
    }
  5. } finally {

    session.close();

    }

위에서 보면 columns라는 ArrayList타입의 리스트에 컬럼명을 넣습니다.

executeQuery에서 'WHERE 0=1'로 거짓조건을 주는 이유는 데이터를 가져오지 않게 하기 위함입니다.

columns를 이용해서 컬럼 목록을 이용하면 됩니다. 

이름의 변경

SQL 매핑 프레임워크 iBATIS가 이름이 MyBatis로 바뀌었다.

클린턴 비긴이 처음 개발했던 아이바티스는 아파치 프로젝트로 들어갔다가 2010년 6월 16일 은퇴(retire)하고 구글 코드쪽에서mybatis라는 이름으로 이동했다. 지금 시점(2010 12월)에서는 MyBatis 3.0.3 버전이 릴리즈 되어 있다.

SQL 주입(injection)에 대한 기사

“카드 정보 1억 3,000만 건 도난”, 주범은 SQL 인젝션

 

iBatis 사용시 XML상의 reference 관련 error시

이클립스에서 느낌표가 나오면 왠지 모르게 짜증이 난다

error.png

[기존]

  1. <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

[수정]

  1. <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

주소가 수정되었나보다. 브라우저에서 주소창에 치면 이전 것도 다운로드 되는데 이클립스에서는 왜 안되지?

다른 sql-map, dao도 올려놓자

  1. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <!DOCTYPE dao PUBLIC "-//ibatis.apache.org//DTD DAO Configuration 2.0//EN" "http://ibatis.apache.org/dtd/dao-2.dtd">

아놔~ 그 문제인줄 알았는데,

회사에서는 외부 인터넷에 연결하기 위해서 프록시 서버를 연결해야 하는데 이클립스에 세팅을 해줘야 하기 때문이었다.

네트워크 연결이 안되니 dtd 파일을 다운받을 수 없고 xml validation도 할 수 없는 것이 었다.

conn.png

 

 iBATIS in Action
(쉽고 강력한 SQL 매핑 프레임워크 아이바티스)

위 책의 필요한 사전 배경지식: Java, JDBC(매핑+), SQL, XML

외부 링크 : 아이바티스 커뮤니티(http://ibatis.apache.org)

SVN : Subversion Source Control

JIRA: for 이슈 트래킹(아틀라시안)

Confluence : wiki 문서 작성

 소스 코드 : 매닝 출판사 웹 사이트(www.manning.com/begin)
                 위키북스 오픈소스 & 웹 시리즈 에디터 일래스틱 온라인(http://web2.0business.or.kr/)

 

  • 머리말

    • 프레임워크 - 사전적 의미(뼈대, 틀, 골자)
    • 향상 : 가독성, 유지보수성, 생산성
    • 퍼시스턴스 계층에 적용할 프레임워크

      • 아이바티스 - JDBC
      • 객체 관계 매핑 툴(ORM) -  하이버네이트 / TopLink
    •  iBATIS : 더 빠른 JDBC 코딩을 위한 일반화된 프레임워크

      • SQL 매퍼 + DAO 프레임워크

 

 요약 (iBATIS)

  • SQL 매핑으로 객체를 관계형 데이터베이스에 저장
  • 애플리케이션이 퍼시스턴스 계층에 일관성있게 접근하는 것을 도와줌
  • 전사적인 수준의 퍼스스턴스 계층에 보다 적함(소규모 시스템에 비교하여)
  • 특징

    • 간단함 - 간단한 퍼시스턴스 프레임워크
    • 생산성 - 62%정도 줄어드는 코드(JDBC와 비교하여), 간단한 설정(근거: 이탈리안 자바 사용자 그룹의 연구)
    • 성능 - 구조적 강점(데이터 접근 속도 높여주는 JOIN매핑)

      • 여러가지 방식의 데이터 가져오기 전략(가져오기 미루기, SQL 줄이기 기법)
    • 관심사의 분리 - 설계를 향상(차후 유지보수성 위해)

      • 리소스를 관리하여 계층화를 지원(커넥션, PreparedStatement, 결과셋)
    • 작업의 분배 - 팀을 세분화하는 것을 도움

      • SQL 문이 애플리케이션 소스 코드로부터 완전히 분리
    • 이식성 - 어떤 프로그래밍언어로도 구현 가능

      • 예) 자바, C#(iBATIS.NET), Ruby(RBATIS)
    • 오픈소스 - 무료+ 커뮤니티티
  • 언제 사용하지 말아야 하나?

    • 개발자가 모든 것에 대해 영원한 결정권 소유

      • 애플리케이션 설계와 데이터베이스 설계에 대한 모든 결정권 보유
      • iBATIS는 관계형 데이터베이스를 위해 설계
      • => 관계 매핑 솔루션(ORM;하이버네이트..) 사용 - 설계시 이점, 생산성 향상
        예) JIRA(이슈 트래킹 패키지 소프트웨어 제품)
    • 완전히 동적인 SQL을 요구시

      • 애플리케이션의 핵심 기능 : SQL을 동적으로 생성일 경우
      • iBATIS의 사용이유: 수작업 SQL 구문 작성, 관리
      • 애플리케이션 -> 대부분의 SQL 구문이 SQL 자동 생성 클래스 로부터 동적으로 생성시 위의 장점은 무의미
    • 비 관계형 데이터베이스 사용

      • 파일, 엑셀, XML
      • => 순수한 JDBC, 저수준 파일 입출력 API 권장장
    • 요구사항과 상반되는 개발 방향, 설계지침 - 복잡도 증가, 프레임워크 자체의 역할 범위 넘어서는 것
  • (주로)관계형 데이터베이스를 위해 설계

    • 비-관계형 기술(일반적 파일, XML, 엑셀 스프레드 시트)사용시 타 API 이용이 효과적
  • 객체 관계 매퍼(ORM) - 애플리케이션~데이터베이스에 대한 결정권 보유
  • JDBC - 주로 동적으로 생성되는 SQL 코드로 작업하는 애플리케이션

 

x설치와 설정 (iBATIS)

  • 배포판 얻기

    1. 바이너리 배포판: 가장 빠르고 쉬운 방법

      • 컴파일된 상태 -> 다운받아 압축을 풀고 사용
    2. 소스로부터 빌드하기

      • 프레임워크를 확장, 버그 수정
      • 소스코드를 직접 컴파일 결과 확인시
    • 배포판의 구조

      • ibatis-2.3.0.677.png
      • 2.3.0.677에서는 jar 파일들(/lib 디렉토리내)가 ibatis-2.3.0.677.jar로 하나로 통합되었다.
      • /doc

        • user-javadoc.zip : for iBATIS 프레임워크를 사용해서 개발을 하는 사용자들
        • dev-javadoc.zip : for iBATIS 프로젝트의 모든 JavaDoc 문서를 포함하고 있는 파일
      • /lib

        • ibatis-common-2.jar : SQL Maps와 DAO 프레임워크 모두가 사용하는 공통 컴포넌트 포함
        • ibatis-sqlmap-2.jar : SQL Maps 프레임워크의 컴포넌트들을 포함하고 있는 파일
        • ibatis-dao-2.jar : DAO 프레임워크 컴포넌트들을 포함하고 있는 파일
      • /src

        • ibatis-src.zip : 프레임워크의 JAR파일을 빌드하는데 사용된 전체 소스를 포함하고 있는 파일
  • 애플리케이션에 iBATIS 붙이기

    • 클래스패스 추가(iBATIS 파일 경로 컴파일시, 실행시)

      • 단독 실행 애플리케이션

        • 클래스패스 옵션 추가

          1. java -cp ibatis-sqlmap-2.jar:ibatis-common-2.jar:. MyMainClass
      • 웹 애플리케이션

        • iBATIS의 jar 파일들을 WEB-INF/lib 디렉토리에 둔다
    • JRE 공유 디렉토리(lib/ext 디렉토리)에 올려서 사용가능하지만 가급적 피할 것

      1. 애플리케이션 변경되어 파일 수정시 공유하고 잇는 파일을 참조하는 모든 애플리케이션을 테스트 필요
      2. 클래스로더 문제((두 개의 서로 다른 클래스로더가 읽으면 서로 다른 클래스로 간주: 정적변수 공유 X)

 

  • SQL Maps 설정 파일

    • <SqlMapConfig.xml>

      1. <!SqlMapConfig.xml SQL Map configuration file-->

        <?xml version="1.0" encoding="UTF-8"?>
        <!-- 유효성 체크를 위한 DOCTYPE과 DTD를 적는다 -->
        <!DOCTYPE sql-map-config
            PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
           "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
        <sql-map-config>
            <properties resource="db.properties" />
        <!-- 전체 설정 옵션 -->
            <settings
                useStatementNamespaces='false'
                cacheModelsEnabled='true'
                enhancementEnabled='true'
                lazyLoadingEnabled='true'
                maxRequests="32"
                maxSessions="10"
                maxTransactions="5"
                />
        <!-- 트랜잭션 매니저 -->
            <transactionManager type="JDBC" >
                <dataSource type="SIMPLE">
                    <property name="JDBC.Driver" value="${driver}"/>
                    <property name="JDBC.ConnectionURL" value="${url}"/>
                    <property name="JDBC.Username" value="${user}"/>
                    <property name="JDBC.Password" value="${pword}"/>
                </dataSource>
            </transactionManager>
        <!-- SQL Map을 기술 -->
            <sql-map resource="sqlMap.xml" />
         
        </sql-map-config>
    • <properties> 요소 - 외부에서 이름/값 쌍의 리스트를 제공

      • 장점 : 공통 설정 부분은 모두 한 곳에 두고 각 환경별로 다른 값들을 properties 파일에 독립 가능
      • 속성

        • resource - 클래스 패스상에 있는 리소스(or 파일)

          • 클래스 로더가 애플리케이션의 클래스패스에서 그 리소스를 찾으려는 시도 함
          • 소스(db.properties)

            • driver=oracle.jdbc.driver.OracleDriver
              url=jdbc:oracle:thin:@localhost:1521:orcl
              user=scott
              pword=tiger
        • url - URL, java.net.URL에 의해 처리
    • <setting> 요소

      • useStatementNamespaces - 매핑 구문이 적절한 이름을 가지고 있어야 iBATIS가 실행 가능하도록 하는 옵션, 값(true/false)
      • cacheModelsEnabled - 캐시(차후 참조 가정->메모리 계속 저장), 값(true/false)
      • enhancementEnabled - CGLIB(실행 시간에 코드를 생성하는 라이브러리)에 최적화된 클래스-> 적재 지연 성능 향상 여부 지정, 값(true/false)
      • lazyLoadingEnabled - 적재 지연(필요할 때만 정보를 읽어들이는 기술), 값(true/false)
      • maxRequests - SQL작업(입력/수정/삭제/저장 프로시저 호출)의 한번에 수행가능한 개수, 기본값: 512
      • maxSessions - 세션(스레드, 관련되어 있는 트랜잭션과 요청의 묶음에 대한 정보 추적 사용), 기본값: 128
      • maxTransactions - 데이터 트랜잭션의 개수, 기본값: 32
    • <typeAlias> 요소 - FQCN(완전한 형태의 클래스 이름, Fully Qualified Class Name) 대신 별칭을 붙임

      • 예)

        • <typeAlias alias="Account"
                type="org.apache.ibatis.jgamestore.domain.Account" />
      • 기본 내장 별칭들

        • 트랜잭션 매니저의 별칭

          • JDBC <- com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig
          • JTA <- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig
          • EXTERNAL <- com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
        • 데이터 타입

          • string <- java.lang.String
          • byte <- java.lang.Byte
          • long <- java.lang.Long
          • short <- java.lang.Short
          • int <- java.lang.Integer
          • integer <- java.lang.Integer
          • double <- java.lang.Double
          • float <- java.lang.Float
          • boolean <- java.lang.Boolean
          • decimal <- java.math.BigDecimal
          • object <- java.lang.Object
          • map <- java.util.Map
          • hashmap <- java.util.HashMap
          • list <- java.util.List
          • arraylist <- java.util.ArrayList
          • collection <- java.util.Collection
          • iterator <- java.util.Iterator
        • 데이터 소스 팩토리 타입

          • SIMPLE <- com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
          • DBCP <- com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
          • JNDI <- com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory
        • 캐시 컨트롤러 타입

          • FIFO <- com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController
          • LRU <- com.ibatis.sqlmap.engine.cache.Iru.LruCacheController
          • MEMORY <- com.ibatis.sqlmap.engine.cache.memory.MemoryCacheController
          • OSCACHE <- com.ibatis.sqlmap.engine.cache.OSCacheController
        • XML 결과 타입

          • Dom <- com.ibatis.sqlmap.engine.type.DomTypeMarker
          • domCollection <- com.ibatis.sqlmap.engine.type.DomCollectionTypeMarker
          • Xml <- com.ibatis.sqlmap.engine.type.XmlTypeMarker
          • XmlCollection <- com.ibatis.sqlmap.engine.type.XmlCollectionTypeMarker
    • <transactionManager> 요소

      • type - 어떤 트랜잭션 관리자르 사용할지 결정

        • JDBC : 간단한 JDBC 기반 트랜잭션 관리 기능 제공
        • JTA : 컨테이너 기반한 트랜잭션 관리 기능 제공
        • EXTERNAL : 트랜잭션 관리자를 제공하지 않고 iBATIS 대신 애플리케이션이 직접 트랜잭션을 관리한다고 가정
      • commitRequired - 커넥션을 닫기 전에 commit/rollback 제어시, 기본값: false
      • <property> 요소 - 각 트랜잭션 관리자 서로 다른 설정 옵션 가능
      • <dataSource> 요소 - javax.sql.DataSource 객체를 사용 -> 커넥션 풀 작업을 표준화
      • type 속성 - 어떤 클래스의 객체를 생성해서 데이터 소스 팩토리를 얻어올지를 정하는 속성

        • SIMPLE - 간단한 커넥션 풀을 내장한 데이터 소스를 설정하고자 할 때(JDBC 드라이버만 빼고 데이터 소스에 필요한 모든 것을 자체 내장)
        • DBCLP - Jakarta Commons Database Connection Pool 구현을 제공
        • JNDI - JNDI(Java Naming and Directory Interface)를 통해 할당된 컨테이너 기반의 데이터 소스를 공유하도록 사용
      • <typeHandler>

        • 타입 핸들러 이용: JDBC 데이터베이스 전용 데이터형 -> 애플리케이션의 데이터형 변환(번역기)
    • <sqlMap> 요소

      • resource - SQL Map 파일을 자바 클래스패스에 두고 리소스로서 참조
      • url - java.net.URL 클래스가 인식하는 임의의 URL 값 이용

 

  • SQL Map API

    • SqlMapClient 인터페이스

      • queryForObject() - 데이터베이스로부터 한 개의 레코드를 가져다가 자바 객체에 저장

        • Object queryForObject(String id, Object parameter) throws SQLException;

          • 디폴트 생성자를 가진 객체를 생성(보편적 방법)
          • 디폴트 생성자가 없으면 throws "런타임 예외"
        • Object queryForObject(String id, Object parameter, Object result) throws SQLException;

          • 반환하는 값으로 사용될 객체를 받음
          • 결과값 -> 파라미터의 형태로 객체에 지정
          • 생성자가 protected / 디폴트 생성자가 없어서 객체를 쉽게 생성할 수 없을 때 유용
      • queryForList() - 한 개 이상의 레코드를 가져와서 자바 객체의 List를 만드는 데 사용

        • List queryForList(String id, Object parameter) throws SQLException;

          • 매핑 구문이 반환하는 모든 객체를 반환
        • List queryForList(String id, Object parameter, int skip, int max) throws SQLException;

          • 전체 결과의 일부만을 반환
          • skip : 지정된 개수만큼 건너뛰고
          • max : 지정된 개수의 레코드만 반환
          • 2.3버전부터 비권장
      • queryForMap() - 데이터베이스로부터 한 개 혹은 그 이상의 레코드를 가져올 때 자바 객체의 Map을 반환

        • Map queryForMap(String id, Object parameter, String key) throws SQLException;

          • 퀴리 실행후 Map 객체를 생성하여 반환
          • key : 결과 객체를 가리키는 키, -> 지정된 프로퍼티의 값

            • Map accountMap = sqlMap.queryForMap(
                 "Account.getAll", null, "accountId");
              System.out.println(accountMap);
        • Map queryForMap(String id, Object parameter, String key, String value) throws SQLException;

          • 결과값 객체 -> value 파라미터에 지정된 프로퍼티 값이 됨

            • accountMap = sqlMap.queryForMap(
                 "Account.getAll", null, "accountId", "username");
              System.out.println(accountMap);
  • non-query 구문

    • 데이터 갱신

      • insert 메소드

        • Object inser(String id, Object parameterObject) throws SQLException;

          • 파라미터 : 실행할 매핑 구문의 이름, 파라미터 객체(데이터베이스에 데이터 삽입하는 데 사용)
          • 반환 : 객체
      • update 메소드

        • int update(String id, Object parameterObject) throws SQLException;

          • 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
          • 반환: update 구문에 의해 영향을 받은 레코드의 개수
      • delete 메소드

        • int delete(String id, Object parameterObject) throws SQLException;

          • 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
          • 반환: 삭제된 레코드의 개수
    • 매핑 구문

      • <insert> | id, parameterClass, parameterMap

        1. <parameterMap id="fullParameterMapExample" class="Account">
              <parameter property="accountId" jdbcType="NUMBER" />
              <parameter property="username" jdbcType="VARCHAR" />
              ...
          </parameterMap>

          <insert id="insertWithExternalInfo"
              parameterMap="fullParameterMapExample">
              insert into account (
                  account Id,
                  username, ...
              ) values (
                  ?, ? , ...
              )
          </insert>
        2. in Java 사용
          sqlMap.insert("Account.insertWithExternalInfo", account);
      • <update> | id, parameterClass, parameterMap
      • <delete> | id, parameterClass, parameterMap
      • <procedure> | id, parameterClass, resultClass, parameterMap, resultMap, xmlResultName
      • <sql> | id

        • 매핑 구문은 아니지만, 매핑 구문 내에서 사용될 수 있는 컴포넌트를 만들기 위해
      • <include> | refid

        • 매핑 구문은 아니지만, 매핑 구문에 <sql>타입으로 생성된 컴포넌트를 삽입하기 위해
  • iBATIS에서 XML 사용

    • XML 파라미터

      • <select id="getByXmlId" resultClass="Account" parameterClass="xml">
           ...
    • XML로 결과 생성

      • <select id="getByValueXml" resultClass=""xmlxmlResultName="account">
              ...

MVC 모델

  • Hierachy.png
  • 비지니스 객체 모델(도메인 클래스) : 처리할 도메인을 객체 지향적으로 묘사

    • 특정 비지니스 로직의 기능을 수행하기 위해 사용
    • 명사 -> 이름 -> 클래스
    • 약간의 로직 포함 가능(다른 계층에 접근하는 코드 금지)
    • 퍼시스턴스 계층의 메소드들의 파라미터의 반환값
  • 프리젠테이션 계층 : 출력(애플리케이션의 데이터/제어화면)하는 역할

    • 모든 정보의 레이아웃, 출력 형식을 정의
    • 예. HTML + JavaScript
    • 웹 애플리케이션

      • 장점: 플래폼에 독립적, 배포와 확장이 쉬움
      • 단점: 높은 수준의 사용자 제어 방식, 복잡한 데이터 처리 어려움

        • => 운영 시스템 위젯 사용하는 리치 클라이언트 방식(탭, 표, 트리, 내장 객체)
    • 리치 클라이언트 방식

      • 장점: 강력한 사용자 인터페이스
      • 단점: 배포의 어려움, 성능, 보안에 손이감
      • 예> Swing(자바), WinForms(.NET)
    • 복합적 리치 클라이언트(웹 애플리케이션 + 리치 클라이언트 방식)

      • 웹 서비스 <= 겉 모양, 비지니스 기능
      • XML <= 리치 클라이언트와 서버 간의 매개체
      • 단점: 애플리케이션의 개발과 배치에 더 많은 소프트웨어 필요

        • 예) Flex(매크로미디어), Flash 브라우저 플러그인(Laszlo시스템), Ajax(Asynchoronous JavaScript And XML)
  • 비지니스 로직 계층(서비스 클래스) - 애플리케이션이 제공하는 포괄적인 서비스들을 표현

    • 큰 덩어리 비지니스 기능을 관련된 비지니스 객체 모델에서 분리
    • 명사-동사 분리(예. 계좌(도메인) 메소드 분리 -> 은행서비스(비지니스 로직-계좌를 개설하다)
    • 서비스를 열어준다는 것은 클래스의 메소드를 사용할 수 있게 권한을 부여한다는 의미가 될 수 있음
  • 퍼시스턴스 계층 - 객체에 저장된 데이터(저장소, 객체 가져오기)

    • 데이터 저장 방식은 다양(관계형 데이터베이스 스스템, 쉼표로 분리된 텍스트, XML 등)
    • 추상화 필요 - 세부사항(데이터가 어떻게 저장/전송) 숨김
    • 내부 계층

      • 추상 계층 : 퍼스스턴스 계층에 일관성 있고 의미 있는 인터페이스 제공

        • 클래스와 메소드의 집합
        • 세부 구현 사항은 감싸서 꾸며줌
        • 적절히 추상 계층 구현을 도와주는 패턴 존재 : 예) 데이터 접근 객체(DAO;Data Access Object)
      • 퍼시스턴스 프레임워크 : 드라이버(or 인터페이스)와 소통하는 책임

        • 데이터 저장/가져옴/수정/검색/관리 메소드들 제공
        • 기반 저장소 클래스에 종속적
        • 표준API - 반복적이고 부차적인 코드가 필요

          • JDBC(자바 애플리케이션 -데이터베이스에 접근~표준 프레임워크)
          • ADO.NET(.NET 애플리케이션을 위한 표준 데이터베이스 퍼시스턴스 프레임워크)
      • 드라이버 / 인터페이스

        • 기반 저장소는 종류 다양(구현, 규모, 행동 상이) -> 소프트웨어 드라이버 사용
        • 드라이버와 통신하여 차이점들을 최소화 간소화하는 역할

 

데이터베이스

  • 관계형 데이터베이스의 사용 이유? - 무결성, 성능, 보안

    • 무결성 - 데이터의 일관성, 신뢰, 값의 정확성 보장

      • VARCHAR(25) NOT NULL
      • 데이터 타입 엄격히 준수 - 예) 값이 문자열 데이터, 길이가 25이하
      • 제약조건 엄수 - 예) UNIQUE
      • 트랜잭션 사용 - 연관(관련)된 데이터들의 일관성 있는 수정 방식(여러 사용자)
    • 성능 - 설계, 소프트웨어 튜닝, 하드웨어

      • 설계: 최고 중요!!!
      • 튜닝 고려사항: 캐시, 파일 관리자, 인덱스 알고리즘, 운영체제 등
      • 하드웨어 고려사항: 고속 디스크 어레이, 고속I/O 컨트롤러, 고속 하드웨어 캐시, 네트워크 인터페이스
    • 보안 - 기밀 데이터 유지
  • 데이터베이스 형태(4가지)

    • 애플리케이션 데이터베이스 - 작고 단순한 형태, 외부 영향 적음

      • 해당 프로젝트의 일보로 애플리케이션과 나란히 설계/구현
      • 예) 웹 애프리케이션 -> 데이터베이스(MySQL,PostgreSQL) -> 리포팅 툴(크리스탈 리포트)
    • 기업용 데이터베이스 - 큰 규모, 외부의 영향 큼

      • 통합 데이터베이스 - 트랜잭션처리 데이터베이스 - 리포팅 데이터베이스
    • 독점적 데이터베이스 - 직접 제작 vs 구입(패키지 소프트웨어)
    • 레거시 데이터베이스 - 오래된 데이터베이스(보잡성, 뒤죽박죽 설계, 의존성. age)

      • 수년간에 걸친 수정, 긴급한 수리 작업, 오류 은폐작업, 오류 피해가기, 땜질식 문제 해결, 기술적 제약 극복 패치..

 

iBATIS

  • iBATIS - 데이터 매퍼

    • 매퍼계층: 객체와 데이터베이스 그리고 매퍼 자체를 독립적으로 유지 + 객체와 데이터베이스 간에 데이터를 이동

      • SQL 구문의 파라미터와 결과(입력/출력)를 클래스에 매핑
    • 매핑방법

      • SQL 구문 - 입력과 출력으로 구분

        • 예) 입력 first_name, last_name / 출력 1234

          1. select first_namelast_name
            from employee
            where employee_number=1234;
        • XML 서술 파일 : SQL 구문의 입력과 출력을 매핑

          1. <select id="getAddress" parameterClass="int" resultClass="Address">
          2. select
          3. ADR_ID   as id,
          4. ADR_DESCRIPTION as description,
          5. ADR_STREET as street,
          6. ADR_CITY as city
          7. from address
          8. where ADR_ID = #id#
          9. </select>
          • 별칭 idsms id라고 불리는 Address 클래스의 프로퍼티에 매핑
          • #id# - 파라미터(Integer 형)
          • 위 코드를 수행하는 자바 코드

            1. Address addr = (Address) sqlMap.queryForObject("getAddress", new Integer(5));
          • 위 코드를 수행하는 C# 코드

            1. Address addr = (Address) sqlMap.queryForObject("getAddress", 5);
      • JDBC, ADO.NET 코드 작성 대신

        • 예) JDBC vs iBATIS

          • JDBC

            1. public Employee getEmployee (int id) throws SQLException {
                  Employee employee = null;
                  String sql = "SELECT * from employee " +
                          "where employee_number = ?";
                  Connection conn = null;
                  PreparedStatemnent ps = null;
                  ResultSet rs = null;
                  try {
                      conn = datasource.getConnection();
                      ps = conn.prepareStatement(sql);
                      ps.setInt(1, id);
                      rs = ps.executeQuery();
                      while (rs.next()) {
                          employee = new Employee();
                          employee.setId(rs.getInt("ID"));
                          employee.setEmployeeNumber(rs.getInt("EMPLOYEE_NUMBER"));
                          employee.setFirstName(rs.getString("FIRST_NAME"));
                          employee.setLastName(rs.getString("LAST_NAME"));
                          employee.setTitle(rs.getString("TITLE"));
                      }
                  } finally {
                      try {
                          if(rs != null) rs.close();
                      } filnally {
                          try {
                              if (ps != null) ps.close();
                          } filnally {
                              if (conn != null) conn.close();
                          }
                      }
                  }
                  return employee;
              }
          • iBATIS

            1. <select id="getEmployee" parameterClass="java.lang.Integer" resultClass="Employee">
            2. select
            3. ID               as id,
            4. EMPLOYEE_NUMBER   as description,
            5. FIRST_NAME   as street,
            6. LAST_NAME    as city
            7. TITLE         as title
            8. from employee
            9. where EMPLOYEE_NUMBER = #empNum#
            10. </select>
            • 실행 코드

              1. Employee emp = (Employee) sqlMap.queryForObject("getEmployee", new Integer(5));
  • (추가내용)

SQLMap.png

자바빈즈를 PreparedStatement 파라미터와 ResultSet으로 맵핑시켜주는 기능을 담당

 

  • 디미터 법칙(Law of Demeter) "각 계층은 다른 계층에 대해 오직 제한된 정보만을 가질 수 있다: 오직 현재 계층에 인접한 계층에 대해서만."

    • 각 계층이 오직 자기 바로 아래 계층과만 소통 가능
    • 의존성이 한 방향으로만 흐르는 것을 조장(스파게티 코드 피하기)
    • iBATIS는 퍼시스턴스 계층 프레임워크(위: 비지니스 로직 / 아래: 데이터베이스)

Spring과 iBATIS

  • 왜 iBATIS대신에 Spring을 사용할까?

    • iBATIS DAO 계층

      • 장점: 빠르고 쉬운 솔루션
      • BATIS SQL Maps / iBATIS DAO 계층 분리(2.3~)
      • 요구사항: 트랜잭션/커넥션 관리 -> Spring보다 훨씬 간단하게 사용가능한 프레임워크
      • 단점: 간결함
      • DAO 패턴을 사용: 결함도가 낮아짐(decoupling) -> 테스트하기 쉽다

        • Action에서 필요한 코드의 구현을 알 필요 없이 오직 필요한 인터페이스만 알면 됨.
        • 구현체는 설정을 통해 기워 넣게 됨
    • Spring : 커넥션과 트랜잭션 관리, 애플리케이션의 모든 부분에 적용(iBATIS DAO는DAO계층에만 적용)
  • 효율적인 DAO 계층

    • 구현체에서 인터페이스 분리

      • 이유

        1. 구현체 바꿔 치기가 가능(다른 형태의 데이터 접근 지원 가능)
        2. 테스트가 쉽고 빨리짐(실제 DB에 접근하는 객체 대신 가상의 DAO 객체를 끼워 넣을 수 있으므로)
      • IDE : 분리 과정 쉽게 처리 가능

        • 리팩토링 툴(클래스에서 인터페이스를 분리 가능)
        • 인터페이스를 만들 때 구현 클래스를 어떤 다른 데잍터베이스를 다루는 툴에 종속적인 부분에 노출 가능성 높음

          • 노출: DAO가 아닌 데이터 접근 구현체에 애플리케이션을 묶어버림

            • 예) 'Fast Lane Reader'패턴을 사용하는 웹 애플리케이션 - JDBC 코드가 뷰 계층과 직접 소통 (테스트 어려워짐)

              • -> 콜백을 사용해서 코드를 작성(뷰가 요청한 데이터를 처리하는 RowHanlder 같은 것)
          • SQL Maps API를 직접 사용하는 애플리케이션 -> 캡슐화된 API

            • 예) sqlMapClient 객체의 queryForList() 메소드를 호출하는 클래스 - > 작성한 DAO 클래스를 호출하게 리팩토링, 클래스의 메소드에서는 List 객체를 반환

              • 데이터 사용자 - 작성한 DAO하고만 소통 가능
    • 외부에서 설정된 팩토리(factory)를 사용하여 구현체의 결합도 낮추기

      • 인터페이스와 구현체 둘 다 DAO를 사용하는 클래스에 노출(인터페이스에 대한 의존성을 DAO를 사용하는 클래스에 추가한 셈)시키면 안됨

        • [구현체]-[DAO]-[interface]-> 구현체를 어떻게 사용할 수 있을 것인가?

          1. AccountDao accountDao = new AccountDaoImpl();   // DAO를 구현에서 분리, 구현체를 직접 참조하고 있음
          2. AccountDao accountDao = (AccountDao)DaoFactory.get(AccoutDao.class);   // 초점: DaoFacotry가 AccountDao 인테페이스를 구현한 객체를 반환
          • DAO factory

            • public인테피이스는 getInstance()와 getDao() 두개의 메소드로 이루어져 있음

              1. public class DaoFactory {
              2. private static DaoFatory instance = new DaoFactory();
              3. private final String defaultConfigLocation = "DaoFactory.properties";   // 프로퍼티 화일(인터페이스, 구현체 이름)
              4. private Properties daoMap;
              5. private Properties instanceMap;
              6. private String configLocation = System.getProperty(
              7. "dao.factory.config",

                defaultConfigLocation

                );

              8. private DaoFactory() {   // 1. private 생성자 선언(single tone; 오직 단 한 개의객체만 생성할 수 있는 클래스)
              9. daoMap = new Properties();
              10. instanceMap = new Properties();
              11. try {
              12. daoMap.load(getInputStream(configLocation));
              13. } catch (IOException e) {
              14. throw new RuntimeException(e);
              15. }
              16. private InputStream getInputStrream(String configLocation)
              17. {
              18. return Thread
              19. .currentThread()
              20. .getContextClassLoader()
              21. .getResourceAsStream(configLocation);
              22. }
              23. public static DaoFactory getInstance() {   // 2. 간단한 팩토리 메소드를 선언 (이 클래스의 유일한 인스턴스 반환)
              24. return instance;
              25. }
              26. public Object getDao(Class daoInterface) {   // 3. DAO를 가져온다 (인터페이스의 구현체를 반환)
              27. if (instanceMap.containsKey(daoInterface)) {
              28. return instanceMap.get(daoInterface);
              29. }
              30. return createDao(daoInterface);
              31. }
              32. private synchoronized Object createDao (Class daoInterface) {   // 4. 타입 별로 단 하나의 DAO만 생성함을 보장
              33. Class implementationClass;
              34. try {
              35. implementationClass = Class.forName((String)daoMap.get(daoInterface));
              36. Object implementation = implementationClass.newInstance();
              37. instanceMap.put(implementationClass, implementation);
              38. } catch (Exception e) {
              39. throw new RuntimeException(e);
              40. }
              41. return instanceMap.get(daoInterface);         // DAO에 대한 실제 요청이 발생할 때에 생성
              42. }
              43. }

               

               
          •  
    • 트랜잭션과 커넥션 관리기능 제공(chap. 7)
  • 스프링: 데이터 매퍼의 두 가지 버전(1.3, 2.0)을 지원

    • 버전 1.3 : SqlMapXxx (SqlMapTemplate 클래스 사용)
    • 버전 2.0 : SqlMapClientXxx (SqlMapClientTemplate 클래스 사용: 내부적으로 iBATIS의 SqlMapClient 사용)

      • SqlMapClient를 스프링 빈으로 설정 : SqlMapClientFactoryBean 클래스 이용

        1. <bean id="sqlMapClinet" class="org.springframework.orm.ibatis.SqlMapClinetFactoryBean"

          • p:dataSource-fef="dataSource"
          • p:configLocation="WEB-INF/sqlMap/sqlMapConfig.xml">
        2. </bean>
      • sqlMapConfig.xml

        1. <?xml version="1.0" encoding="UTF-8" ?>
        2. <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        3. "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
        4. <sqlMapConifg>
        5. <sqlMap resource="GuestBook.xml" />
        6. </sqlMapConifg>
      • GuestBook.xml

        1. <?xml version="1.0" encoding="UTF-8" ?>
        2. <!DOCTYPE sqlMap
        3. PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
        4. "http://ibatis.apache.org/dtd/sql-map-2.dtd">
        5. <sqlMap namespace="Guestbook">
        6. <typeAlias alias="Message" type="kame.spring.questbook.service.Message" />

          <parameterMap id="messageParamMap" class="Message">

        7. <parameter property="guestName" />
        8. </parameterMap>
        9. <resultMap id="messageResultMap" class="Message">
        10. <result property="id" column="GUESTBOOK_MESSAGE_ID" />
        11. <result property="guestName" column="GUEST_NAME" />
        12. <result property="content" column="CONTENT" />
        13. </reslutMap>
        14. ..
        15. <select id="selectList" resultMap="messageReusltMap" resultClass="Message" parameterCalss="map">
        16. select * from GUESTBOOK_MESSAGE order by GUESTBOOK_MESSAGE_ID desc limit #startRow#, #fetchSize#
        17. </select>
        18. </sqlMap>
      • limit 는 mySql에 있다.

 

바깥고리

자바 프레임워크 활용 전략


JDeveloper에서 iBATIS 실행하기

자동으로 클래스패스를 잡아주니 라이브러리에 추가만 해주면 된다.

1. Library Name에 알기 쉬운 이름을 붙여준다(iBATIS2.3.0.677)

include_lib2.png

 

include_lib.png

 


iBATIS를 통해 더 즐겁게 개발하고, 또 개발의 재미도 느끼고 야근도 덜 할 수 있기를 기원한다. - xx

불가지론자(경험해보지 않은 것은 믿을 수 없다) - xxi

"망치를 가진 사람은 모든 것을 못으로 본다" , 환경이 다양하면 다양한 도구가 필요한 법 - xxii

책을 쓰는 것은 (소프트웨어를 작성)하는 것보다 더 어렵다. - xxiv

돈을 위해 낮에는 일을 하고 명성과 영광을 얻기 위해 밤에는 오픈소스 소프트웨어(또는 책)를 작성하기 위해 시간을 보낸다.(클린턴 비긴) - xxiv

긱(geek: 학업이나 일, 컴퓨터 등에 몰두하다 보니 세상물정과는 거리가 멀어진 사람 / 특정 분야에 대해 광적인 사람), 우리는 첫 번째 컴퓨터를 가졌을때의 좋은 기억이 있고 그 컴퓨터를 사주는 투자가 나중에 좋은 결과를 낳게 된다는 것을 아는 부모님을 신뢰한다. - xxv

은 무언가를 배우는 최고의 방법, 종이책이 전자책으로 대체되거나 뒤통수에 잭을 꼽아서 몇 초안에 정보를 업로드하는 방식으로 바뀔 거라는 등 많은 억측, 나는 책을 좋아한다. 책은 편리하게 갖고 다닐 수 있고, 다루기도 쉽기 때문이다. 책에 메모를 남기고, 종이를 접고, 반으로 쪼개서 갖고 다닐 수도 있다.(클린턴 비긴) - xxvii

 사람들은 스스로 동기를 부여받아 탐구하는 동안 배운 것들을 기억(인지 과학), 인류는 행동하며(in action) 배운다. - xxxii

 

노하우

db.properties 위치

 

 

'스프링3.0' 카테고리의 다른 글

contextConfigLocation  (0) 2012.07.04
스프링 3.0 + ibatise  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

스프링 3.0 + ibatise

2012. 7. 3. 13:35

 

FOCUS : 
Eclipse + Maven + Spring Framework  개발환경 설정.

Reference :
1. http://www.oracle.com/technetwork/java/javase/downloads/index.html
2. http://www.eclipse.org/downloads
3. http://openness.tistory.com/107
4. http://tomcat.apache.org/download-70.cgi
5. http://blog.daum.net/istae0430/279
6. http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
7. http://blog.doortts.com/59 
8. http://alexk.springnote.com/pages/3501753#toc_2
9. http://maven.apache.org/download.html
10. http://eclipse.org/m2e/
11. http://eclipse.org/m2e/download
12. http://stackoverflow.com/questions/2921473/m2eclipse-eclipse-is-running-in-a-jre-but-a-jdk-is-required
13. pom reference ( http://maven.apache.org/pom.html)
14. http://kongkk.springnote.com/pages/8115902
15. http://sepiroth11.tistory.com/entry/SetPropertiesRuleServerServiceEngineHostContext-Setting-property-source-to-orgeclipsejstjeeserver%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%AA%85-did-not-find-a-matching-property
16. http://entireboy.egloos.com/4534698

Need to known :
The APR based Apache Tomcat Native library 

Maven http://maven.apache.org/  
    1) How do i build my project http://www.avajava.com/tutorials/lessons/how-do-i-build-my-project.html

    2) build lifecycle phase :http://cvs.peopleware.be/training/maven/maven2/buildLifecyclePhases.html#site

Spring Framework http://www.springsource.org/  , 
    1)  Spring Framework module 설명  : http://blog.naver.com/gigar/60121489281 





spring Framework 개발환경 설정에 대해 정리해 본다.
개발 환경 설정 하는데, 왜 이리 걸리는게 많은지, 환경 설정 하다가 포기하겠당 ㅋㅋ
그래서 다시 한번 정리!!



- 개발환경은 아래와 같은 순서로 설정  (for windows 7)
1. java 설치
2. eclipse 설치.
3. tomcat 설치 + eclipse wts 설정
4. maven 설치 + eclipse m2eclipse 설치
5. spring Framework 설정



1. java 설치 
아래의 URL 에서 JDK 7  download
http://www.oracle.com/technetwork/java/javase/downloads/index.html

JDK7 설치 후, 윈도우 환경변수에 JAVA_HOME 설정
JAVA_HOME --> C:\Dev\Java\jdk1.7.0


2. Eclipse(Indigo SR1) 설치 
아래의 URL 에서 Eclipse IDE for Java EE Developers download 
http://www.eclipse.org/downloads/

받은파일 (eclipse-jee-indigo-SR1-win32.zip)의 압축해제로 eclipse 설치 


3. tomcat 설치 + eclipse wts 설정 ( 참고 : http://openness.tistory.com/107)
아래의 URL에서 tomcat 7.0 download
http://tomcat.apache.org/download-70.cgi

받은파일 압축해제로 tomcat 설치 
tomcat 설치 후, 윈도우 환경변수에 CATALINA_HOME 설정
CATALINA_HOME -->D:\tomcat

Eclipse 에서 New > Other > Server > Apache Tomcat v7.0 Server 선택 
 tomcat installation directory -> d:\tomcat 설정
 jre -> jre7 (C:\Dev\Java\jdk1.7.0) 설정

위와 같이 설정하면 
하단의 Servers tab 에 Tomcat v7.0 Server at localhost [Stopped, Republish] 라고 나온다.

Tomcat v7.0 Server at localhost Start 후, 웹브라우저에 http://localhost:8080 로 실행 했을때 아래와 같이 나오면 정상



tomcat 설치중 문제발생 : (참고 : http://blog.daum.net/istae0430/279)
위와 같이 tomcat 실행이 되는 건 확인 했는데 eclipse console log를 보니 아래와 같은 log가 있다. ㅜㅜ

[log]
정보: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Dev\Java\jdk1.7.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;...
2월 10, 2012 3:44:47 오후 org.apache.coyote.AbstractProtocolHandler init


근데 ARP 라는 넘이 머 하는 넘인지는 모르겠는데 검색 해 보니 
http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
가서  tcnative-1.dll(windows 의 경우) 을 받아 java.library.path 넣으란다. 

그래서 v 1.1.17 을 받아 C:\Dev\Java\jdk1.7.0\bin 에 넣었더니 아래의 붉은색과 같이 log가 뜬다. 닝길 ..

[log]
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: An older version 1.1.17 of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of 1.1.20
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: Loaded APR based Apache Tomcat Native library 1.1.17.
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].


 다시 v1.1.20 을 받아  C:\Dev\Java\jdk1.7.0\bin 에 넣고 Server를 실행 시켜보니 아래와 같이 버전 맞지 않는 문제가 해결 되었다.   아직 ARP 가 머 하는데 쓰는 넘인지 잘 모르겠는데, 이넘이 없어도 문제없이 실행되는 거 같다. 
이 ARP라는 넘이 먼지 나중에 찾아봐야지.

[log]
2월 10, 2012 3:50:34 오후 org.apache.catalina.core.AprLifecycleListener init
정보: Loaded APR based Apache Tomcat Native library 1.1.20.
2월 10, 2012 3:50:34 오후 org.apache.catalina.core.AprLifecycleListener init
정보: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].



4. maven 설치 + eclipse m2eclipse 설치
 ( 참고 : http://blog.doortts.com/59 , http://alexk.springnote.com/pages/3501753#toc_2)

4.1 Maven 설치 : 아래의 URL에서 Maven download
http://maven.apache.org/download.html

받은파일 압축해제로 maven 설치 
maven 설치 후, 윈도우 환경변수에 M2_HOME 설정
M2_HOME -->C:\Dev\apache-maven-3.0.4

cmd 창에서 mvn -version 을 타이핑 해보면 아래와 같이 결과가 나온다. 

 




4.2 m2eclipse 설치  ( 참고 : http://eclipse.org/m2e/http://eclipse.org/m2e/download/)
eclipse > help > install new software 에 http://download.eclipse.org/technology/m2e/releases 
를 입력하면 m2e plugin을 다운 받을 수 있다. 

다운로드가 완료되면 아래와 같은 윈도우가 뜬다. 


Restart Now 실행 

eclipse > window > preferences  > Maven > Installations에 보면 Embedded 되어 있는 Maven 버전이 3.0.2로 
apache 에서 다운로드 받은 버전보다 더 낮아 add 해 주었다. 



m2eclipse 문제 발생시 참고 
(http://stackoverflow.com/questions/2921473/m2eclipse-eclipse-is-running-in-a-jre-but-a-jdk-is-required)

maven build 실행시 compile 문제 발생하면 참고 
http://maven.40175.n5.nabble.com/Unable-to-locate-the-Javac-Compiler-Problem-td133804.html

5. spring Framework 설정
Maven을 깔았으니 eclipse maven project로 spring Framework을 설정 해 보려한다.

5.1 project 생성
 1)eclipse > new > project > maven > maven project 선택 
 2) create a simple project (skip archetype seletion) check 
Next
 1) Group Id -> com.test2
 2) artifact id -> springTest2
 3) Packaging -> war 
Finish 

아래와 같은 모양으로 project 생성 




pom reference ( http://maven.apache.org/pom.html)
spring framework 사용을 위해 첨부 파일과  같이 pom.xml을 만든다.
pom.xml 중 spring 과 ibatis 이외의 부분은 없어도 될거 같다.

삽질 원인
 - Oracle JDBC Driver는 라이센스 문제로 인해서 Maven Central 저장소에서 로컬 저장소로 jar 파일을 정상적으로 다운로드 받지 못한다!!! (오라클이 갑자기 싫어질라고 한다.)

해결방법
 
- 방법1 : pom.xml 파일에 http://mesir.googlecode.com/svn/trunk/mavenrepo 메이븐 저장소를 추가해서 사용하는 방법
<dependencies>
        <dependency>
       <groupId>com.oracle</groupId>
     <artifactId>ojdbc14</artifactId>
     <version>10.2.0.4.0</version>
        </dependency>
<dependencies> 

 <repositories>
<repository>
<id>mesir-repo</id>
<url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
</repository>
</repositories> 
*** 주의 사항 :  mesir-repo  저장소를 추가하지 않고 ojdbc 의존성만 추가한 후 빌드를 수행하게 되면... 로절 저장소가 더럽혀 지는 경우가 발생하는 것 같다.(아님말구!) 그런 경우 로컬 저장소에서 해당 내용을 삭제한 후 다시 시도를 해야 한다.

- 방법2 : 
직접 ojdbc?.jar 파일을 다운로드 받아서 mvn 명령어로 로컬 저장소에 추가하는 방법
  1. 
 ojdbc14.jar 파일을 다운로드 받은 후 mvn 명령을 이용하여 로컬 저장소에 ojdbc14.jar 를 추가한다. 
mvn install:install-file -Dfile=ojdbc14.jar -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.0 -Dpackaging=jar -DgeneratePom=true  

  2. pom.xml 파일에 의존성 추가
<dependencies>
        <dependency>
       <groupId>com.oracle</groupId>
     <artifactId>ojdbc14</artifactId>
     <version>10.0</version>
        </dependency>
<dependencies> 
 

Oracle JDBC Driver 덕분에 maven에 대해서 좀더 알게 된것 같다. 하지만 너무 많은 시간을 삽질하는데 시간을 허비해버렸다.
Maven을  사용하면 기존의 개발환경 보다는 편리한 점이 있지만... 아직 이클립스의 maven 플러그인이 완별하지 않은 것 같고 또 maven 자체도 좀더 스마트해질 필요가 있을 것 같다. JDK 에도 node.js의 NPM과 같은 툴이 포함되었으면 하는 바램이다.











pom.xml 을 첨부된 pom.xml 과 같이 설정 후, 아래와 같은 오류가 발생했다.


 Project configuration is not up-to-date with pom.xml. Run project configuration update 라는 메세지가 있어   Project > properties > Maven > Update Project Configuration... 실행 
--> 오류 가 제거 되었다. 

그리고 아래 그림과 같이 Maven Dependencies 에 library가 추가 되었다..
예전엔 jar를 하나씩 다 복사해서 넣고 썼었는데 , library 관리가 참 편리해 졌다. ㅋㅋ



2) maven project를 tomcat 에 add
으미 생성한 Maven 프로젝트를 tomcat 에 add 하려고 Servers > add and remove 메뉴를 선택하면 add 할 resource가 없단다.. 그럼 내가 만들어 놓은 maven project는 tomcat에 add 할수 없다? 
그래서 한참을 헤멨다..그런데 ㅋㅋ ( 참고 : http://kongkk.springnote.com/pages/8115902
참고에 보면 project Facets를 찾아서 Dynamic Web Module 를 선택하면 된다다. 

Project > properties > Project Facets > Convert to faceted form > Dynamic Web Module (check)
그리고 바로 아래에 i Further configuration available.. 에서 src/main/webapp 로 Web contents 경로를 지정했다.
그러면 아래 그림과 같이 src/main/webapp/WEB-INF가 생성되고, tomcat에 publish 가능한 project가 된다.


tomcat에 project를 추가하고 tomcat을 실행시켜보니 
에고고 산넘어 산이구나 아래의 문제가 발생한다. 이건 또 머꼬?

경고: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:springTest2' did not find a matching property.
그래서 또 검색을 해 보니..다들 격고 있구나 ㅋㅋ 
(참고 : http://sepiroth11.tistory.com/entry/SetPropertiesRuleServerServiceEngineHostContext-Setting-property-source-to-orgeclipsejstjeeserver%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%AA%85-did-not-find-a-matching-property)

Servers tab > Tomcat v7.0 더블클릭 > Overview 하단에 Server options 에서 
Publish module contexts to separate XML files 에 check 하란다. 

그리고 다시 tomcat 실행하니, 아래와 같은 경고가 또 떴다.  
경고: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:springTest2' did not find a matching property.

검색중 어딘가에서 살짝 본 기억이 난다. 
springTest2 바로 위의 Servers에서 server.xml 을 열어보면 하단에 
<Context docBase="springTest2" path="/springTest2" reloadable="true" source="org.eclipse.jst.jee.server:springTest2"/>
부분이 있는데 source="org.eclipse.jst.jee.server:springTest2" 형식을 tomcat이 지원하지 않아서 그런다고 한다.
더 진행해 보고, spring Framework이 동작하지 않으면 다시 이유를 찾아봐야겠다. 


3) web.xml , dispatcher-servlet.xml , controller , jsp 


 web.xml , dispatcher-servlet.xml , controller, jsp 모두 만들고 tomcat을 실행하니 또 아래와 같이 오류 발생

심각: Exception starting filter encodingFilter
java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
 at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:415)
 at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:397)
 at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118)
 at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:252)
 at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:372)
 at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:98)
 at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4562)
 at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5240)
 at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5235)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
 at java.util.concurrent.FutureTask.run(FutureTask.java:166)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)

검색해 보니 결국은 spring Framework library가 WEB-INF/lib에 없어서 발생한 문제다.
(참고 : http://entireboy.egloos.com/4534698)
eclipse 설정을 통해 해결 가능한데 다음과 같이 하면 된다.

Project > properties > Deployment Assembly > add button > java Build Path Entries  선택 그리고 Next
Maven dependencies 선택 하면 아래 그림과 같이 설정된다.
Maven Dependencis -> WEB-INF/lib가 새로 생성 된것 




설정을 마치고 tomcat을 다시 실행 시켰더니 아래와 같이 log msg가 뜨지만 "INFO" Level 이라 그냥 지나갔다.

정보: validateJarFile(D:\Dev\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\springTest2\WEB-INF\lib\geronimo-servlet_2.5_spec-1.2.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class


브라우저 실행후 http://localhost:8080/springTest2/test1.do  실행 시켰더니 원하는 페이지가 떴다.
휴우~
중간 중간의 고비를 잘 넘기고 spring framework으로 만들어진 간단한 페이지가 떴다.



아직 잘못 설정되어 있는 부분이 있을 수 있지만 , spring Framework을 하나씩 더 알아가면서 바꾸면 될것 같다.
간단하게 Hello 하나 찍는 건데 꽤 긴 시간을 들였다. 에공~~
늙어도 개발을 취미삼아 조금씩 할 수 있었으면 좋겠는데 , 어째 개발 환경 설정이 점점더 복잡해 지고 있는 것 같다.

개발환경도 단순화 시킬수 없을까? 잡스흉아처럼...ㅋㅋ







spring Framework 개발환경 설정(1) 에서는 eclips Maven project 로 spring Framework 설정방법을 살펴봤다.
이번에는 이미 설정되어 있는 spring Framework에   iBatis 설정을 추가한다. 

FOCUS
spring Framework 에 iBatis 설정 하고 테스트 페이지 만들기

Reference
1. jsp taglib 사용 위해 maven 에 설정 해야 할 dependency?

   <dependency> 
    <groupId>javax.servlet</groupId> 
      <artifactId>jstl</artifactId> 
      <version>1.2</version>
 </dependency>
 
 <dependency>
   <groupId>taglibs</groupId>
   <artifactId>standard</artifactId>
   <version>1.1.2</version> 
    </dependency>

2. iBatis 설정하여 개발할때 편하게 개발 할 수 있는 순서
  1)Table  스키마 확인
  2) iBatis resultMap 작성
  3) DB Query 문 작성
  4) DAO 작성
  5) JSP 작성
  6) Service & Controller 작성
  7) 필요하면 환경설정파일 변경.


Need to know
iBatis 사용법.




iBatis 연동을 위해 아래의 작업을 진행한다.
1. pom.xml에 iBatis dependency 추가.
2. /WEB-INF/web.xml 수정.
3. /WEB-INF/spring/spring-config.xml 생성 .
4. /WEB-INF/sql-map-config.xml 생성 
5. Test.xml(sqlmap 파일) 생성.
6. dao 파일 생성
7. domain 생성
8. Controller 수정
9. JSP 수정


1. pom.xml 에 iBatis dependency 추가.
   ( spring Framework 개발환경 설정(1) 에 첨부된 파일 이미 추가되어 있슴)
<dependencies>
...
 <!--  DB- jdbc driver 시작  -->
    <dependency>    
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.18</version>
    </dependency>
    <!--  DB - jdbc driver끝  -->
    
    <dependency>
   <groupId>commons-dbcp</groupId>
   <artifactId>commons-dbcp</artifactId>
   <version>1.4</version>
 </dependency>

 <dependency>
   <groupId>org.apache.ibatis</groupId>
   <artifactId>ibatis-sqlmap</artifactId>
   <version>2.3.4.726</version>
 </dependency>
...
</dependencies>



2. WEB-INF/web.xml 수정
아래의 내용을 web.xml 에 추가. 

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/*-config.xml</param-value>
 </context-param>

 <listener>
  <display-name>SpringContextLoader</display-name>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>


3. /WEB-INF/spring/spring-config.xml 생성 
web.xml 에 선언 후, 
/WEB-INF/spring 디렉토리에 *-config.xml 로 명명되는 파일은 spring configuration 용으로 사용.

아래는 spring-config.xml (jdbc , ibatis, dao 설정)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
 
    
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://domain or ip/dbname"/>
        <property name="username" value="id"/>
        <property name="password" value="password"/>
        <property name="maxActive" value="30"/>
        <property name="maxIdle" value="10"/>
        <property name="maxWait" value="1000"/>
        <property name="defaultAutoCommit" value="true"/>
    </bean>

 
 <!-- SqlMap setup for iBATIS Database Layer -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
  <property name="dataSource" ref="dataSource"/>
 </bean>
 
 
 <!--  DAO -->  
 <bean id="testDao" class="com.springTest2.dao.TestDao">
  <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>

</beans>


4. /WEB-INF/sql-map-config.xml 생성 

아래의 내용은 query 문이 기록된 xml resource 설정

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
 <sqlMap resource="com/springTest2/dao/map/Test.xml" />
</sqlMapConfig>

5. Test.xml(sqlmap 파일) 생성.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Test">

 <typeAlias alias="TestTableInfo" type="com.springTest2.domain.TestTableInfo" />
 
 <resultMap id="testTableInfoResult" class="TestTableInfo">
  <result property="name" column="NAME" />
  <result property="age" column="AGE" />
  <result property="sex" column="SEX" />
 </resultMap>


 <!--  testTable 모든 데이터 조회  -->
 <select id="getTestTableList" parameterClass="map" resultMap="testTableInfoResult">
  SELECT name, age, sex 
  FROM testTable 
 </select> 

</sqlMap>


6. dao 파일 생성
package com.springTest2.dao;

import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;


public class TestDao extends SqlMapClientDaoSupport{

 //testTable list를 조회한다.
 public List getTestTableData(Map map ) throws DataAccessException {
  return  getSqlMapClientTemplate().queryForList("getTestTableList", map);
 }
 
 
}


7. domain 생성 

package com.springTest2.domain;

public class TestTableInfo {
 
 private String name;
 
 private int  age;
 
 private String sex;

 
 public String getName() {
  return name;
 }

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

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getSex() {
  return sex;
 }

 public void setSex(String sex) {
  this.sex = sex;
 }
 

}


8. Controller 수정

보통 Controller 에서는 Service Object만 사용하나  지금 테스트 하는 예제는 단순하기때문에 Service단을 생략하고 
Controller에서 Dao를 설정하여 사용하였다.


package com.springTest2.controller;

import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.springTest2.dao.TestDao;

  
  
 @Controller
 public class TestController {
 
  @Autowired
  private TestDao testDao;
  
 
  @RequestMapping("/test1.do")
  public ModelAndView helloworld(){
  
   String message = "Hello Spring Framework";
   
   ModelAndView mnv = new ModelAndView();
  
   mnv.setViewName("resultPage");
   mnv.addObject("message", message);
  
   //query 문에 넘길 param 없으므로 아무값도 설정하지 않는다.
   HashMap map = new HashMap();
   
   //testTable data를 조회한다.
   List list = testDao.getTestTableData(map);
   mnv.addObject("TestTalbeDataList", list);
   
   return mnv; 
  
  }

  
 }

 

9. JSP 수정

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    ${message} 
    <br/>
    <br/>
    <table border="1">
     <!- DB에서 조회한 데이터 Display 하는 영역 -->
     <c:forEach var="TestTableData" items="${TestTalbeDataList}" >
          <tr>
           <td>name</td>
           <td>age</td>
           <td>sex</td>
          </tr>
         <tr>
            <td>${TestTableData.name}</td>
            <td>${TestTableData.age}</td>
            <td>${TestTableData.sex}</td>
          </tr>
      </c:forEach>
    </table>

</body>
</html>

결과확인




이제 spring Framework + iBatis 까징 설정 했으니 logging만 설정하믄 기본적인 준비는 다 되는 것 같다.

FOCUS
spring Framework에 logging 설정


Reference
1. http://shonm.tistory.com/217
2. http://blog.outsider.ne.kr/561

Need to know
/main/resource/ log4j.properties 파일이 위치하게 하는 설정법은 어떻게 하는거지?


1. /WEB-INF/ web.xml 에 아래와 같이 listener 추가.
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

2. /WEB-INF/web.xml 에서 Log4J 설정파일 위치 설정

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/logging/log4j.properties</param-value>
</context-param>

3. log4j 설정 파일인 log4j.properties 작성

  2.에서 설정한 위치에 log4j.properties 작성.


4. code 에 logging 적용시

private Logger log = Logger.getLogger(this.getClass());   
...
...

log.debug("this is spring Framework logger Test");

'스프링3.0' 카테고리의 다른 글

contextConfigLocation  (0) 2012.07.04
MyBatis  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

내가 가장 좋아하고 많이 사용하는 자바 프레임워크는 스프링과 하이버네이트다. 거의 5년전 이 두개의 프레임워크를 처음 접했을 때의 충격과 감동은 지금도 잊혀지지 않는다. 두가지 다 내가 가졌던 오랜 고정관념을 확실히 깨뜨려주었고, 자바 프로그래머로서의 정체성을 다시금 확인할 수 있게 해주었다. 자바가 객체지향언어이며 비록 웹 개발을 한다고 할지라도 구지 ASP인지 JSP인지 구분이 안가는 JSP+스크립트성 자바코드 방식이 아닌 진정한 자바의 객체지향언어로서의 장점을 지키며 개발할 수 있다는 것을 분명 확인할 수 있었다. DB지상주의자들의 오만한 주장처럼 자바(또는 일반 프로그래밍 언어)는 그저 DB를 호출하고 UI랑 연동시켜주는데 사용하는 껍데기 인터페이스 뿐이다라는 수십년된 구닥다리 생각이 얼마나 시대에 뒤떨어지고 무지에서 나온 것인지도 분명히 깨닫게 되었다.

특히 하이버네이트는 당시 10년이 넘도록 매진해온 RDB의 경험과 매력을 사실 한층 더 가치있게 활용하는 법을 알려준 가장 고마운 프레임워크이다. 80년데 DBase시리즈로 출발해서 클리퍼,폭스베이스,폭스프로 등을 경험하다 93년에 처음 오라클7.3을 대형 프로젝트에서 처음 경험 했을 때 알게된 RDB의 매력과 능력이 당시에는 존재하지도 않았던 자바라는 멋진 언어와 이렇게 잘 조화되어서 양쪽의 장점을 다 살려서 빠르고 정확하고 멋지게 개발할 수 있구나라는 생각을 하게 만들어주었다. 당시 하이버네이트는 버전 2.6이었고, Gavin King이 호주 멜번에서 주로 EJB기반의 프로젝트에 참여하던 시절에 그의 매일 밤과 주말 시간을 모두 희생해서 열정적으로 개발하고 지원하던 사실상 1인 개발 프레임워크였던 시절이었다. 그럼에도 I모사의 책상 앞에서만 똑똑한 연구진들이 만들어내, 기업의 덩치로 밀어붙여 억지로 표준기술로 만들어버린 EntityBean이라는 자바역사상 가장 웃음거리가 된 기술보다 백만배쯤 낫다고 느껴졌다. 사용자들의 반응도 뜨거웠다. 결국 Gaving King은 JBoss에 영입되어 하이버네이트 개발을 책임지는 풀타임 오픈소스 개발자가 되었다.

그 당시 Hibernate vs JDBC와 관련된 논쟁이 많이 있었다. 그때 나름 공감을 받던 주장은 이렇다.

만약 애플리케이션 개발자가 DB설계를 직접 할 수 있거나, 영향력을 줄 수 있는 위치에 있다면 하이버네이트가 좋고, 아니고 DBA팀을 비롯한 애플리케이션 쪽은 전혀 모르고 DB만 고려하고 설계하거나 이미 오래전에 만들어져서 운영준인 레거시DB라는 JDBC를 선택하는 것이 낫다

이유가 뭘까? 왜 같은 DB이고 같은 애플리케이션이 결국 사용할 것인데 개발자들이 직접 DB를 관장하면 하이버네이트에 적합하고, 아니라면 부적합한 것일까? 어떤 이들은 이것을 하이버네이트는 객체DB스타일의 설계가 필요하기 때문에 ODB적인 구조로 DB를 특별하게 만들어야 하기 때문에 객체설계 후 그에 따른 DB스키마 작성이 필요하기 때문이라고 말한다. 하이버네이트의 기본도 모르는 바보들의 주장이다. 하이버네이트는 순수 객체기반 영속성 솔루션인 엔티티빈에 대한 반감과 저항으로 등장한 기술이다. 하이버네이트가 지향하는 것은 진정한 O"R"M이다. 저 R이 관계형DB의 R이라는 것을 모르지는 않을텐데 말이다. 왜 DB를 써서 ODM이라고 하지 않고 ORM이라고 구지 관계형DB라는 것을 명시했을까? 그 이유는 하이버네이트는 관계형DB와 자바의 매핑이 목적인 프레임워크이기 때문이다. 그 말은 하이버네이트에 적합하게 따로 설계된 DB가 아닌, 가장 관계형DB다운 DB라면 하이버네이트와 완벽하게 연동이 될 수 있다는 말이다.

레거시DB와 하이버네이트 2.x가 함께 사용하기에 부적합했던 이유는 딱 한가지이다. 무식한 DBA나 DB설계자들 탓에 정규화도 제대로 되지 않은 엉망인 구조의 DB들인 경우가 있었기 때문이다. 물론 필요에 따라 비정규화를 한 경우도 있겠지만, 국내 한 유명 DB컨설턴트의 푸념처럼 정규화를 거치지도 안고 처음부터 그냥 생각없이 퍼포먼스를 위해서라는 근거도 없는 명분으로 비정규화부터 하는 식의 엉터리 DB설계들이 판을 치기 때문이라는 것이다. 하이버네티는 2.x조차도 RDB의 바른 설계원칙을 따라 만들어진 DB라면 완벽하게 매핑시킬 수 있다.

또 한가지 주장은 퍼포먼스이다. ORM은 JDBC를 그대로 가져다가 사용하는 것에 비해서 분명 퍼포먼스의 손해가 있다. 하지만 이 가정은 아주 단순한 기본적인 아이디어일 뿐이다. 혹 하이버네이트 1.x라면 들어맞을지도 모르겠다. 하지만 하이버네이트는 수많은 ORM의 퍼포먼스 향상 기법을 도입했고, 단지 매핑된 객체와 하이버네이트의 기반 HQL을 이용해서 거의 완벽에 가깝게 그것이 만들어 내는 SQL을 제어할 수 있다. 초기 ORM기술의 바보같은 n+1 퀴리 문제 같은 것은 더 이상 하이버네이트에서는 아무 문제가 아니다. 모델은 그대로 1tom 이더라도 그 정보를 조인해서 한번에 가져오는 것은 아주 간단한 일이다. 혹 하이버네이트에 무지한 자들이 하이버네이트는 JDBC/SQL을 사용하지 않는 것처럼 착각하는데 하이버네이트도 결국 JDBC를 이용해서 SQL로 DB와 커뮤니케이션 한다. 숙련된 하이버네이트 개발자들은 엔티티 객체를 다루면서 그것이 백그라운드에서 만들어 내는 SQL을 완벽하게 함께 머리로 그릴 수 있는 능력이 있다. 게다가 하이버네이트는 매우 간단한 설정만으로 객체베렐, 퀴리 레벨의 다양한 캐슁을 지원한다. 그것도 분산서버에서 트랜잭션까지 지원하는 캐슁도 아무런 문제없이 지원한다. DB스타일에 따라 캐슁이 적절히 사용되면 별다른 캐슁기술을 적용하지 않은 JDBC코드와 비교해서 훨씬 나은 성능을 보여줄 수도 있다.

JDBC를 이용한 애플리케이션도 이전처럼 ResultSet을 jsp까지 끌어가서 화면에 바로 출력하는 미련한 짓은 하지 않을 것이다. 다 DAO레이어를 만들고, 어떤 스타일이든 DTO를 사용해서 객체에 정보를 담는다. 그런 오버헤드가 사실상 전체 퍼포먼스에 미치는 영향은 극히 미미한데다 그것으로 얻을 수 있는 개발생산성과 버그의 위험도를 줄일 수 있는 가능성등의 장점이 워낙 크기 때문에 당연히 다들 DTO를 사용한다. 그런데 왜 하이버네이트의 매핑은 무슨 엄청난 오버헤드가 있어서 별 대단한 것도 아닌 시스템에서조차 성능때문에 못쓴다라고 하는 것일까?

하이버네이트 성능과 관련해서 국내 초대형 사이트에서만 잔뼈가 굵은 엔트웍스님이 아주 잘 설명한 글이 있다. 2006년 작성글이니 이전 버전 기준일테고 조금 철지난 내용도 있지만 그래도 하이버네이트에 대한 잘못된 미신을 타파하는데 도움이 될 것 같다.

 

DB의 성능에 대한 요구는 DB자체의 발전만으로는 커버가 불가능하다. 경험해본 사람들은 DB의 스케일업과 아웃이 얼마나 큰 비용이 드는지는 잘 알것이다. 클러스터링이 가장 어렵고, 된다고 해도 엄청난 비용이 드는 것이 DB이다. 작년엔가 모 금융사에서 메인메모리만  수백G짜리 수십억(백억이 넘던가..) 대의 초대형 DB서버를 구입해서 콘솔리데이션 프로젝트를 했었는데 얼마나 끔찍하게 고생했는지 거기에 참여했던 컨설턴트를 통해서 들은 적이 있다. 그래서 이제는 각종 Data Grid 와 같은 분산 기술들이 자바와 같은 객체지향언어와 결합해서 엄청난 속도로 발전하고 있다. DB의 절대왕좌를 차지하고 있는 오라클 조차 Coherence의 Tangosol을 인수했다는 것을 모르는가? Coherence는 수백대의 클러스터 그리드를 이용해서 미국의 한 금융 벤치마크에서 백만 TPS를 기록했다고도 한다. 국내의 경우에도 리니어하게 스케일링되는 구조에서 노드당 1500TPS이상을 가뿐하게 기록했다고 나와있다. 리니어스케일이 되는 이런 기술들이 하이버네이트와 얼마나 잘 결합되는지는 하이버네이트-Coherence의 역사를 보면 아주 잘 알 수 있을 것이다. 시대가 이렇게 빠르게 흘러가는데 아직도 기업의 DB관리는 보수적이고 어쩌고 저쩌고 하면서 한번 배운 기술 마르고 닳도록 울궈먹기 모드로 꼭 들어가야 하는 것일까?

 

스프링의 초기에도 그랬던 것처럼 그런 이유는 무지해서 그렇다. 잘 모르거나, 어설픈 얕은 지식으로 그냥 자신의 무지를 성능탓으로 돌리는 것이다.  그것은 마치 스프링으로 개발하면 메인프레임과 연동은 불가능하다(EJB만 된다)는 헛소리와 마찬가지 주장이다.

다시 위의 DB설계의 책임이 누구에게 있냐에 따른 하이버네이트 적용의 판단기준을 살펴보자. 하이버네이트 팀은 저런 상황을 잘 파악하고 있었다. 그리고 이상적인 모델만 현실에 존재하지 않는다는 것을 잘 파악했다. 그래서 하이버네이트 3.0이 나온 것이다. 이미 3년 전에 말이다. 하이버네이트3.0은 정규화가 잘된 깔끔한 DB뿐 아니라 바보 DB모델러들이 어설프게 설계한 레거시 DB도 매핑하는데 아무런 문제가 없게 만들어졌다. 게다가 엔티티 단위가 아닌 각종 복잡한 프로젝션 쿼리(일명 리포트 쿼리)도 완벽하게 지원한다. 역시 객체 단위가 아닌 벌그 업데이트도 당연히 지원한다. 사실상 SQL레벨에서 하던 거의 모든 작업을 하이버네이트의 OR매핑 장점을 그대로 살린채로 다 적요할 수 있다. 심지어 DB에 아주아주 specific한 네이티브 쿼리를 사용해야 하는 경우도 얼마든지 적용된다. iBatis못지않은 SQL-객체 바인딩도 지원한다. 심지어 그 결과를 DTO가 아닌 엔티티로 가져와서 작업하는 것도 가능하다. 하이버네이트를 쓰면 못쓰는 DB특화된 SQL이 있어서라는 엉터리 주장을 하는 사람들을 보면 한심하기 짝이 없다. Stored Procedure도 아무런 문제없이 하이버네이트 안에서 호출이 가능하다.

 

오늘 아침에 읽은 글이다.

스터디 끝나고, 간단히 식사를 하면서 왜 국내에서는 하이버네이트 보다 iBatis가 더 각광 받느냐에 대한 의견 교환이 있었습니다. 비즈니스 모델링 단계에서 개발자 혹은 설계자가 자료 구조에 대한 고민을 하고 되는데, 객체지향 분석/설계에 충실하다면 객체 모델링을 통해 도출된 데이터 구조 자체를 저장소(repository)로 손쉽게 매핑(mapping)할 수 있는 하이버네이트가 유리하다는 점에서는 동의했습니다. (사실 제 첫번째 직장이 객체형 데이터베이스 회사였기 때문에 충분히 수긍할 만한 의견이었습니다.)

하지만 국내 IT 현장에서 가장 큰 발언권을 가진 사람들은 개발자가 아니라 시스템 운영자들 혹은 데이터베이스 관리자들입니다. IT를 잘 모르는 경영진 입장에서는 아무래도 회사의 자산이라고 여겨지는 것이 바로 데이터베이스이고 프로그램은 덜 중요해 보이거든요. 그러다 보니, 시스템 개발 현장에서 가장 먼저 그리고 중요하게 분석/설계되는 것은 업무 요건이 아니라 바로 데이터베이스 설계입니다. 데이터 구조가 먼저 설계되고 쿼리를 만들고 그 위에 어플리케이션을 탑재하는 순서로 개발하니 당연히 하이버네이트는 적합한 프레임워크로 고려될 수 없게 되는 것입니다.

이상(ideal)을 추구하는 것은 산을 오르는 것과 같다

 

제대로 DB설계가 된다면 왜 그것이 하이버네이트에는 적합하지 않다는 말인가? 참 답답하다. 이 글을 읽다가 답답한 마음이 들어 이 글을 쓰기 시작했다.

물론 나도 하이버네이트가 모든 곳에 항상 적용가능하고 낫다고 보지는 않는다. 예를 들어, DB는 간단하고 부하만 큰 포탈의 게시판, 블로그 등은 ORM이 적합한 곳이 당연히 아니다. 객체 매핑 해봐야 무슨 이득이 있겠는가. 사실상 저런데는 RDB조차 적합하지 않다. 4억명의 회원을 보유한 ebay는 잘 알려진대로 DB트랜잭션조차 사용하지 않는다고 한다. 바른 선택이다. 또 데이터의 입출력은 거의 없는 분석위주의 OLAP시스템도 하이버네이트 쓰는 것이 불가능하지는 않으나 별 장점이 없다. 그럴땐 OLAP쿼리 관리나 깔끔히 하면서 iBatis 같은게 낫다고 하겠다. 고객이 정말 무식과 고집을 겸비하고 있는데다, 밉보이면 향후 프로젝트에 지장이 있을 것 같은데 무조건 JDBC기반 DAO를 쓰겠다고 주장하면 살금살금 꼬셔서 SpringJDBC정도만 어찌 도입해보는게 나을 것이다. 정치적인 이유지만 어쨌든 시스템을 원활히 개발하기 위한 어쩔 수 없는 선택이 있다는 것도 안다. 또 애플리케이션은 DB의 인터페이스 용으로만 쓰고 모든 로직이 다 Stored Procedure에 저장되어있는 구닥다리 시스템이고 그것을 고칠 마음이 전혀 없다면 역시 하이버네이트는 선택의 대상이 아니다. 하지만 그 외의 모든 경우라면 하이버네이트는 충분히 적합하고 적용할 수 있고 많은 장점이 있다. 하지만 개발자들이 먼저 나서서 하이버네이트는 성능이 어쩌고, 적합하지 않아서 어쩌고 하는 것은 정말 아니다. 제대로 검증해보고 타당한 증몀을 해봤는가? 장단점을 충분히 진지하게 따져봤는가?

대형사이트? 더욱 더 적극 도입해야 한다. 물론 개발자가 많으면 평균 수준이 떨어지고, 각자 가진 기술수준이 차이가 많이 나서 기술수준 자체를 낮춰야 할 수도 있겠다. SQL만 달랑 넣으면 DTO부터 전 레이어의 기본코드가 딱 만들어지는 초간단 툴들이 요즘 인기있는 이유가 그것이라고 한다. 그만큼 다른 많은 것을 손해를 보고 가야함은 당연한 것이지만. 그렇다고 언제고 SQL만 알고 자바 문법만 아는 사람들로만 시스템 개발을 할 것인가? 오픈소스는 안돼라고 외치던 많은 곳에서 이미 스트럿츠1을 시작으로 이미 스프링과 iBatis 같은 고급 프레임워크 까지 적용이 이뤄지고 있다. 적절한 전략과 충분한 준비와 시간이 있다면 얼마든지 도입 할 수 있다. 개발자가 많으면 구현방식의 통일이 어렵고, 버그의 발생가능성이 높아진다. 하이버네이트와 같은 자바에 충실한 개발방식이 얼마나 개발자의 스트레스를 덜어주고, 생산성을 높이며 버그발생을 줄여주고, DB와 자바, UI까지 왔다갔다 정신없는 것을 충실하게 자바 모델에만 집중해서 개발할 수 있게 해주는지 안다면, 대형사이트일 수록 과감한 도입이 필요할지도 모른다. 그 비싸고 많은 모델러와 컨털선트는 왜 쓰는데…

내가 실무 프로젝트를  초기에 경험 할때는 코볼에 ISAM에 익숙한 노땅 개발자들의 전성시대에서 RDB와 같은 신기술이 막 떠오르려고 하던 때이다. 또 틈새를 비집고 UniSQL과 같은 허접 ODB도 설쳐대던 때다. 그때 ISAM에 익숙한 선배 개발자들의 푸념이 기억난다. 메인프레임에서 ISAM으로 했으면 이 정도는 순식간에 완벽하게 착착 다 만들었을 텐데 이게 무슨 장난감 같은 유닉스에, 복잡한 언어인 C에, 배우기도 힘든 3-Tier기술에, 성능도 떨어지는 RAD툴에 RDB까지 정신이 없다고 투덜대던 시절이다. 왜 복잡하고 지저분한 SQL을 이용하는, ISAM에 비해 성능도 떨어지는 RDB를 써야 하냐는 그때 그 사람들의 모습이 바로 지금 SQL에 익숙한데 왜 하이버네이트와 같은 새로운 기술을 또 공부해야 하냐라고 저항하는 개발자들의 모습과 꼭 닮았다.

 

물론 하이버네이트가 좋으니 당장 바꿔라라고 말하고 싶지 않다. 심지어 하이버네이트 사이트에도 프로젝트 1개월 남았는데 갑자기 하이버네이트로 바꾸자 따위의 생각은 꿈도 꾸지 마라라고 FAQ에 나와있었다. 개발 패러다임의 변화이니 충분한 시간을 가지고 학습하고 최적화된 기술을 익히는 과도기를 거쳐야 할 것이다. 그런 이유에서라면 당장 도입을 지연하는 것은 이해한다. 하지만 별 것도 아닌 중소형 사이트에 시간도 있고, 새로운 프레임워크도 익힌다면서 하이버네이트는 "그거 한국에서는 안돼"라는 말로 아무런 근거도 검증도 없이 그냥 iBatis나 쓰자라는 식으로 가는 모습은 정말 안타깝다. 제발이지 좀 근거를 가지고 구체적으로 비판을 하려면 했으면 좋겠다. 제발이지 나도 화딱지 나서 외국의 개발자들에게 "한국 개발자들은 무식하고 겁쟁이라 하이버네이트는 쓸 줄도 모릅니다"라고 하지 않도록…


'하이버네이트' 카테고리의 다른 글

하이버 네이트 시작 하기.  (0) 2012.06.30
하이버네이트  (0) 2012.06.30
Posted by 사라링

하이버네이트를 시작하기 위한 기본설정을 해봅시다.

Eclipse Galileo
Java 1.6.0_16
Tomcat 6.0.14



http://www.hibernate.org 에서 라이브러리와 플러그인을 다운로드 받습니다.

왼쪽 메뉴에서 'Download' 를 클릭 후 zip 파일을 다운로드 합니다.






하이버네이트 플러그인(Hibernate Tools)은 이클립스 플러그인 설치를 이용해서 합니다.

업데이트 주소는 하이버네이트 홈페이지에서 HIBERNATE Tools 부분에 링크 되어있습니다.



업데이트 주소 : http://download.jboss.org/jbosstools/updates/stable

           마지막에 /버전이름   을 추가 할것. 




플러그인이 잘 설치 되었습니다... ㄷㄷ;





이제 하이버네이트를 하기위한 최소한의 라이브러리를 세팅합시다.

다운로드 받은 hibernate-distribution-3.3.2.GA-dist.zip 파일을 압축 해제합니다.

hibernate3.jar 와 lib\required 폴더 안의 *.jar 만 있으면 하이버네이트를 사용할 수 있습니다.

log4j 를 사용하기 위해선 slf4j-log4j12-1.5.10.jar  log4j-1.2.15.jar 가 필요합니다. (설정파일 log4j.properties !!!)

마지막으로 데이터베이스에 맞는 jdbc 드라이버가 필요합니다.





하이버네이트 기본 설정 파일인 hibernate.cfg.xml 을 작성해봅시다. 이클립스 플러그인으로 생성하겠습니다.

File - New - Other... - Hibernate - Hibernate Configuration File (cfg.xml) 선택 - Next




설정파일을 저장할 경로 지정




접속 정보를 입력합니다. - Finish

접속 정보는 http://antop.tistory.com/54 에 있는 샘플 DB 입니다.

※ Database dialect 를 DB 에 알맞게 잘 골라주세요.




src 경로 아래 hibernate.cfg.xml 파일이 생성 되었습니다.

※ 플러그인을 설치하면 하이버네이트 관련 xml 파일의 아이콘이 아래 그림과 같이 표시됩니다.



파일을 열어보면 기본적으로 데이터베이스 접속 정보가 설정되어있습니다.

코드 어시스트(Ctrl + Space)를 이용해(플러그인 있어야함) 다른 설정들도 할 수 있습니다.



하이버네이트 세션(JDBC의 Connection이라고 보면 됨)을 관리해주는 클래스를 사용하도록 합시다.

HibernateUtil 클래스입니다. 하이버네이트 공식 메뉴얼에서 구한 국민 세션 관리 유틸이죠 ㅎㅎ

package util;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
   public static final SessionFactory sessionFactory;

   static {
      try {
         // Create the SessionFactory from hibernate.cfg.xml
         sessionFactory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) {
         // Make sure you log the exception, as it might be swallowed
         System.err.println("Initial SessionFactory creation failed." + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }

   public static final ThreadLocal<Session> session = new ThreadLocal<Session>();

   public static Session getCurrentSession() throws HibernateException {
      Session s = session.get();
      // Open a new Session, if this thread has none yet
      if (s == null) {
         s = sessionFactory.openSession();
         // Store it in the ThreadLocal variable
         session.set(s);
      }
      return s;
   }

   public static void closeSession() throws HibernateException {
      Session s = (Session) session.get();
      if (s != null)
         s.close();
      session.set(null);
   }
}


※ 여기까지 하셨으면 하이버네이트를 사용할 최소한의 준비는 끝났습니다.



간단한 테스트 파일을 하나 만들어서 접속 테스트 해봅시다.

다른 이무 작동 없고 접속만 했다가 끊는 소스 입니다.

HibernateUtil 을 이용해서 접속합니다.

package app;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import util.HibernateUtil;

public class Test {
   
   public static void main(String[] args) {

      Session sess = null;
      Transaction tx = null;
  
      try {
         // 세션 열기
         sess = HibernateUtil.getCurrentSession();
         // 트랜잭션 시작
         tx = sess.beginTransaction();
         
         // processing..
   
         tx.commit(); // 커밋
      } catch (HibernateException e) {
         tx.rollback(); // 롤백
         e.printStackTrace();
      } finally {
         // 세션 닫기
         HibernateUtil.closeSession();
      }
    
   }
}

에러 안뿜어내고 로그 나오면 잘 된겁니다. ㄷㄷ;;




'하이버네이트' 카테고리의 다른 글

하이버 네이트에 대한 토비님의 글.  (0) 2012.06.30
하이버네이트  (0) 2012.06.30
Posted by 사라링

하이버네이트

2012. 6. 30. 13:08

Hibernate는 객체 모델링(Object Oriented Modeling)과 관계형 데이터 모델링(Relational Data Modeling) 사이의 불일치를 해결해 주는 ORM(Object Relation Mapping) 도구입니다.

Hiberbate Architecture


잘 사용하면 쿼리(sql) 하나 안쓰고 클래스의 set, get 같은것으로만 DB를 조종(?)할 수 있습니다.

하이버네이트를 이용하여 아주 간단한 CRUD1 만 해봅시다!

Java 1.6.0_13
Hibernate 3.3.2.GA
Apache Tomcat 6.0.18
HSQLDB 1.9.0 rc4
Eclipse 3.5 + Habernate Tools


- 하이버네이트 라이브러리와 log4j 사용을 위한 properties 파일을 세팅합니다.(아래 war 파일에서 확인해주세요)


- 하이버네이트 실행에 관련된 속성 정보를 가지고 있는 hibernate.cfg.xml 파일을 만듭니다.




- hibernate.cfg.xml 파일을 저장할 위치를 설정합니다. (기본 src)



- Database 정보를 입력합니다.



- hibernate.cfg.xml 파일을 열어서 몇가지를 더 추가해줍니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
   "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
      <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="hibernate.connection.url">jdbc:hsqldb:hsql/antop</property>
      <property name="hibernate.connection.username">sa</property>
      <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>

      <!-- JDBC connection pool (use the built-in) -->
      <property name="connection.pool_size">1</property>

      <!-- For a HSQL 1.8 in-memory database, this is required -->
      <property name="connection.shutdown">true</property>
        
      <!-- Drop and re-create the database schema on startup -->
      <property name="hbm2ddl.auto">create</property>

      <!-- Echo all executed SQL to stdout -->
      <property name="show_sql">true</property>
  
      <!-- Mapping -->

   </session-factory>
</hibernate-configuration>

show_sql 프로퍼티를 true로 하면 콘솔에서 쿼리를 확인할 수 있습니다.
hbm2ddl.auto 프로퍼티는 hbm.xml 이 바뀌면 디비 테이블을 드랍시키고 다시 생성하니 주의하세요!

- 간단한 고객테이블(customer)를 매핑시켜보겠습니다. (각 컬럼의 속성은 다를겁니다... MySQL 툴로 디자인한거라...)



- Customer 클래스를 작성합니다.
package com.tistory.antop;

public class Customer {
   private int seq;
   private String id;
   private String password;
   private String name;

   public Customer() { }

   public int getSeq() {
      return seq;
   }

   // 자동으로 생성되는 번호이므로 set 금지
   private void setSeq(int seq) {
      this.seq = seq;
   }
   // getter, setter, toString()
}


customer 테이블의 seq 칼럼은 자동증가이므로 클래스에서 setter를 private으로 선언한 것을 볼 수 있습니다. +_+/


- Customer 클래스에 대해 Mapping XML 파일을 작성합니다.

해당 클래스파일(.java)에서 마우스 오른쪽버튼 클릭 → New → Other...




이렇게 파일을 만들면 쵸큼 더 쉽게 작성할 수 있습니다.

Customer.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 package="com.tistory.antop">
   <class name="Customer" table="customer">
      <!-- 기본키가 되는 필드 -->
      <id name="seq" column="SEQ">
         <!-- 자동 증가 -->
         <generator class="increment" />
      </id>
      <property name="id" column="ID" />
      <property name="password" column="PWD" />
      <property name="name" column="NAME" />
   </class>
</hibernate-mapping>

각 태그에 대한 성명은 여기를 봐주세요.


- 마지막으로 hibernate.cfg.xml 에다가 Customer.hbm.xml을 추가해줘야합니다.
...
<hibernate-configuration>
   ...

      <!-- Mapping -->
      <mapping resource="com/tistory/antop/Customer.hbm.xml"/>
  
   </session-factory>
</hibernate-configuration>


- 간단하게 customer에 관한 예제를 만들어보았습니다. 배보다 배꼽이 더 크군염 ㅠ_ㅠ



테스트는 용자만 할 수 있습니다.! +_+/




참조 사이트
http://docs.jboss.org/hibernate/stable/core/reference/en/html/
http://dev.anyframejava.org/anyframe/doc/core/3.1.0/corefw/guide/hibernate-introduction.html
http://javacan.tistory.com/entry/101


참조 문서

출처: http://cafe.naver.com/deve.cafe (문제가 된다면 삭제하겠습니다. ㅠ_ㅠ)

'하이버네이트' 카테고리의 다른 글

하이버 네이트에 대한 토비님의 글.  (0) 2012.06.30
하이버 네이트 시작 하기.  (0) 2012.06.30
Posted by 사라링

초보 자바 Web개발자들을 위한 로드맵[퍼온글]



OKJSP에 자주 가서 요즘 자바 개발자들이 어떻게 살아가나를 보는 편인데, 아주 많이 반복적으로 올라오는 질문이 "대체 뭘 공부해야 하나요? 프레임워크는 Spring을 해야 할까요? iBATIS를 해야 할까요?" 하는 식의 질문들이다(이 질문은 사실 말이 안된다. 왜 그런지 읽다보면 나온다).

Java는 웹 관련 프레임워크들이 너무 다양하고, Ruby나 Python 같은 경우에는 RubyOnRails나 Django 처럼 하나의 프레임워크 안에 기능별 프레임워크들도 모두 다 All in one 형태로 들어 있어서 혼란을 주지 않는 반면, Java는 각 영역별로 프레임워크가 모두 다르고, 또한 각 영역별로 존재하는 프레임워크들의 종류도 많아서 초보 개발자들에게 극심한 혼란을 주고 있다.

그래서 나름대로 Java Web 개발자들을 위한 학습 로드맵을 정리해 보았다.

1. Java 그 자체많은 웹 개발자들이 마치 JSP 코드를 짤 줄 알면 그걸로 Java 웹 개발을 할 줄아는 것이라 생각하고 Java 그 자체를 소홀히 하는 것을 본다.
말도 안되는 소리이다. Java를 모르고서 Java 웹 개발을 제대로 한다는 것은 어불 성설이다. Java 그 자체를 먼저 공부하라.

특히 Java 5 문법을 숙지하길 권한다. 이제 우리나라도 점차 Java 5가 대세가 되어 가고 있다. 대부분의 프레임워크들과 WAS(JSP와 서블릿을 구동하는 서버)도 모두 Java 5를 기준으로 바뀌었으며, JVM 자체도 버전이 높을 수록 성능이 더 좋다.

2. JSP와 Servlet 그리고 Model 1모델 1은, JSP 하나에 DB에 접속해서 쿼리를 날리는 등의 모든 업무적인 기능(Business Logic)을 넣고, 그 아래에 HTML 코드를 박아 넣는 식으로 개발하는 것을 의미한다.
아직도 많은 개발자들이 여기에 길들여져 있는데, 일단 JSP 자체에 대한 기본기를 익힌 뒤로는 재빨리 버려야 할 습관이다.

그리고 많은 개발자들이 Servlet을 무시하고 JSP만 하는 것을 보곤 하는데, Servlet에 대한 학습이 제대로 이뤄지지 않으면 더 나은 웹 개발이 곤란하다. Servlet에 대한 기초 개념을 확실히 잡길 권한다.

모델 1은 제가 알기로는 HTML과 로직을 모두 한 JSP에 넣는 방식이 아니라 jsp:beans를 이용하는 방식입니다. 모델 1에서도 여전히 비즈니스 로직과 UI는 분리할 수 있죠. thin controller, fat model에는 더 맞는 방식이라고도 할 수 있습니다. - 영록, 그리고 Servlets and JSP Pages Best Practices에서 Model 1 관련 부분 참조

 
모델 1은 JSP나 혹은 서블릿 하나가 요청에 대한 처리, 데이터 유효성 검사, 비즈니스 로직 처리, 응답 생성을 모두 다 책임지는 방식이다. 모델 1은 작고, 간단한 애플리케이션에서 개발을 쉽게하고자 할때 사용된다.

In Model 1, a request is made to a JSP or servlet and then that JSP or servlet handles all responsibilities for the request, including processing the request, validating data, handling the business logic, and generating a response. The Model 1 architecture is commonly used in smaller, simple task applications due to its ease of development. -
Wikipedia


3. Model 2 - 프레임워크의 등장JSP로 열심히 개발을 하다보니 프로젝트 규모도 커지기 시작하고, JSP 파일 크기도 수천줄에 달하는등 엄청나게 커진다.
그런데 이 JSP에다 두서없이 모든 기능을 다 때려 넣다보니 JSP마다 똑같은 기능들이 Copy&Paste로 들어가고, JSP 안에 들어 있는 Java 코드들에서 에러가 발생하면 찾아내서 디버깅 하는 일이 지옥같이 느껴지기 시작한다.

여기서 Model 2가 구원자로 등장한다.

Model 2는 말만 멋드러졌지 실제로는 간단한 개념이다.

JSP에서 수행하던 DB 쿼리 등의 작업을 Servlet에게 넘겨주고 JSP에서는 오로지 화면 출력만 담당하는 것이다.

Servlet에서 DB 쿼리등 화면 출력과는 상관없는 비지니스 로직을 일단 먼저 모두 수행하고, 그 결과를 request.setAttribute("key",결과객체);로 담은 다음 JSP 페이지로 포워딩(forward)을 하면 JSP에서는 request.getAttribute("key")로 그 객체를 받아서 화면에 뿌려주기만 한다.
이런 업무 수행단/화면 출력단의 철저한 역할 분리가 Model 2이다.

여기서 이러한 각 역할을 "MVC - Model View Controller" 라고 한다. 그래서 Model 2는 MVC와 동일한 의미로 사용하기 도 한다. MVC의 의미는 공부하면서 찾아보라.

이게 뭐가 좋냐고? 개발 기간이 좀 길어지고 프로젝트 규모가 쬐끔 커지고, 기존 프로젝트를 유지보수를 해보면 얼마나 좋은지 몸소 뼈져리게 느끼게 된다.

Model 2의 기능을 정형화해서 쉽게 구현하게 해주는 것이 MVC Framework들의 역할이다.
가장 유명한 Model 2 웹 프레임워크들은 다음과 같은 것들이 있다.

스트럿츠 1 - Struts 1
스트럿츠 2 - Struts 2
스프링 MVC - Spring MVC
* 기타 덜 유명한 Wicket, Stripes, JSF, Tapestry 등.

Struts 1은 MVC의 효시라고 할 수 있다. 우리에게 MVC라는 축복을 주기는하였으나, 나온지 오래된 만큼 낡은 개념들이 많이 녹아있고 쓸데 없이 복잡하고 배우기도 어려운 편이다.

오히려 Struts 2와 Spring MVC가 더 배우기 쉬울 것이며, 개발도 더 쉽다. 현재 추세는 Struts 2와 Spring MVC이다. 대형 포탈이나 SI 업체들도 Spring/Struts 2를 주로 채택하는 추세로 가고 있는 것으로 알고 있다.

둘 중 하나의 개념만 확실히 이해해도 다른 것을 배우는데 어려움이 별로 없으므로 그냥 둘중에 골라서 배우길 권한다. 나는 Spring을 선호한다.

그리고 MVC 프레임워크를 사용하기 시작하면서 View를 만드는 JSP에 대해서도 재조명이 시작된다. 기존에 Java 코드를 JSP에 직접 넣던 관행을 버리고 JSTL과 태그 라이브러리를 사용하거나 아예 JSP를 버리고 다른 템플릿 엔진으로 만들기도 한다. 이에 관해서는 맨 마지막에.

4. 퍼시스턴스 프레임워크 : JDBC 반복 작업에 짜증이 나기 시작하다.현대 웹 개발에서 가장 큰 역할을 차지하는 것은 뭐니뭐니해도 단연 Database 작업이다.
지금까지는 아마도 JDBC에서 DB 커넥션을 맺고, 쿼리를 날리고 그 결과 ResultSet을 JSP로 넘겨주어서 출력하는 식으로 했을 것이다.
이미 다들 알고 있겠지만 JDBC를 사용하면 똑같은 코드가 굉장히 많이 반복해서 나온다. 한마디로 "삽질"의 전형이 JDBC 작업이다.
이것을 깨달은 많은 개발자들이 조금 어정짱하게 반복작업을 해결해주는 Util 클래스들을 프로젝트별로 만들어서 사용하곤 한다.
하지만, 물론 이에 대해 정형화하고 깔끔하고 훨씬 더 사용하기 쉬게 만들려는 노력이 이미 수년에 걸쳐 이루어졌다.

이렇게 DB관련된 작업을 정형화한 것들을 Persistence Framework 라고 한다.

아이바티스 - iBATIS : SQL Mapper - JDBC보다 더 쉽게 배우고, 더 편하게 사용한다.
하이버네이트 - Hibernate : 객체지향을 객체지향답게, 개발 기간을 엄청나게 단축시켜주다.

퍼시스턴스 프레임워크의 양대 산맥은 iBATIS와 Hibernate이다. 이 둘 모두 우리나라에 책이 나와 있다.
iBATIS는 SQL Mapper의 한 종류이고, Hibernate는 ORM의 한 종류이다.

이 둘의 차이는 iBATIS는 개발자가 SQL 쿼리를 직접 작성한 것을 객체에 매핑시켜주는 것이고, ORM은 DB 스키마와 객체간의 관계를 설정파일로 만들면 자동으로 쿼리를 만들어주는 것이다.

자, 이 둘을 보면 미국에서는 Hibernate가 인기가 좋고, 우리나라에서는 iBATIS가 사실상 SI 업계를 평정했다.
그러니까, 일단은 우리나라에서는 iBATIS를 공부하면 된다고 보면 된다.

이렇게 말하니까 마치 이 둘이 경쟁자 같은데, 사실 이 둘은 경쟁 상대라기 보다는 보완해주는 역할을 한다. SI에서 처럼 DB 테이블이 정규화 되어 있지 않은 경우에는 Hibernate같은 ORM을 사용하면 프로젝트를 말아먹을 수 있다.

iBATIS는 테이블 정규화에 무관하게, 개발자가 작성한 SQL을 객체로 매핑하기 때문에 DB 스키마가 마구 꼬여 있는 상황에서도 유연하게 작동하고, 개발자가 직접 SQL 튜닝을 할 수 있다는 장점이다.

그리고 Hibernate는 배우기가 굉장히 어려운 프레임워크이고 튜닝이 매우 어렵다. Hibernate책을 보면 캐싱을 통해 성능을 향상시키라고 하지만 캐싱은 iBATIS도 못지않게 잘 지원한다. 하지만 일단 배우면, 그로인한 코딩 생산성이 iBATIS가 감히 넘볼 수 없을 정도록 급격히 향상된다.

Hibernate는 DB 정규화가 잘되어 있는 웹 포탈 업체나 패키지 소프트웨어 제작시에 강력히 권장할만 하다.

5. IoC와 DI - 객체의 생성주기와 의존성을 관리하고 싶어지다사실 내가 경험한 SI를 보면 4단계 까지만 가도 막장은 아닌 프로젝트라고 본다. 아직도 신규 프로젝트를 하면서도 Model 1에 JDBC로 코딩하는 것을 많이 보았기 때문이다.

앞서, MVC라는 형태로 웹 애플리케이션의 역할을 철저하게 분할해서 처리하라고 했었다.

이제 여기서 좀 더 역할을 분할하기 시작한다.

Database를 관장하는 코드(DAO)와 Database 처리 결과를 가지고 그외 비지니스 로직을 추가로 수행하는 코드(Service), 그리고 웹으로 들어온 요청을 받아서 비지니스 로직을 호출하고, 그 결과를 다시 웹(HTML 등)으로 내보내는 코드(Controller)로 분할을 하면 유지보수가 더 쉽고, DB가 Oracle에서 DB2 로 변경되는 식의 중대 변화가 있을 때도 DAO만 바꾸면 되는 식으로 변화에 대한 대처가 유연해 진다는 것을 깨닫기 시작한다.

이제는 각 역할별로 클래스를 분할하고 컨트롤러 객체는 서비스 객체에 서비스 객체는 DAO 객체에 의존해서 작동하도록 코드를 바꾸기 시작한다. 그리고 객체의 생성과 파괴 주기도 관리해야만 하게 된다. 객체를 하나만 생성하면 되는데 불필요하게 매번 new를 할 필요는 없으니까.

이렇게 객체의 생성/파괴 주기를 관리하고 객체간의 의존성을 관리해주는 프레임워크를 IoC 컨테이너라고 부른다.

1. Spring Framework
2. EJB 3.0

사실상 대세는 Spring Framework로 굳어졌다. EJB 3.0은 내가 안써봐서 뭐라 말은 못하겠다.

Spring MVC는 이 Spring Framework의 일부분이다.

Spring은 또한 AOP도 지원한다.

AOP 의 개념이 상당히 어려운 편이라서 개념 자체를 확실히 한마디로는 표현하지 못하겠다. 어쨌든 개발자들에게 가장 쉽게 다가오는 표현으로 하자면, AOP는 동일한 패턴으로 반복적으로 해야하는 일을 설정을 통해 자동으로 해주는 것이다.
이에 관한 가장 보편적인 예가 바로 트랜잭션이다.
지금까지는 아마도 비지니스 로직이 시작될 때 트랜잭션이 시작되고, 비지니스 로직이 끝날 때 트랜잭션을 종료하는 코드를 매번 작성해서 넣었을 것이다.
AOP를 사용하면, 비지니스 로직의 역할을 하는 메소드가 무엇인지 설정파일에 넣어주기만 하면 자동으로 메소드가 시작될 때 트랜잭션을 시작시키고, 메소드가 끝날 때 트랜잭션을 종료시켜준다. 물론 예외가 발생하면 트랜잭션을 rollback도 해준다. 따라서 Spring을 사용한 프로젝트에서는 트랜잭션 관련 코드를 볼 수 없을 것이다.

Spring 프레임워크는 기본적으로 IoC 컨테이너 역할을 하는 것이 핵심이다. 따라서 Spring을 사용한다고 해서 꼭 Spring MVC를 사용할 필요는 없다. Struts 2 + Spring + iBATIS 나 SpringMVC + Spring + Hibernate 등... 어떠한 조합이라도 가능하다.

6. 그 외◈ Template Engine : JSP 보다 더 간결하면서 강력한게 필요해!
   * JSP + JSTL : Sun이 지정한 산업표준이다. JSTL은 당연히 쓰고 있으리라 믿는다.
   * Freemarker : 가장 권장할 만하다.
   * Velocity : 굉장히 배우기 쉽다. JSTL보다 더 빨리 배워서 쓸 수 있다. 가독성도 좋다. 그러나 Freemarker 만큼 편하고 강력하지는 못하다.
많은 사람들이 Java 웹 개발을 그냥 "JSP 개발"이라고도 부르는데, MVC가 도입되고, Freemarker 같은 다른 템플릿 엔진을 사용하게 되면 더이상 JSP는 코빼기도 안보이게 된다. 그러므로.. JSP 개발이라는 말은 쓰지 않았으면 좋겠다.

◈ Layout Engine
   * Sitemesh : 헤더 푸터 처럼 동일 패턴이 반복되는 레이아웃을 관리해준다.

◈ XML 도우미 : W3C DOM은 너무 어렵고 난잡하다. 좀 더 편한 XML관련 개발을 원한다면..
   * JDOM : Java 표준으로 지정됐다고 한다.
   * DOM4J
둘 다 비슷하게 편한거 같다. 예전엔 JDOM을 썼었는데, 나 같은 경우 현재 프로젝트에서는 DOM4J를 사용한다. Hibernate가 DOM4J를 사용하기 때문에, 별도의 라이브러리 더 넣는게 귀찮아서.

◈ 단위 테스트
   * jUnit : 코드를 철저하게 테스트하자.

◈ 소스코드 버전관리
   * CVS
   * Subversion : 현재 대세는 Subversion
내가 최고 막장으로 꼽는 프로젝트는 아직도 FTP로 소스 관리하는 프로젝트이다. 이런 프로젝트에는 절대로 참여하지 않을 것이라고 굳게 맹세하고 또 맹세했다. --;
소스 코드 버전관리는 여러 개발자들이 동시에 개발할 때 소스코드를 저장하고 충돌을 관리해주며, 소스 변경 내역을 계속해서 추적해서 과거 소스로 언제든지 돌아갈 수 있도록 도와준다.
현재 대세는 Subversion이지만 CVS로도 버전관리의 이점을 충분히 만끽할 수 있다. 그리고.. 사실 CVS가 사용법을 익히기는 더 쉽다.

◈ 자동 빌드
   * Ant : Ant 면 만사 Ok!
   * Maven
아직도 javac 로 컴파일하고 있고, FTP로 파일 올려서 복사하고 있다면.. 이 모든일을 자동으로 명령 한방에 처리하도록 해야 실수도 적고, 퇴근도 일찍한다.
Ant로 빌드와 배포를 자동화 하자.

결론
내가 권하는 조합은
* SI 업체에서 일하는 경우 : Struts 2 혹은 SpringMVC + iBATIS + JSP/JSTL + 가능하다면 Spring Framework

* 웹 포털등과 같은 업계, 패키지 소프트웨어 제작 업체 : Struts 2 혹은 Spring MVC + Hibernate + Spring Framework + Freemarker + Sitemesh

Posted by 사라링


  • Framework의 종류와 구분
    사용자 삽입 이미지
  • 자주 사용되는 Framework

스프링(Spring)


J2EE기반의 웹 어플리케이션을 쉽게 하는 것을 목적으로 하고 있으면서 J2EE서비스에 종속되지 않으며, 계층화, 모듈화가 잘 되어 있는 유연한 프레임워크 이다.


스프링의 주요목적중 하나인 "기존의 잘 만들어진 솔루션들과 경쟁하지 않고, 이들과의 통합을 추진한다."는 점이 다른 프레임워크들과 유기적으로 잘 연동할 수 있을 것인가를 알 수 있게 한다.


스프링 프레임워크는 다른 프로젝트에서 개발된 컴포넌트를 어떻게 잘 조합하여 사용할 것인가에 대한 고민의 해답으로 제시된 IoC(제어역행화; Inversion of Control) 또는 연관성 삽입(Dependency Injection) 패턴이 스프링의 중심된 개념이다.


※ 참고사이트

- IoC, 연광성 삽입 패턴 관련 문서 http://martinfowler.com/articles/injection.html

- 스프링 프레임워크 http://www.springframework.org

- 메뉴얼 http://www.springframework.org/docs/reference/index.html

벨로시티(Velocity) 

자카르타 프로젝트에서 진행 중인 자바 기반의 템플릿 엔진.

템플릿으로부터 SQL, HTML, 자바 소스를 생성하는 등 사용할수 있는 용도가 다양하지만, JSP의 대안으로 웹 어플리케이션 개발에서 많이 사용된다.

스트럿츠는 JSP를 통해 구현된 뷰를 프리젠테이션의 기본으로 하고 있지만, 일부 개발자들은 벨로시티를 선호하고 있다.

JSP가 표준스펙을 제정한 표준 기술인데 비해 벨로시티는 독자적인 표준을 제성한 것이므로, 표준 기술의 적용을 선호하는 기업환경에서는 벨로시티가 JSP를 대치하기는 어려울 것이다.


※ 참고사이트

- 벨로시티 사이트 http://jakarta.apache.org/velocity/index.html

익스프레소(Expresso) 

익스프레소 프레임워크는 보안 기능, OR Mapping, 백그라운드 작업, 자체 테스트 기능, 로깅 등의 기능을 제공하는 데이터베이스 드리븐(Database-Driven) 어플리케이션 개발을 위한 프레임워크이다. 익스프레소는 스트럿츠의 컨트롤러의 지원을 활용하면서 스트럿츠에서는 지원하지 않는 모델 영역을 지원하도록 설꼐 되어 있다.


※ 참고사이트

- 익스프레소 http://www.jcorporate.com


웹워크(WebWork) 

웹워크는 XWork라고 부르는 커맨드 패턴 프레임워크 API를 활용한 웹 어플리케이션 프레임워크다. 스트럿츠보다 인터셉터(Interceptor), IoC(Inversion of Control) 등의 특징은 스트럿츠보다 강력하다고 할수 있다.


※ 참고사이트

- 웹워크 http://www.opensymphoney.com/webwork/

JSF(Java Server Faces) 

JSF는 자바 개발자에게 웹 기반의 사용자 인터페이스를 작성하기 위한 API와 태그 라이브러리를 제공한다. 스트럿츠 프레임워크와 같이 JSF는 자바빈즈 속성에 연결된 HTML폼 요소를 생성하는 JSP태그 집합을 가지고 있어, 두 프레임워크가 비슷해 보이지만 JSF는 자바 표준이기 때문에 보다 많은 개발 도구의 지원을 받게 될 것이며, 이미 많은 벤더들이 JSF를 지우너하겠다고 나서고 있다.

JSF가 그동안 정무했던 웹 애플리케이션의 프리젠테이션 로직을 위한 프레임워크라는 점에서 관심을 모으고 있으며 다른 프레임워크들도 JSF와 연동을 위한 방안을 내놓고 있다.


출처 - http://hojaelee.tistory.com/entry/Framework의-종류와-구분

Posted by 사라링

<style>


body {

 background: #8c92ac;

 background: -moz-linear-gradient(bottom, #8c92ac, #fff) no-repeat;

 background: -o-linear-gradient(bottom, rgb(140,146,172), rgb(255,255,255)) no-repeat;

 background: -webkit-gradient(linear, center bottom, center top, from(#8c92ac), to(#fff)) no-repeat;

}

</style>





Posted by 사라링


jquery selectbox(중요)  JQuery 

2012/05/04 11:29

복사http://blog.naver.com/crazymania/10138015840

jQuery로 선택된 값 읽기

$("#select_box option:selected").val();
$("select[name=selectbox]").val();

jQuery로 선택된 내용 읽기
$("#selectbox option:selected").text();

선택된 위치
var index = $("#test option").index($("#test option:selected")); 



// 셀렉트 박스 옵션에 추가(기존 옵션 뒤쪽으로 추가)

$("#myselect").append("<option value='1'>Apples</option>");
$("#myselect").append("<option value='2'>After Apples</option>");

// 옵션 시작 부분(맨 앞에) 추가
$("#myselect").prepend("<option value='0'>Before Apples</option>");

// 옵션값을 새롭게 정의
$("#myselect").html("<option value='1'>Some oranges</option><option value='2'>More Oranges</option><option value='3'>Even more oranges</option>");

// 옵션값의 인덱스 번호를 변경
$("#myselect option:eq(1)").replaceWith("<option value='2'>Some apples</option>");
$("#myselect option:eq(2)").replaceWith("<option value='3'>Some bananas</option>");

// 2번 인덱스의 값을 선택된 상태로 변경
$("#myselect option:eq(2)").attr("selected", "selected");

// 텍스트 내용으로 선택된 상태로 변경
$("#myselect").val("Some oranges").attr("selected", "selected");

// 선택된 옵션의 값을 변경
$("#myselect").val("2");

// index번호가 0인것을 제거
$("#myselect option:eq(0)").remove();

// 첫번째 옵션 엘리먼트를 제거
$("#myselect option:first").remove();

// 마지막 옵션 엘리먼트를 제거
$("#myselect option:last").remove();

// 선택된 텍스트 알림으로 보이기
alert($("#myselect option:selected").text());

// 선택된 값 알림으로 보이기
alert($("#myselect option:selected").val());

// 선택된 옵션의 인덱스 번호 보이기
alert($("#myselect option").index($("#myselect option:selected")));

// Alternative way to get the selected item
alert($("#myselect option:selected").prevAll().size());

// 0번 인덱스 다음으로 옵션을 추가
$("#myselect option:eq(0)").after("<option value='4'>Some pears</option>");

// 3번 인덱스 이전에 옵션을 추가
$("#myselect option:eq(3)").before("<option value='5'>Some apricots</option>");

// select 박스의 값이 변경되었을 때 알링으로 값과 텍스트 보이기
$("#myselect").change(function() {
alert($(this).val());
alert($(this).children("option:selected").text());
});

[출처] jquery selectbox(중요)|작성자 미친곰

'J-Query' 카테고리의 다른 글

jQuery.slide()  (0) 2012.07.10
body CSS 그라데이션 흰색 - > 블랙  (0) 2012.06.22
select 태그에서 선택된 option 값 알아보기  (1) 2012.06.15
Build CRUD Application with jQuery EasyUI  (0) 2012.06.14
슬라이드 시계  (0) 2012.06.13
Posted by 사라링

BLOG main image
.. by 사라링

카테고리

사라링님의 노트 (303)
JSP (32)
J-Query (41)
디자인패턴 (1)
JAVA (24)
스트러츠 (3)
안드로이드 (11)
오라클 (45)
우분투-오라클 (1)
이클립스메뉴얼 (6)
스프링3.0 (23)
자바스크립트 (11)
HTML5.0 (17)
정보처리기사 (1)
기타(컴퓨터 관련) (1)
문제점 해결 (3)
프로젝트 (2)
AJAX (4)
하이버네이트 (3)
트러스트폼 (11)
Jeus (2)
재무관리(회계) (5)
정규식 (5)
아이바티스 (8)
취미 (2)
소프트웨어 보안 관련모음 (0)
정보보안기사 (6)
C언어 베이직 및 프로그램 (3)
보안 관련 용어 정리 (2)
넥사크로 (6)
웹스퀘어_ (0)
Total :
Today : Yesterday :