네이티브 앱, 웹 앱, 하이브리드 앱 그리고 PhoneGap

모바일 개발자라면 어느 정도 알고 있는 개발 접근 방법일 것입니다.

 

각 방법의 장단점에 대해 간단히 정리 해 보겠습니다.

 

네이티브 앱


ios 나  android 같은 특정 플랫폼에서 작동하는 앱입니다.

 

네이티브 앱의 장점으로는 특정플랫폼이 탑재되어 있는 디바이스의 모든 기능을 활용이 가능하고 대부분의 UI 요소가 제공되어 뛰어난 성능을 나타낸다는 점입니다.

단점으로는 특정 플랫폼에서만 동작을 하기 때문에 크로스 플랫폼  디바이스 문제가 발생할 경우가 있고 여러 플랫폼에서 개발을 해야  경우 플랫폼 각각의 개발을 하므로 개발비용이 많이들어가는 점입니다.

 

웹 앱

 

웹앱 또는 모바일 앱이라고 불리며 브라우저를 통해 동작하는 앱입니다.

웹앱의 장점으로는 대부분 모든 브라우저에서   있으므로 다양한 플랫폼의 동시 지원이 가능하고 서버 기반 앱으로 빠른 업데이트가 가능합니다

단점으로는 디바이스에 접근이 제한적이고 속도가 느리다는 점입니다.

 

하이브리드 앱

 

하이브리드 앱의 경우 모바일 앱과 웹앱의 장점을 포함하고 있다는 것입니다.

네이티브 앱과 동일한 환경에서 브라우저를 통해 실행 되는 앱입니다.

하이브리드 앱의 장점은 네이티브의 단점으로 언급되었던 크로스 플랫폼 문제와 웹앱에서 언급되었던 디바이스 사용문제를 해결이 가능합니다.

 

현재의 추세는 하이브리드앱입니다네이티브앱의 장점과 웹앱의 장점을 적절히 이용할  있고 모바일에서 크로스 플랫폼이나 매쉬업에 대응   있는 대안이라고   있습니다.

 

여기서 하이브리드 앱을 개발하기 위해 나온 스마트폰 크로스 플랫폼이 PhoneGap입니다. 이외에도 Appspresso, Titanium Mobile등이 있습니다.

 

다음 글에서는 그중 가장 많이 사용되는 PhoneGap 환경 구축에 대해 정리하겠습니다.

자바스크립트DOM - 노드 다루기

문서에서 특정 태그 이름을 지닌 노드 찾기

- Document 객체의 getElementsByTagName()을 이용하면 전체 문서에서 매개변수 값의 엘리먼트를 찾을 수 

  있습니다.

var divs = window.document.getElementsByTagName("div");

alert("문서내의 div 엘리먼트 개수 : " + divs.length);


for (var i = 0; i < divs.length; i++) {

var div = divs.item(i);

div.style.border = "1px solid #ff0000";

}


특정노드의 자식노드에서 특정태그 이름을 지닌 노드 찾기  

- 문서 전체가 아닌 특정 노드의 자식 가운데 특정 태그 이름을 가진 엘리먼트를 찾고 싶은 경우 Document 객체의 

  메서드인 getElementsByTagName() 대신 Element 객체의 메서드인 getElementsByTagName()을 사용합니다.

var divs = window.document.getElementsByTagName("div");

var div2 = divs[2];

var div2Child = div2.getElementsByTagName("div");


for (var i = 0; i < div2Child.length; i++) {

div2Child[i].style.border = "4px solid #ff0000";

}


문서에서 특정클래스가 적용된 노드 찾기

- 태그 이름이 아닌 클래스 이름을 알고 있거나 이 클래스가 적용된 엘리먼트를 문서 전체에서 찾고 싶을 때 

   Document 객체의  getElementsByClassName

var contentData = window.document.getElementsByClassName("content_data");

for(var i = 0; i < contentData.length; i++) {

contentData[i].style.border = "4px solid #ff0000";

}


문서에서 특정 ID를 지닌 노드 찾기

- Document 객체에는 문서 전체에서 아이디(id) 값으로  특정 엘리먼트를 찾는 getElementById() 메서드를 

   제공합니다.

var header = window.document.getElementById("header");

header.style.border ="4px solid #ff0000";


자식 노드 찾기

- 자식 노드를 모두 구하고 싶을 때

- 특정 엘리먼트의 하위 노드인 자식 노드에 접근하고 싶을 때는 Node 객체의 프로퍼티인 childNodes를 

   사용하면 됩니다.

- 자식노드중 N번쨰 노드에 접근하고 싶을 때

- 하위 노드 가운데 N번째 요소에 접근하고 싶을 때는 var node = page.childNodes[N] 또는 

   node = page.childNodes.item(N) 과 같은 식으로 하면 됩니다.

- 첫번쨰 자식 노드에 바로 접근

- Node에는 firstChild 라는 프로퍼티가 있어서 이를 이용하면 자식 노드중 첫번째 자식 노드에 바로 접근할 수 있

  습니다.

-마지막 자식 노드에 바로 접근하고 싶을 때

- 마지막 자식 노드에도 lastChild 라는 프로퍼티가 있어서 이를 이용하면 바로 마지막 노드에 접근 할 수 있

   습니다.

var page = window.document.getElementById("sample_page");

var nodes = page.childNodes;

alert("#sample_page의 자식 노드 개수는? " + nodes.length);

for (var i = 0; i < nodes.length; i++) {

var node = nodes.item(i);

if (node.nodeType == 1)

node.style.border = "1px solid #ff0000";

}

var firstChild = page.firstChild;

firstChild.style.color = "#ff0000";

var lastChild = page.lastChild;

lastChild.stlye.color = "#ff0000";


부모 노드 찾기

- 특정 엘리먼트의 부모노드에 접근하고 싶을 때는 Node  객체의 기본 프로퍼티인 parentNode를 사용합니다.

var header = document.getElementById("header");

header.parentNode.style.border = "4px solid #ff0000";


형제 노드 찾기

- DOM에서는 이런 형제노드를 쉽게 찾을 수 있게 몇가지 유용한 프로퍼티를 제공합니다.

- Node 객체의 프로퍼티인 previousSibling와 nextSibling을  이용하면 앞뒤로 인접한 형제노드에 각각 접근

  할 수 있습니다.

var content = document.getElementById("content");

content.previousSibling.previousSibling.style.border = "4px solid #ff0000";

content.nextSibling.nextSibling.style.border = "4px solid #ff0000";


노드 생성 및 추가하기

- 노드를 생성하고 추가하는 방법은 세가지가 있습니다.

- Document.createElement() 메서드 사용

- HTMLElement.innerHTML 프로퍼티 사용

- Node.cloneNode() 메서드 사용

- 위 세가지 방법을 경우에 따라 적절하게 독립적으로 또는 서로 조합해서 사용하면 됩니다.

Document.createElement() 메서드를 사용하는 경우

- 첫번째 영역에 추가하기

1. 새로 생성할 노드를 추가할 위치의 기준이 되는 엘리먼트의 첫번째 자식노드를 찾습니다.

2. createElement() 메서드를 이용해 새로운 노드를 생성합니다.

3. 새롭게 생성한 텍스트를 추가하기 위해 createTextNode() 메서드를 이용해 텍스트 노드를  생성합니다.

4. 생성한 텍스트노드를 2번에서 생성한 자식 노드로 appendChild() 메서드를 이용해 추가합니다.

5. 끝으로 page.insertBefore(추가노드, 기준노드) 함수를 이용해 #sample_page 노드의 형제노드로 

    새로 생성된 노드를 추가합니다.

- 두번쨰 영역에 추가하기

첫번째와 같은 순서로 진행됩니다. 다만 새로 생성되는 노드가 많을 경우 자식노드를 모두 만들어 준 후 새로

생성되는 노드에 추가하는 구문이 들어갑니다.

- 세번째 영역에 추가하기

첫번째와 같은 순서로 진행됩니다. 새로 생성된 노드의 위치가 #sample_page 노드의 자식 노드로 추가되고

이를 위해 insertBefore() 메서드 대신 appendChild() 메서드를 사용합니다.

HTMLElement.innerHTML 프로퍼티를 사용하는 경우

- Element의 내부에 들어있는 모든 자식을 문자열로 담은 프로퍼티입니다.

innerHTML 프로퍼티 기능을 사용하면 새로 추가할 노드를 DOM 메서드를 이용해 일일이 생성하지 않고 문자

  열을 만들어 대입해주기만 하면 됩니다.

Node.cloneNode() 메서드를 사용하는 경우

- 생성하고 싶은 내용이 이미 생성되 있는 요소와 똑같거나 다소 비슷하다면 Node객체에서 제공하는 

   cloneNode() 메서드를 이용해 똑같은 노드를 복사해서 생성할 수 있습니다.


노드 삭제 하기

- 지우려는 노드를 찾은 다음 Node 객체의 메서드인 removeChild()를 호출하여 사용합니다.


노드 이동시키기

- 이미 생성된 노드를 특정 위치로 이동 시키려면 노드 생성 및 추가시 사용한 appendChild()insertBefore()를 

   그대로 사용하면 됩니다.(이미 존재하는 경우 기존의 위치에서 삭제한 후 추가 )


텍스트 노드 생성 및 추가하기 

- 텍스트 노드는 일반 엘리먼트 노드와 성격이 달라서 생성하는 방법이 조금 다릅니다.

- 택스트 노드를 생성하려면 생성하는 기능인 팩토리 메서드로 가득찬 Document 객체의 createTextNode() 메서드

   드를 이용하면 됩니다.


텍스트 노드 내용 변경하기 

- 바꾸려는 텍스트 노드를 찾아 Node 객체의 프로퍼티인 nodeValue에 원하는 값을 대입하면 변경할 수 있습니다.



출처 : jQuery를 이용한 인터렉티브 웹콘텐츠 제작

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

자바스크립트 DOM  (0) 2014.01.22
JSTL의 코어라이브러리 - 2  (0) 2014.01.22
JSTL의 코어라이브러리 - 1  (0) 2014.01.22

자바스크립트 DOM

DOM 이란?

- 웹 페이지 자체를 손수 편집하지 않고 웹 브라우저에 표시된 상태에서 웹 페이지의 특정부분을 동적으로 지우거나 

   다른 내용으로 변경하거나, 또는 글자 색과 글자크기를 바꾸고 싶을때 DOM 기능을 활용하게 됩니다.


핵심 DOM 객체소개

Node 객체

- DOM 객체 가운데 가장 최상위 객체이자 노드를 조작하기 위한 가장 기본적인 프로퍼티와 메소드가 정의돼 있

  는 Node 인터페이스를 구현한 객체입니다.

- Node 객체에서 제공하는 기능을 이용하면 노드타입을 파악하거나 부모, 형제, 그리고 자식노드를 알아내서 접

  근하거나, 자식노드를 추가, 삭제, 교체할 수 있습니다.


Element 객체

- Node 객체의 자식이므로 Node 객체가 가지고 있는 기능을 모두 사용할 수 있고, HTML과XML의 태그 노드를 

  조작하기 위한 기본적인 프로퍼티와 메서드가 포함돼 있습니다.

- 태그 기능이 담긴 프로퍼티와 속성을 알아내고 설정하는 기능과 이벤트를 추가하거나 삭제하거나 발생시키는

  기능을 합니다.


HTMLElement 객체

- Element 객체의 기능 외에도 오직 HTML 페이지의 p, div 태그와 같은 HTML 태그에서만 쓸 수있는  속성과 기

  기능이 포함돼 있습니다.

- HTMLDivElement, HTMLImageElement, HTMLBodyElement와 같은 객체의 부모객체이기도 합니다.


Document 객체

- HTML문서와 XML문서의 루트 객체로서 앨리먼트 노드와 이벤트. 속성노드, 텍스트 노드, 주석 노드까지 생성

  하는 팩토리 기능 

- id, className, tagName으로 특정노드를 찾는 기능

- 이벤트를 발생시키고 등록시키는 이벤트 등록 모델 기능


HTMLDocument 객체

- HTML 문서 전용 Document 객체입니다. 이에 따라 body와 같은 HTML 문서전용 프로퍼티와 메서드가 

   포함돼 있습니다.

- HTML 페이지 로딩 후 파싱단계에서 만들어진 html, head, body 객체를 비롯해  페이지에 작성된 태그와

   일대일로 매칭되는 모든  Node 객체를 가지고 있는 객체입니다.


Text 객체

- Node 객체의 하위 객체이며 텍스트 노드를 조작하는 기능이 포함돼 있습니다.

- 텍스트노드는 일반적으로 엘리먼트 노드의 자식노드로 존재하므로 Text 객체 역시 Element 객체의 자식 객체

   로 존재합니다.


Attribute 객체

- Node 객체의 하위 객체이며  태그의 속성 정보를 조작하는 기본 프로퍼티와 메서드가 포함돼 있습니다.

- Attribute 객체에 접근하려면 먼저 Element 객체의 프로퍼티 가운데 attribute가 어떤 객체의 인스턴스인지

   알아야 합니다.

- attributes 의 프로퍼티 객체타입은 NamedNodeMap 객체의 인스턴스로서  일종의 NodeList와 같은 

   컬렉션 객체입니다.

- 태그에 설정돼 있는 속성과 일대일 매칭되는 Attribute 객체의 인스턴스를 요소로 가지고 있습니다.

JSTL의 코어라이브러리 - 2

<c:forTokens>

- for문과 java.util.StringTokennizer클래스의 기능을 합친 것과 같은 기능을 제공하는 커스텀액션

- 문자열에 포함된 토큰을 분리해서 각각의 토큰에 대해 반복처리를 수행하도록 합니다.

<c:forTokens var="pet"  items ="햄스터 이구아나" delims =" " >

${pet} <BR>

</c:forTokens>

- var : 토큰을 대입할 변수 ,  items : 토큰을 포함한 문자열 , delims : 구획문자


<c:catch>

- try문과 비슷한 역할을 하는 커스텀액션

- <c:catch> 커스텀액션은 try에만 해당되므로 catch 블록은 별도록 구현해야합니다.

<c:catch var="e">

<% int result = num / num2>

나눗셈의 결과는? <% = result %>

</c:catch>

<c:if test="${e != null}" >

에러메세지 : ${e.message} 

</c:if>


<c:redirect>

- sendRedirect 메서드와 동일한 방법으로 작동하는 커스텀액션

- jsp 페이지가 아닌 웹자원과 다른 웹서버에 있는 웹자원도 호출 할 수 있습니다.

- <c:redirect>의 시작과 끝 태그사이에 <c:param>을 이용해 데이터를 넘겨줄 수 있습니다.

<c:redirect url ="www.test.com/test.jsp" >

<c:param name="test1"  value="5" />

<c:param name="test2"  value="6" />

</c:redirect>


<c:import>

- 현재의 jsp페이지에서 다른 jsp 페이지의 결과를 포함시키는 커스텀액션

- <c:redirect>와 사용법은 유사합니다.


<c:url>

- <c:set> 커스텀액션과 마찬가지로 변수의 선언에 사용되는 액션

- URL을 저장하기 위한 변수의 선언에 사용됩니다.

- <c;redirect>와 사용법은 유사합니다.


<c:out>

- 데이터를 출력할 때 사용하는 커스텀액션

- 웹브라우저에 의해 특수문자로 해석될 가능성이 있는 <,  >,  &, ', " 문자를 포함한 데이터는 이 액션을 

   이용하는 것이 좋습니다.

- 특수문자를 자동으로 이스케이프 시퀀스로 바꿔주는 기능이 있습니다.

- 이스케이프 시퀀스로 변환하기를 원치 않을 경우 escapeXml 애트리뷰트를 추가하고 값을 true로 저장하면 됩니다.

- 출력할 데이터의 디폴트값을 지정할 수 도 있습니다.


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

자바스크립트DOM - 노드 다루기  (0) 2014.01.22
자바스크립트 DOM  (0) 2014.01.22
JSTL의 코어라이브러리 - 1  (0) 2014.01.22

JSTL의 코어라이브러리 - 1

<c:set>

- 변수를 선언하고 그 변수에 초기값을 대응하는 기능 

- 선언한 변수는 익스프레션 언어의 EL식 안에서 사용이 가능합니다.(스크립팅 요소안에서는 사용불가)

 올바른 예

 잘못된 예


 <c:set var="num" value = "100" />

 ..........

 ${num}


 <c:set var = "num" value ="100" /> 

 ...........

 <%= num %>

- <c:set> 액션을 이용해서 선언한 변수의 값을 또 다른 변수의 초기값으로 사용가능

<c:set var = "num1"  value = "${num1+num2} />

- <c:set> 태그에 scope라는 애트리뷰트에 저장할 영역을 지정하면 저장할 데이터영역 명시 가능

<c:set var ="PRICE" value ="15000" scope="request">


<c:remove>

- <c:set>액션을 이용한 변수는 데이터영역에 저장되기 때문에 인위적으로 삭제해야 합니다.

- <c:remove> 액션은 다음과 같이 사용이 가능합니다.

1. 데이터 영역에 저장되어 있는 해당 이름의 모든 변수를 삭제하는 경우

    <c:remove var ="code" />

2. 특정영역에 저장되어 있는 해당 이름의 변수를 삭제하는 경우(scope 테그에 명시)

    <c:remove var ="code"  scope="request" />


<c:if> 

- 자바의 if문과 비슷한 역할을 하는 커스텀 액션

- 조건식은 변수 이름의 애트리뷰트값으로 지정하해야 합니다.

  <c:if test="${num1 > num2}" >

num1 이 더 크다 

 </c:if>


<c:choose>

- 자바문법의 switch문과 동일한 기능을 하는 커스텀 액션

- <c:when> 과 <c:otherwise> 라는 커스텀액션을 함께 사용합니다.

 <c:choose>

     <c:when test ="${num == 0}">

num = 0; <BR>

    <c:when test ="${num == 1}">

num = 1; <BR>

    <c:otherwise>

</c:choose>


<c:forEach>

- for문에 해당하는 기능을 제공하는 커스텀액션

<c:forEach begin ="1" end ="10">

야호 <BR>

</c:forEach>

- 반복문에 카운트 변수를 사용해야 하는 경우 (var에 카운트 변수의 이름을 지정)

<c:forEach var ="cnt" begin = "1" end = "10">

${cnt} <BR>

</c:forEach>

- 반복문에 증가치를 변경 해야 경우 (step에 증가치를 지정)

<c:forEach var ="cnt" begin = "1" end = "10" step ="2">

${cnt} <BR>

</c:forEach>


- 배열의 항목을 순서대로 출력하는 경우 (item에 배열이름을 지정하고 var에 배열의 항목을 담는 변수이름 지정)

<c:forEach var="str"  items="${arr}">

${str} <BR>

</c:forEach>



- 참고 자료 : 뇌를 자극하는 JSP & Servlet

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

자바스크립트DOM - 노드 다루기  (0) 2014.01.22
자바스크립트 DOM  (0) 2014.01.22
JSTL의 코어라이브러리 - 2  (0) 2014.01.22

[ MyBatis3 ] 동적 SQL

- MyBatis 의 가장 강력한 기능 중 하나는 동적 SQL 기능이다.

- MyBatis 다른 요소의 사용을 최대한 제거하기 위해 OGNL기반의 표현식을 가져왔다.

    • if
    • choose (when, otherwise)
    • trim (where, set)
    • foreach

* if

<select id = "aaaa" parameterType = "Blog" resultType = "Blog">

SELECT * FROM BLOG

WHERE state = "bbbb"

<if test="title != null">

AND title like #{title}

</if>

</select>


- 이 구문은 선택적으로 문자열 검색 기능을 제공한다.

- title 값이 없다면 모든 active상태의 Blog가 리턴될 것이고 title 값이 있다면 그 값과 비슷한 데이터를 찾게 될 것이다.

* choose, when , otherwise

- 종종 모든 조건을 원하는 대신 한가지 경우만 만족하는 경우를 원할 수 있다, 자바에서 swith문과 유사하다.

<select id = "aaa" parameterType ="Blog" resultType = "Blog">

SELECT * FROM BLOG WHERE state = 'ACTIVE'

<choose >

<when test = "title != null">

AND title like #{title}

</when>

<when test ="author != null and author.name != null">

AND author_name like #{author.name}

</when>

<otherwise>

AND featured = 1

</otherwise>

</choose>

</select>


- title 만으로 검색하고 author 가 있으면 그값으로 검색하고 둘다 제공하기 않는다면 featured 상태의 blog가 리턴된다.


* trim, where, set


위 예제에서 어떤 조건에도 해당하지 않는다면

SELECT * FROM BLOG

WHERE

처럼 나온것이고 sql문이 꼬이게 될 것이다.

<select id=”findActiveBlogLike”parameterType=”Blog” resultType=”Blog”>

SELECT * FROM BLOG

<where>

<if test=”state != null”>

state = #{state}

</if>

<if test=”title != null”>

AND title like #{title}

</if>

<if test=”author != null and author.name != null”>

AND title like #{author.name}

</if>

</where>

</select>

>> where 요소는 태그에 의해 컨텐츠가 리턴되면 필요할 경우 "WHERE" 을 추가한다.

만약 컨텐츠가 "AND" 나 "OR"로 시작한다면 삭제해버린다.


만약 where 요소가 기대처럼 동작을 하지 않는다면, trim 요소를 사용자 정의할 수 있다.


<trim prefix ="WHERE" prefixOverrides = "AND | OR">

</trim>

>> override 속성은 오버라이드하는 텍스트의 목록을 제한한다.

결과는 override 속성에 명시된 것들을 지우고 with 속성에 명시된 것을 추가한다.


<update id ="updateAuthorIfNecessary" parameterType="domain.blog.Author">

update Author

<set>

<if test="username != null">username=#{username},</if>

<if test="password != null">password=#{password},</if>

<if test="bio != null">bio=#{bio}</if>

</set>

where id = #{id}

</update>


>> 여기서 set 요소는 동적으로 SET 키워드를 붙이고 필요없는 콤마를 제거한다.

<trim prefix="SET" suffixOverrides=",">

</trim>


* foreach


- 동적 SQL에서 공통적으로 필요한 것으 collection에 대한 반복처리를 하는 것이다. 종종 IN 조건을 사용하게 된다.

- foreach 요소는 매우 강력하고 collection을 명시하는 것을 허용한다.

- 요소내부에서 사용할 수 있는 item, index 두가지 변수를 선언한다.


- 열고 닫는 문자열로 명시할 수 있고 반복간에 둘 수 있는 구분자도 추가할 수 있다.

[ MyBatis3 ] SQL Map XML 파일(resultMap-3)

* collection

<collection property="posts" ofType="domain.blog.Post">

<id property = "id" column="post_id" />

<result property ="subject" column="post_subject" />

</collection>


- collection 요소는 관계를 파악하기 위해 작동한다.

- ofType : 자바빈 프로퍼티 타입과 collection 의 타입을 구분하기 위해 필요하다.

>> associations과 collections에서 내포의 단계혹은 조합에는 제한이 없다.


* discriminator


<discriminator javaType="int" column="draft">

<case vaule="1" resultType="DraftPost" />

</discriminator>


- 종종 하나의 데이터베이스 쿼리는 많고 다양한 데이터 타입의 결과를 리턴한다.

이 요소는 클래스상속관계를 포함하여 이러한 사항을 위해 고려됨

- discriminator 정의는 column 과 javaType 속성을 명시한다.

column은 MyBatis로 하여금 비교할 값을 찾을 것이다. javaType은 동일성 테스트와 같은 것을 실행하기 위해 필요

- 각각의 레코드를 가져와 draft값과 비교한다. 만약 비교값과 같은 경우가 생기면 명시된 resultMap을 사용 없다면 무시된다.

[ MyBatis3 ] SQL Map XML 파일(resultMap-2)

* id , result

<id property ="id" column="post_id" />

<result property="subject" column="post_subject" />


>> 결과 매핑의 기본적인 형태, id와 result 모두 한개의 칼럼을 한개의 프로퍼티나 간단한 데이터 타입의 필드에 매핑한다.


* constructor


<constructor>

<idArg column="id" javaType="int"/>

<arg column="username" javaType="String" />

</constructor>


- 프로퍼티가 데이터전송객체(DTO) 타입 클래스로 작동한다.

- MyBatis는 private 프로퍼티와 private 자바빈 프로퍼티를 지원하지만 많은 사람들은 생성자 주입을 선호한다.


* association

<association property="author" column="blog_author_id" javaType='Author">

<id property="id" column="author_id" />

<result property="username" column="author_username"/>

</association>


- association 요소는 "has-one" 타입의 관계를 이룬다.

- association 매핑은 다른 결과와 작동한다. 값을 가져오기 위해 대상 프로퍼티를 명시한다.

- MyBatis는 관계를 정의하는 두가지 방법을 제공한다.

  • 내포된(Nested) Select : 복잡한 타입을 리턴하는 다른 매핑된 SQL구문을 실행하는 방법
  • 내포된(Nested) Result : 조인된 결과물을 반복적으로 사용하여 내포된 결과매핑을 사용하는 방법

- 관계를 위한 내포된 Select

<resultMap id ="blogResult" type="Blog">

<association property ="author" column ="blog_author_id" javaType = "Author" select="selectAuthor" />

</resultMap>


<select id="selectBlog" parameterType ="int" resultMap="blogResult">

SELECT * FROM ……..

</select>


<select id= "selectAuthor: parameterType="int" resultType="Author">

SELECT * FROM …….

</select>


>> 두개의 select 구문중 하나는 Blog를 로드하고 다른하나는 Author를 로드한다.

Blog의 resultMap은 author 프로퍼티를 로드하기 위해 "selectAuthor" 구문을 사용한다.

다른 프로퍼티들은 칼럼과 프로퍼티명에 일치하는 것들로 자동으로 로드 될 것이다.


이 방법은 간단한 반면, 큰 데이터나 목록에는 제대로 작동하지 않을 것이다.

이 방법은 "N +1 Select문제"으로 알려진 문제점을 가진다.

- 레코드의 목록을 가져오기 위해 하나의 sql구문을 실행한다.("+1"에 해당)

- 리턴된 레코드별로, 각각의 상세데이터를 로드하기 위해 select구문을 실행한다.("N"에 해당)


- 관계를 위한 내포된 Result


<select id ="selectBlog" parameterType="int" resultMap="blogResult">

select

B.id as blog_id,

B.title as blog_title,

B.author_id as blog_author_id.

A.id as author_id,

A.username as author_username,

A.bio as author_bio

from Blog B left outer join Author A on B.author_id = A.id

where B.id = #{id}

</select>


<resultMap id="blogResult" type="Blog">

<id property ="blog_id" column="id" />

<result property="title" column="blog_title" />

<association property ="author" column="blog_author_id" javaType ="Author" resultMap="authorResult" />

</resultMap>


<resultMap id="authorResult" type="Author">

<id property="id" column="author_id" />

<result property="username" column="author_user_name" />

<result property="bio" author_id = "author_bio" />

</resultMap>


>> id 요소는 내포된 결과 매핑에서 매우 중요한 역할을 담당한다.

결과중 유일한 것을 찾아내기 위한 한개 이상의 프로퍼티를 명시해야 한다.

가능하면 결과중 유일한 것을 찾아낼수 있는 프로퍼티를 선택해야 한다

[ MyBatis3 ] SQL Map XML 파일(resultMap)

# resultMap

- MyBatis에서 가장 중요하고 강력한 요소이다. ResultSet에서 데이터를 가져올 때 작성되는 JDBC코드를 대부분 줄여주는 역할을 담당한다.

- 모든 칼럼의 값이 결과가 되는 간단한 구문에서는 HashMap에서 키 형태로 자동으로 매핑된다, 하지만 대부분의 경우 HashMap은 매우 좋은 도메인 모델이 되지는 못한다.

- 그래서 대부분 도메인모델로는 자바빈이나 POJO를 사용할 것이다.

- TypeAliases가 편리한 기능임을 기억해두는게 좋다. TypeAliases를 사용하면 타이핑 수를 줄일 수 있다.
<typeAlias type="com.someapp.model.User" alias="User"/>

<select id ="selectUsers" parameterType="int" resultType="User">
</select>

- 칼럼명이 프로퍼티명과 다르다면
  1. SQL 구문에 별칭을 지정

    <select id ="selectUsers" parameterType ="int" resultType ="User">
    select
    user_id as "id"
    user_name as "userName"
    from some_table
    </select>


  2. 명시적인 resultMap을 선언하는 방법

    <resultMap id ="userResultMap" type="User">
    <id property ="id" column="user_id" />
    <result property ="username" column="username" />
    </resultMap>

    <select id = "selectUsers" parameterType ="int" resultType ="userResultMap">
    select user_id, user_name
    from some_table
    </select>

- resultMap요소는 많은 하위 요소를 가진다. 다음은 resultMap요소의 개념적인 뷰이다.

  • constructor - 인스턴스화 되는 클래스의 생성자에 결과를 삽입하기 위해 사용
  • id - ID 결과, ID와 같은 결과는 전반적으로 성능을 향상시킴
  • result - 필드나 자바빈 프로퍼티에 삽입되는 일반적인 결과
  • association - 복잡한 타입의 연관관계; 많은 결과는 타입으로 나타난다.
  • collection - 복잡한 타입의 컬렉션
  • discriminator - 사용할 resultMap을 판단하기 위한 결과값을 사용

> 가장 좋은 형태는 매번 resultMap을 추가해서 빌드한다.

[ MyBatis3 ] SQL Map XML 파일(select, insert, update, delete, sql)

MyBatis의 가장 큰 장점은 매핑된 구문이다. 동일한 기능의 JDBC코드와 비교하면 아마도 95%이상 코드수가 감소하기도 한다.


# Select

- select 구문은 가장 많이 쓰는 요소이다. MyBatis는 데이터를 조회하고 그 결과를 매핑하는데 집중하고 있다.
  • MyBatis
<select id ="selectPerson" parameterType = "int" resultType = "hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

  • JDBC
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?";
PreparedStatement ps = comm.prepareStatment(selectPerson);
ps.setInt(1,id);

# insert, update, delete

* insert
<insert id ="insertAuthor" parameterType="domain.blog.Author">
insert into Author (id, username, password, email, bio)
values (#{id}, #{username}, #{password}, #{email}, #{bio})
</insert>
* update
<update id = "updateAuthor" parameterType="domain.blog.Author">
update Author set
username = #{username}
password =#{password}
email = #{email}
bio = #{bio}
where id = #{id}
</update>
* delete
<delete id = "deleteAuthor" parameterType="int">
delete from Author where id = #{id}
</delete>

* insert 자동생성키 설정(Autoincrement)

- 사용하는 데이터베이스가 자동생성키를 지원하는 경우
<insert id ="insertAuthor" parameterType="domain.blog.Author"
useGeneratedKeys = "true" keyProperty ="id">

- 자동생성키를 지원하지 않는 경우 (랜덤 ID 생성 -> 자동생성키와 비슷한 효과를 나타냄)
<insert id ="insertAuthor" parameterType="domain.blog.Author">
<selectKey keyProperty = "id" resultType ="int' order = "BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>

# Sql

- 이 요소는 다른 구문에서 재사용 가능한 SQL구문을 정의할 때 사용

<sql id = "userColumns">id, username, password</sql>

<select id = "selectUsers" parameterType ="int' resultType ="hashmap">
select <include refid = "userColumns"/>
from some_table
where id = #{id}
</select>


※ 출처 : Mybatis-3-User-Guide.pdf