반응형

목차

  1. id로 특정 요소 가져오기[1]
  2. 폼 컨트롤러의 값을 가져오기[2]
  3. 스타일 변경하기[3]
  4. html 내용 변경하기[4]
  5. Ajax Request의 파라미터 셋팅하기[5]
  6. Ajax Request 생성하기[6]
  7. Event 추가하기[7]
  8. 각 요소별로 함수 실행하기[8]
  9. 이벤트 핸들링[9]
  10. 호출 체이닝[10]
  11. 테이블 형태의 html 내용변경하기[11]
  12. key 이벤트 감지하기[12]
  13. 이벤트 가로채기[13]
  14. insert() 메소드 제대로 사용하기[14]
  15. form 다루기[15]

id로 특정 요소 가져오기[#1]

이전의 방법
document.getElementById('foo')

추천하는 방법

$('foo')

폼 컨트롤러의 값을 가져오기[#2]

이전의 방법
var woot = document.getElementById('bar').value
var woot = $('bar').value

추천하는 방법

var woot = $F('bar')

스타일 변경하기[#3]

이전의 방법
$('footer').style.height = '100px';
$('footer').style.background = '#ffc';  

추천하는 방법

$('footer').setStyle({
  height: '100px',
  background: '#ffc'
})

html 내용 변경하기[#4]

이전의 방법
$('coolestWidgetEver').innerHTML = 'some nifty content'

추천하는 방법

$('coolestWidgetEver').update('some nifty content')

Ajax Request의 파라미터 셋팅하기[#5]

이전의 방법
new Ajax.Request('ninja.php?weapon1=foo&weapon2=bar')

추천하는 방법

new Ajax.Request('ninja.php', {
  parameters: {
    weapon1: 'foo',
    weapon2: 'bar'
  }
})

Ajax Request 생성하기[#6]

이전의 방법
new Ajax.Request('blah.php', {
  method: 'POST',
  asynchronous: true,
  contentType: 'application/x-www-form-urlencoded',
  encoding: 'UTF-8',
})

추천하는 방법

new Ajax.Request('blah.php')

여기서 위 방법이 잘못된게 아니다. 하지만 사용된 값이 모두 디폴트 값이기 때문에 굳이 표기할 필요가 없다는 것이다.

Event 추가하기[#7]

이전의 방법
Event.observe('myContainer', 'click', doSomeMagic)

추천하는 방법

$('myContainer').observe('click', doSomeMagic)

뒤의 방법이 좀더 객체 지향적이고 다른 이벤트를 추가하기가 용이하다.

각 요소별로 함수 실행하기[#8]

이전의 방법
$$('div.hidden').each(function(el){
  el.show();
})

추천하는 방법

$$('div.hidden').invoke('show')

같은 기능을 하기 위해 첫번째 방법처럼 지나치게 많은 함수를 사용할 필요가 없다.

이벤트 핸들링[#9]

이전의 방법
$$('div.collapsed').each(function(el){
  el.observe('click', expand);
})

추천하는 방법

$$('div.collapsed').invoke('observe', 'click', expand)

호출 체이닝[#10]

이전의 방법
$$('input.date').invoke('observe', 'focus', onFocus);
$$('input.date').invoke('observe', 'blur', onBlur);

추천하는 방법

$$('input.date')
  .invoke('observe', 'focus', onFocus)
    .invoke('observe', 'blur', onBlur)

위 두가지 모두 같은 기능을 실행하게 되지만 앞의 예제처럼 $$() 함수를 두번이나 호출해서 처리할 필요가 없다. 아래의 경우처럼 체이닝(chaining nirvana)를 사용하면 된다.

테이블 형태의 html 내용변경하기[#11]

이전의 방법
$('productTable').innerHTML = 
  $('productTable').innerHTML + 
  '<tr><td>' + productId + ' '
  + productName + '</td></tr><tr><td>'
  + productId + ' ' + productPrice + 
  '</td></tr>'

추천하는 방법

var rowTemplate = new Template('<tr><td>#{id} #{name}</td></tr><tr><td>#{id} #{price}</td></tr>');
$('productTable').insert(
  rowTemplate.evaluate({
    id: productId,
    name: productName,
    price: productPrice
  }))
)

위 두가지 모두 같은 기능을 실행하게 되지만 앞의 예제처럼 $$() 함수를 두번이나 호출해서 처리할 필요가 없다. 아래의 경우처럼 체이닝(chaining nirvana)를 사용하면 된다.

key 이벤트 감지하기[#12]

$('myInput').observe('keyup', function(e){
  if (e.keyCode == Event.KEY_TAB)
    doSomethingCoolWhenTabIsPressed();
})

keyCode는 KEY_RETURN, KEY_ESC, KEY_TAB, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN 과 같은 값들이 있다.

이벤트 가로채기[#13]

기본적인 방법
Event.observe('productInfo', 'click', displayProductInfo, false); // 'false' could be skipped
Event.observe('productInfo', 'click', displayProductInfo);

간단한 방법

$('productInfo').observe('click', displayProductInfo, false); // 'false' could be skipped
$('productInfo').observe('click', displayProductInfo);

insert() 메소드 제대로 사용하기[#14]

new Insertion.Bottom('blogEntry',
  new Template('<div><h2>#{name}</h2><p>#{content}</p></div>')
    .evaluate({
      name: blogEntry.name,
      content: blogEntry.content
    }));
 
// Insertion class is deprecated - it's recommended to use Element's insert method:
 
$('blogEntry').insert(new Template('<div><h2>#{name}</h2><p>#{content}</p></div>')
    .evaluate({
      name: blogEntry.name,
      content: blogEntry.content
    }), 'bottom' ); // "bottom" can be skipped
 
$('blogEntry').insert(new Template('<div><h2>#{name}</h2><p>#{content}</p></div>')
    .evaluate({
      name: blogEntry.name,
      content: blogEntry.content
    }));

위치값은 top, bottom, before, after 를 사용할수 있다. 이 값을 생략한다면 디폴트는 bottom이다.

form 다루기[#15]

다음은 .request를 사용하는 일반적인 form이다.
$('register').observe('submit', function(e){
  Event.stop(e);
  $(this).request();
})

.getInputs 는 type과 name속성에 기초하여 요소를 필터링하기 쉬도록 해준다. 여기서는 "email" 이라는 이름의 요소를 직렬화하고 폼의 "action" 이라는 속성내 포함된 URI에 결과를 서브밋한다.

$('register').observe('submit', function(e){
  Event.stop(e);
  new Ajax.Request($(this).readAttribute('action'), {
    parameters: Form.serializeElements($(this).getInputs('', 'email'))
  })
})

앞서 본 .getInputs가 대부분의 경우 유용하지만 일부 속성을 제외하고자 할때는 .reject를 사용한다.

$('register').observe('submit', function(e){
  Event.stop(e);
  new Ajax.Request(this.readAttribute('action'), {
    parameters: Form.serializeElements($(this).getElements()
      .reject(function(el){return el.hasAttribute('multiple')})
    );
  })
})
Posted by 1010
반응형

소개

웹 도처에 사용되는 자바스크립트의 늘어가는 인기는 클라이언트측 코드가 안정성, 속도, 재사용성등이 혼합으로 구현되도록 하는것이 좀더 중요하게 되었다. 이것을 달성하기 위한 가장 좋은 방법중 하나는 간단한 라이브러리와 모든 프로젝트를 위한 기본사항처럼 사용하기 위한 문법이다. 고맙게도 Sam Stephenson 는 우리의 자바스크립트 개발을 쉽게 하기 위한 Prototype.js 라 불리는 놀라운 함수들의 라이브러리를 만들었다.

우리의 독자들이Prototype 문법을 사용하는 문서 를 읽은 후 크게 놀랐고, 우리는 많은 개발자를 위해 좀더 쉽게 배울수 있도록 도와주는 라이브러리를 위한 참조문서를 만드는게 좋겠다는 결심을 했다. 다음의 튜토리얼은 Particletree프로젝트에서 사용된 가장 공통적인 함수들을 사용하는 간단한 예제와 함께 설명할 것이다. 이 문서는 Sergio Pereira에 의해 좀더 많은 내용을 가진 비공식적인 프로토타입 문서 와 함께 사용되었음을 의미한다. 그리고 script.aculo.us 문서 위키는 모든 자바스크립트/프로토타입 개발자들이 읽기를 매우 추천한다.

시작하기

파일을 다운로드 한 후에, 당신이 선호하는 디렉토리에 그 파일들을 넣어둬라. 당신이 해야할 일은 html문서에 다음처럼 추가를 하는 것이다.

<script src="/scripts/prototype.js" type="text/javascript"></script>

이것으로 자바 스크립트를 개발하는게 10배는 쉬워진다. 지금, 당신이 획득한 새롭고 멋진 무기를 보자.

알림 - 이 튜토리얼은 1.3.1버전을 기반으로 작성되었다.

$() 함수

가장 자주 사용되고 편리한 함수인, $()는 DOM요소를 다루기 위한 쉬운 방법을 제공한다. 일반적으로, 당신이 DOM내 특정 요소에 접근하고자 한다면, 다음처럼 작성할것이다.

node = document.getElementById("elementID");

$()를 사용하면, 다음처럼 간단히 작성할수 있다.

node = $("elementID");

간단하고 멋지지만 이러한 장점보다, $()함수는 다중 요소를 함수안으로 가져오는 기능을 가지고 있기 때문에 document.getElementById()보다 좀더 강력하다.

allNodes = $("firstDiv", "secondDiv");
for(i = 0; i < allNodes.length; i++) {
    alert(allNodes[i].innerHTML);
}

이 예제에서, 우리는 루프를 통해 간단히 접근할수 있는 요소들의 배열을 가지고 오는 것을 볼수 있다.

폼 헬퍼(Form Helper) 함수

폼은 HTML과 CSS관점에서 근심거리일뿐 아니라, 자바스크립트의 측면에서도 그렇다. Prototype.js는 폼을 다루는 유용하고 독창적인 함수를 제공한다.

$F() 함수 는 폼 요소의 값과 전달하는 ID를 반환한다. 만약 우리가 다음처럼 HTML필드를 둔다면,

<input type="text" id="textfield" name="textfield" />
<textarea rows="5" cols="5" id="areafield" name="areafield"></textarea>
<select id="selectfield" name="selectfield">
    <option value="1" selected>One</option>
    <option value="2">Two</option>
</select>
<input type="checkbox" id="checkfield" name="checkfield" value="1" checked />

우리는 $F()함수를 사용하여 폼내의 값들에 쉽게 접근할수 있다.

$F("textfield");      // returns the value of the text input
$F("areafield");      // returns the value of the textarea
$F("selectfield");    // returns the selected value of the select
$F("checkfield");     // returns undefined if not checked, or the value

제어와는 관계없이 값을 얻는 기능은 대부분의 환경에서 좀더 쉽게 폼을 처리하도록 해준다. 여기에 이 함수를 사용할때 찾을수 있는 두가지 결점이 있다. 1) radio그룹의 선택된 값에 접근하는 쉬운 방법이 없다(하나의 radio요소의 값만 처리). 2) $()함수를 사용할때처럼 다중 ID를 전달하는 것이 불가능하다.

*다른 함수인, Form.getElements() 는 타입에 관계없이 모든 폼 요소의 배열을 반환한다.

allNodes = Form.getElements("myform");
for(i = 0; i < allNodes.length; i++) {
    //do something to each form field
}

이 예제에서, 우리는 myform이라는 id를 가진 폼으로 부터 모든 요소를 가져온다. 만약 당신이 onclick을 추가하고 싶거나 각각의 폼필드에 도움말 팝업을 추가하기를 원한다면, 당신은 위와 같은 형식을 통해 할수 있다.

우리가 볼 다음 메소드는 Form.serialize()이다. Ajax요청을 빌드할때, 당신은 데이터를 전달하기 위해 당신 자신만의 문자열을 포맷팅하기를 원한다. 폼이 서브밋되었을때, 문자열은 빌드되고, serialize()는 처리를 쉽게 만든다.

allNodes = Form.serialize("myform");

// returns field1=value1&field2=value2&field3=value3 and so on...

우리를 돕기 위해 문자열을 빌드하라. 하지만 메소드를 좀더 좋게 만드는 것은 이것은 필드의 타입에 기초를 두지 않는 것이다. 우리는 이전에 $F()가 radio그룹에서 몇가지 문제점을 가지는 것을 봤다. 하지만 serialize()는 어떠한 필드 타입을 위해서도 값을 정확하게 처리한다. 사용가능한 폼 메소드만 있는 것은 아니다, 나머지것들을 보기 위해서는 Sergio의 문서 를 보라.

getElementsByClassName

getElementsByClassName()가 아직도 자바스크립트로 빌드되지 않은 이유는 뭔가.? 이것은 프로토타입이 아니고 그래서 프로토타입은 문서객체의 확장처럼 저장소(arsenal)로 이것을 추가했다. 이것은 document.getElementsByTagName()처럼 정확하게 작동한다. 단지 차이점은 className을 체크하는 것이다.

allNodes = document.getElementsByClassName("red");
for(i = 0; i < allNodes.length; i++) {
    alert(allNodes[i].innerHTML);
}

반환되는 배열은 주어진 className과 일치하는 모든 요소를 포함한다. 이것은 다중 className을 가진 요소들과도 잘 작동한다. getElementsByClassName()는 도처에서 모든 프로젝트에서 사용되는 함수가 되었다. 주로 DOM이벤트에 붙기 때문에 나는 모든 개발자가 이것을 사용하도록 제안한다.

요소 헬퍼(Element Helper) 함수

요소객체는 공통적으로 DOM조작을 돕는 많은 수의 헬퍼 함수를 제공한다. 몇몇 이러한 함수는 하나의 호출에 10줄 이상의 코드를 단순화하는동안 어떤 새로운 것도 생성하지 않는다. 그럼 몇몇 예제를 보자.

헬퍼 없이 요소의 높이를 가져오자.

$("first").offsetHeight

그리고 지금은 헬퍼를 사용하는 경우이다.

Element.getHeight("first")

이 경우, 헬퍼는 어떠한 잇점도 제공하지 않는다. 지금 우리가 요소로부터 className을 제거하길 원하는가.? 이것은 (Prototype.js소스코드로 부터 얻어진) 다소 긴 방법이다.

element = $(element);
if (!element)
    return;
var newClassName = '';
var a = element.className.split(' ');
for (var i = 0; i < a.length; i++) {
    if (a[i] != className) {
        if (i > 0)
            newClassName += ' ';
        newClassName += a[i];
    }
}
element.className = newClassName;

그리고 지금은 헬퍼 함수를 사용하는 경우이다.

Element.removeClassName("elementID", "red");

멋진가.? 첫번째 예제와는 달리, 대부분의 헬퍼 함수는 공통적인 작업을 쉽게 수행하여 시간과 수고를 아낀다. 그리고 일관성을 위해, 이것은 프로젝트 도처에 Element문법을 사용하는 것이 가장 좋은 방법이 될것이다. 헬퍼 함수의 전체 목록과 그것들을 사용하는 방법을 보기 위해서, Sergio의 프로토타입 문서를 보라.

Try.these 함수

Try.these()는 다른 자바스크립트 구현물과 관계없이 브라우저를 종속되지 않고 작동하는 코드를 생성하도록 개발자를 도와주기 위한 멋진 함수이다. 객체와 브라우저 인식의 자신만의 방법대신에, 이 함수는 에러를 발생할때까지 코드의 하나의 경로를 수행하도록 시도하고 다음 경로로 교체한다.

return Try.these(
    function() {
        alert("first");
        jkgjhgjhg        //intentional error
        alert("firsterror");
        return 1;
    },
    function() {
        alert("second");
        return 2;
    }
);

위 예제에서, 첫번째 경로는 내부 에러발생시 수행을 멈출것이다. 이것을 알라. 모든것은 에러가 발생되지 전에 수행되어야 하기 때문에 이것은 우리의 코드가 신중하도록 하기 위해 중요하다. 우리는 코드가 두번 수행되지 않도록 주의해야만 한다. 전체적으로, Try.these()는 우리가 종종 사용하는 함수일뿐 아니라, 이것이 존재하고 어떻게 사용해야 하는지 아는것은 멋진 일이다.

Ajax 지원

이 라이브러리에서 Ajax지원 함수는 부족하지 않다. 그리고 나는 Prototype.js의 도움으로 Ajax애플리케이션을 생성하는 방법을 보여줄것이다. 문서로부터 우리는 다음처럼 일반적인 Ajax요청을 볼수 있다.

var myAjax = new Ajax.Request(
    url,
    {method: 'post', parameters: data, onComplete: ajax_response}
);

메소드가 post이거나 get인 지점에서, 파라미터는 이름/값 형태의 문자열이고, onComplete은 모든것이 종료되었을때 호출되어야 하는 함수이다. 핵심기능을 이해했을때, 라이브러리를 도구화하는 자신만의 함수를 생성하여 반복적인 Ajax호출을 만드는 것이 쉽다. 먼저, Ajax요청을 처리하는 간단한 함수이다.

function ajax_request(url, data) {
    var myAjax = new Ajax.Request(
        url,
        {method: 'post', parameters: data, onComplete: ajax_response}
    );
}

요청이 종료된후, 이것을 ajax_response()로 보낸다.

function ajax_response(originalRequest) {
    if(!bHasRedirect) {
        //process originalRequest.responseText;
    }
    else {
        bHasRedirect = false;
        ajax_request(originalRequest.responseText, "");
    }
}

당신이 Ajax요청을 만든후, 응답은 언제나 ajax-response()로 보내진다. 여기서 다른 Ajax요청은 bHasRedirect(전역변수)가 true로 셋팅된 경우에만 만들어질것이고 true가 아니라면 아마 코드는 함수와 originalRequest.responseText()의 전역 배열에 기반하여 수행될것이다.

PeriodicalExecuter

PeriodicalExecuter객체가 초기화되면, 이것은 주어진 기간에 특정 함수를 반복적으로 호출한다. 이것은 당신이 사이트의 Ajax부분을 자동으로 수정하길 바랄때 유용할것이다.

function periodicalUpdate() {
    new PeriodicalExecuter(refreshNews, 10);
}

function refreshNews() {
    //Ajax code to grab news and update DOM
}

PeriodicalExecuter 생성자는 첫번째 파라미터처럼 호출하기 위한 함수를 예상한다. 그리고 이것은 시간간격(초단위)이다. 비록 공통적인 setInterval()가 밀리세컨드를 다루지만 시간을 혼동하지 말라. 하지만 이 함수에서 우리는 초 단위로 다룬다. 예제는 Ajax가 복잡하다고 가정하지만, 이것은 어떤 이유로 페이지를 수정할수 있다. Prototype.js는 또한 Ajax를 다룰때 쉽게 처리할수 있는 Ajax.PeriodicalUpdater클래스를 가진다.

추가적인 고급기능.

우리가 Prototype.js가 제공하는 모든 함수와 메소드를 다룰수는 없지만, 이것은 여기서 다룰수 없는 것중에 몇몇을 강조해두는 것은 중요하다고 볼수 있다.

감독(observe) - 이 메소드 함수는 addEvent()와 비슷하고, DOM에 이벤트를 붙이기 위해 사용된다.

사용자 상호작용(User Interaction) - 당신은 사용자를 처리하는 key가 무엇을 만드는지 알기 위해 KEY_TAB와 같은 전역값내 빌드된것을 찾을수 있다. 추가적으로, 당신은 마우스를 클릭할때 위치를 찾을수 있다.

클래스 생성(Class Creation) - Prototype.js가 제공하는 것이 무엇인지 왜 멈추는가.? 같은 문법과 함수를 사용하여, 우리는 일관성을 유지하기 위해 자신만의 클래스를 빌드할수 있다. 생성자와 추가적인 메소드를 추가하는 것은 결코 쉽지 않다. 이것을 포장하기 위해 문서에서 Class.create() 를 보라.

당신이 저자를 알지못하고 무엇인가 발생한것을 제대로 이해하지 못할때 일반적인 코드/라이브러리를 사용하는 것을 받아들일수 있는가.? 당신이 코드를 테스트하고 사람/커뮤니티를 신뢰하는 만큼 나의 대답은 예이다. Prototype.js의 경우, 신뢰는 두개의 소스로부터 빌드된다. 먼저, Ruby on Rails 은 프로토타입 지원과 통합되었다. Ruby on Rails이 훌륭한 개발 기본이 된 이후로, 많은 버그가 발견되었고 Prototype.js가 좀더 안정화되도록 많은 문제가 해결되었다. 두번째, 개발자는 Ruby on Rails의 creator 를 고용하는 37시그널에서 근무한다. 나는 회사의 개발 환경을 신뢰할 뿐 아니라, Prototype.js가 테스트가 지속되고 지속적으로 발전하리라고 생각한다. 주어진 것으로 나의 프로젝트를 테스트하고, 나는 나의 모든 프로젝트에 이 라이브러리를 자신있게 사용한다.

Prototype.js는 이 튜토리얼에서 목록화된 것보다 두배 이상의 함수를 가지고 명백히 체크아웃할 가치가 있다. 만약 당신이 파일 사이즈(약 30K)가 꺼려진다면, 당신이 사용하지 않는 클래스는 뺄수 있고 사용자에게 제공하기 전에 PHP와 함께 자바스크립트 파일을 압축할수 있다는 것을 기억하라. 또한 당신이 약간의 메소드를 사용했다면 나머지는 배우기 쉽다. 그래서 배우는 과정은 매우 간단하다. 기본적으로 이것을 시도하기 위한 핑계거리는 없다. 위에서 본 예제는 Particletree에서 이것들을 다룬 방법이고 테스트없이 사용된 것은 없다. 기억하라. 이것은 Prototype.js에 대한 소개이고 그래서 비공식적인 프로토타입 문서를 참조하고 신뢰해야 하며 다양한 메소드를 찾는 어려운 작업을 위해 script.aculo.us 문서 위키 wiki를 보라. 언제나 처럼, 당신이 실수나 가능한 개선사항이 있다면, 우리에게 알려달라.

Posted by 1010
54.iBATIS, MyBatis/iBatis2008. 7. 25. 16:04
반응형

<JDBC 연결을 위한 DB서버 정보 세팅>

database.propertis

#ORACLE 10g  DB server관련 드라이버,URL,계정,비밀번호 세팅
db_driver=oracle.jdbc.driver.OracleDriver
db_url=jdbc:oracle:thin:@localhost:1521:XE
db_usernm=scott
db_pw=tiger

앞의 프러퍼티 이름은 임의로 정해주면 된다.


ORM을 위한 POJO 객체를 생성한다.

Member.java

//POJO
package com;

import java.io.Serializable;

public class Member implements Serializable {
 private String id;
 private String pw;
 private String nm;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getNm() {
  return nm;
 }
 public void setNm(String nm) {
  this.nm = nm;
 }
 public String getPw() {
  return pw;
 }
 public void setPw(String pw) {
  this.pw = pw;
 }
}

테이블과 연관하기 위한 정보및 쿼리를 작성한다.

Member.xml

<?xml version="1.0" encoding="EUC-KR" standalone="no"?>
<!DOCTYPE sqlMap          
                                PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"          
                                "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Member">
 <!--
  Member
 -->
 <typeAlias alias="member" type="com.Member" /><!-- pojo클래스 별칭주기 -->

 <resultMap id="getMemberAll" class="member"><!-- 클래스 프러퍼티와 디비 컬럼맵핑 -->
  <result property="id" column="id" />
  <result property="pw" column="pw" />
  <result property="nm" column="nm" />
 </resultMap>

 <select id="getMemberAll" resultMap="getMemberAll">
  SELECT id, pw, nm FROM MEMBER
 </select>
 
 <select id="getMember" resultMap="getMemberAll">
  SELECT id, pw, nm FROM MEMBER

  WHERE ID=#id#
 </select>

 <insert id="insertMember" parameterClass="member">
  INSERT INTO MEMBER (id, pw, nm) VALUES (#id#, #pw#, #nm#)
 </insert>

 <update id="updateMember" parameterClass="member">
  UPDATE MEMBER SET pw = #pw#, nm = #nm#

  WHERE ID = #id#
 </update>

 <delete id="deleteMember" parameterClass="member">
  DELETE FROM MEMBER WHERE ID = #id#
 </delete>

</sqlMap>

PreparedStatement에서 동적으로 값을 할당하기 위해 ?를 사용 하듯이

#id#처럼 동적으로 값이 할당 되는 부분을 정한다.


SqlMapClientManager.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig 
                                PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
                                "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
        <properties resource="com/database.properties" /><!-- 디비 정보 프러퍼티  세팅 -->
        <settings cacheModelsEnabled="false"
                  useStatementNamespaces="true"
        />

        <transactionManager type="JDBC"> <!--  프러퍼티 값을 세팅-->
                <dataSource type="SIMPLE">
                    <property name ="JDBC.Driver" value="${db_driver}"/>
                    <property name ="JDBC.ConnectionURL" value="${db_url}"/>
            <property name ="JDBC.Username" value="${db_usernm}"/>
            <property name ="JDBC.Password" value="${db_pw}"/>
                </dataSource>
        </transactionManager>

        <sqlMap resource="com/Member.xml" /> <!-- pojo, 테이블을 맵핑한 xml들 -->
</sqlMapConfig>
프러퍼티에 세팅한 정보를 가져와 JDBC관련 세팅을 하고,

pojo와 연관시킨 xml를 읽어 들인다.


SqlMapClientManager.java

package com;
import java.io.Reader;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
/**
*
* @author Administrator
*
*/
public class SqlMapClientManager {
       
        private static final SqlMapClient sqlMap;

        static {
                try {
                        String resource = "com/SqlMapClientManager.xml";
                        Reader reader = Resources.getResourceAsReader(resource);
                        sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
                       
                } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                }
        }
       
        private SqlMapClientManager(){}
       
        public static SqlMapClient getSqlMapClient() {
                return sqlMap;  
        }

}

SqlMapClientManager.xml 파일을 읽어 들여 SqlMapClient 인스턴스를 생성한다.


MemberDAO.java

package com;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import com.ibatis.sqlmap.client.SqlMapClient;

public class MemberDAO {

 private static SqlMapClient sqlMap = SqlMapClientManager.getSqlMapClient();
 public List listAll(){//모든 회원 조회

  Member paramMember = new Member();
  Member returnMember = new Member();

  List list=null;
  try {
   list = sqlMap.queryForList("Member.getMemberAll", paramMember);
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

  return list;

 }

 public Member getMember(Member member){  //회원 정보 조회

  Member paramMember = member;
  Member returnMember = new Member();

  try {
   member = (Member) sqlMap.queryForObject("Member.getMember", paramMember);
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return member;
 }


 public void insert(Member member){ //회원 등록

  Member paramMember = member;
  System.out.println("insert Member");
  System.out.println(member.getId());
  System.out.println(member.getNm());
  System.out.println(member.getPw());
  try {
   sqlMap.insert("Member.insertMember",paramMember);
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }
 public void update(Member member){
  // 사용자 수정
  Member paramMember = member;

  try {
   sqlMap.update("Member.updateMember",paramMember);
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public void delete(Member member){
  // 사용자 삭제
  Member paramMember = member;
  try {
   sqlMap.update("Member.deleteMember",paramMember);
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }
}

sqlMapClient 인스턴스를 통해 MEMBER테이블에 접근하기 위한 API제공

Posted by 1010
54.iBATIS, MyBatis/iBatis2008. 7. 25. 16:03
반응형

Hibernate 첫 번째 예제 - 튜토리얼

                                  원문 : http://www.laliluna.de/first-hibernate-example-tutorial.html

                                  역자 : 김종대(jdkim528@korea.com)

이 튜토리얼은 Hibernate를 사용하는 간단한 예제를 보여준다. 우리는 Hibernate가 어떻게 동작하는지를 보여주는 간단한 자바 어플리케이션을 생성시킬 것이다.

(광고 생략...)

개괄

저자: Sebastian Hennebrueder

날짜: December, 19th 2005

사용된 소프트웨어와 프레임워크

Eclipse 3.x

MyEclipse 4.x가 권장되지만 선택사항임

Hibernate 3.x (3.1을 사용함)

소스 코드: http://www.laliluna.de/download/first-hibernate-example-tutorial.zip

소스들은 라이브러리들을 포함하지 않는다. hibernate.org에서 라이브러리들과 당신의 데이터베이스 드라이버를 내려 받고 그것들을 아래에 설명되어 있는 프로젝트에 추가한다. 예제는 당신의 데이터베이스 설정들과 동작하도록 구성되어야 한다! 튜토리얼을 읽기 바란다.

 

튜토리얼의 PDF 버전:  http://www.laliluna.de/download/first-hibernate-example-tutorial-en.pdf

Hibernate2용 이전 PDF 버전:  http://www.laliluna.de/download/first-hibernate-2-example-tutorial-en.pdf

짧은 개요

Hibernate는 객체 관계형 매핑을 위한 솔루션이고 영속 관리 솔루션 또는 영속 계층이다. 이것은 아마 Hibernate를 배우는 아무나 이해 가능한 것은 아니다.

당신이 생각할 수 있는 것은 아마 당신이 당신의 어플리케이션에 몇몇 기능들(비지니스 로직)을 갖도록 하고 데이터베이스 내에 데이터를 저장하고 싶어하는 것이다. 당신이 자바를 사용할 때 모든 비지니스 로직은 통상적으로 다른 클래스 타입들인 객체들과 동작한다. 당신의 데이터베이스 테이블들은 전혀 객체들이 아니다.

Hibernate는 데이터베이스 테이블들을 어떤 클래스로 매핑시키는 솔루션을 제공한다. 그것은 데이터베이스 데이터를 어떤 클래스로 복사한다. 반대 방향으로 그것은 객체들을 데이터베이스에 저장하는 것을 지원한다. 이 과정에서 객체는 하나 이상의 테이블들로 전환된다.

저장소에 데이터를 저장시키는 것은 영속이라 명명된다. 그리고 테이블들을 객체들에 복사하는 것 등등은 객체 관계형 매핑이라 명명된다.

Java 프로젝트를 생성한다

Eclipse를 사용하여 새로운 프로젝트를 생성시키기 위해 Ctrl+n (Strg+n) 키를 누른다. Java 프로젝트를 선택한다. 우리는 그것을 FirstHibernateExample라 명명할 것이다.
 

MyEclipse를 사용하여 Hibernate용 프로젝트를 준비한다

MyEclipse를 사용하고 있다면, 패키지 탐색기 내에서 당신의 프로젝트 상을 마우스 오른쪽 버튼 클릭하고 Add Hibernate capabilities.를 선택한다.




 

마법사를 계속하고 src 디렉토리 내에 새로운 hibernate.cfg.xml 을 생성시킨다.

마지막 단계에서 당신은 Hibernate SessionFactory를 생성시킬 수 있다. 나는 내 자신의 것을 생성 시키는 것을 선호한다. 당신은 아래에서 그것을 찾을 수 있다.

Hibernate용 프로젝트를 준비한다

당신이 MyEclipse를 사용하고 있지 않을 때 http://www.hibernate.org/ 웹 사이트로부터 Hibernate를 내려 받아라.

파일을 추출한다. Hibernate는 많은 라이브러리들의 목록으로 구성되어 있다. 당신은 그것들 모두를 필요로 하지 않는다. lib 디렉토리 내에 필수적인 것을 설명하고 있는 README 파일이 존재한다. 당신의 프로젝트 properties를 열고, “Java Build Path”를 선택하고, “Add External Jars”을 클릭하고 아래에 보이는 라이브러리들을 당신의 프로젝트 경로에 추가한다.

 



 

SessionFactory를 생성시킨다

세션 팩토리는 Hibernate에서 중요하다. 그것은 단위 쓰레드 당 오직 한 개의 세션 인스턴스만이 사용됨을 보증하는 설계 패턴을 구현하고 있다. 당신은 단지 이 팩토리로부터 당신의 Hibernate 세션을 얻을 것이다.

de.laliluna.hibernate 패키지 내에 HibernateSessionFactory로 명명된 클래스를 생성시키고 아래의 소스 코드를 추가한다.

/**
 * 
 * @author Sebastian Hennebrueder
 * created Feb 22, 2006
 * copyright 2006 by http://www.laliluna.de
 */
package de.laliluna.hibernate;

import javax.naming.InitialContext;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;

/**
 * @author hennebrueder 이 클래스는 오직 한 개의 SessionFactory 만이 초기화 되고
 *         컨피그레이션이 싱글톤으로 쓰레드 안전하게 행해진다는 점을 보증한다.
 *         실제로 그것은 단지 Hibernate SessionFactory를 포장한다.
 *         JNDI 이름이 구성될 때 세션은 JNDI에 바인드 되고, 
 *         그 밖의 경우 그것은 오직 로컬 상으로 저장된다.
 *         당신은 임의의 종류의 JTA 또는 Thread transactionFactory들을 사용하는 것이 자유롭다. 
 */
public class InitSessionFactory {

	/**
	 * Default constructor.
	 */
	private InitSessionFactory() {
	}

	/**
	 * hibernate.cfg.xml 파일의 위치. 주의: 위치는 Hibernate가 사용하는 classpath 상에 있어야 한다
	 * #resourceAsStream 스타일은 그것의 구성 컨피그레이션 파일을 검색한다.
	 * 그것은 Java 패키지 내에 있는 config 파일에 위치된다 - 
	 * 디폴트 위치는 디폴트 Java 패키지이다.<br>
	 * <br>
	 * 예제: <br>
	 * <code>CONFIG_FILE_LOCATION = "/hibernate.conf.xml". 
	 * CONFIG_FILE_LOCATION = "/com/foo/bar/myhiberstuff.conf.xml".</code>
	 */
	private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";

	/** hibernate 컨피그레이션의 싱글톤 인스턴스 */
	private static final Configuration cfg = new Configuration();

	/** hibernate SessionFactory의 싱글톤 인스턴스 */
	private static org.hibernate.SessionFactory sessionFactory;

	/**
	 * 아직 초기화 되지 않았다면 컨피그레이션을 초기화 시키고 현재 인스턴스를 반환한다
	 * 현재 인스턴스를 반환한다
	 * 
	 * @return
	 */
	public static SessionFactory getInstance() {
		if (sessionFactory == null)
			initSessionFactory();
		return sessionFactory;
	}

	/**
	 * ThreadLocal Session 인스턴스를 반환한다. 필요하다면 Lazy는 
	 * <code>SessionFactory</code>를 초기화 시킨다.
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public Session openSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 이 메소드의 행위는 당신이 구성했던 세션 컨텍스트에 의존한다.
	 * 이 팩토리는  다음 프로퍼티 is intended to be used with a hibernate.cfg.xml
	 * <property name="current_session_context_class">thread</property>를 
	 * 포함하는 hibernate.cfg.xml과 함께 사용되게 기안되어 있다. 이것은 
	 * 현재의 열려진 세션을 반환할 것이거나 존재하지 않을 경우 새로운 세션을 생성시킬 것이다
	 * 
	 * @return
	 */
	public Session getCurrentSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 심지어 하나 이상의 쓰레드가 sessionFactory를 빌드하려고 시도하는 경우조차도 
	 * 안전한 방법으로 sessionFactory를 초기화 시킨다
	 */
	private static synchronized void initSessionFactory() {
		/*
		 * [laliluna] 다시 null을 체크한다 왜냐하면 sessionFactory가 마지막 체크와 현재의 체크 사이에
		 * 초기화 되었을 수도 있기 때문이다
		 * 
		 */
		Logger log = Logger.getLogger(InitSessionFactory.class);
		if (sessionFactory == null) {
 

			try {
				cfg.configure(CONFIG_FILE_LOCATION);
				String sessionFactoryJndiName = cfg
				.getProperty(Environment.SESSION_FACTORY_NAME);
				if (sessionFactoryJndiName != null) {
					cfg.buildSessionFactory();
					log.debug("get a jndi session factory");
					sessionFactory = (SessionFactory) (new InitialContext())
							.lookup(sessionFactoryJndiName);
				} else{
					log.debug("classic factory");
					sessionFactory = cfg.buildSessionFactory();
				}

			} catch (Exception e) {
				System.err
						.println("%%%% Error Creating HibernateSessionFactory %%%%");
				e.printStackTrace();
				throw new HibernateException(
						"Could not initialize the Hibernate configuration");
			}
		}
	}
 
	public static void close(){
		if (sessionFactory != null)
			sessionFactory.close();
		sessionFactory = null;
 
	}
}


 

Log4J 구성하기

당신이 위에서 보았듯이 우리는 log4j 라이브러리를 추가시켰다. 이 라이브러리는 소스 디렉토리 내에 컨피그레이션 파일처럼 행하거나 다음 오류로서 당신을 맞이한다.

log4j:WARN No appenders could be found for logger (TestClient).
log4j:WARN Please initialize the log4j system properly.

루트 디렉토리에 log4j.properties로 명명된 파일을 생성시키고 다음을 삽입시킨다:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=info

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
log4j.logger.org.hibernate.cache=info

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

데이터베이스 드라이버를 추가한다

Hibernate는 데이터베이스에 접근할 데이터베이스 드라이버를 필요로 한다. 프로젝트 properties를 열고, “Java Build Path”를 클릭하고, “Add External Jars”를 선택하고 당신의 데이터베이스 드라이버를 추가한다. 당신이 PostgreSQL를 사용할 때 당신은  http://jdbc.postgresql.org에서 당신의 데이터베이스 드라이버를 찾을 수 있고 MySQL을 사용하고 있다면 이곳 http://www.mysql.de/products/connector/j에서 찾을 수 있다.

데이터베이스와 테이블드을 생성시킨다.

Create a database with MySql 또는 PostgreSQL 또는 당신이 좋아하는 DBMS에 데이터베이스를 생성시킨다. 그것을 “firsthibernate”로 명명한다.

PostgreSql을 사용한다면 테이블을 생성시키기 위해 다음 스크립트를 사용하라:

CREATE TABLE "public"."honey" (
  id SERIAL, 
  name text, 
  taste text, 
  PRIMARY KEY(id)
);


 

MySql을 사용하고 있다면 다음 스크립트를 사용하라:

CREATE TABLE `honey` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(250) default NULL,
  `taste` varchar(250) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

클래스를 생성시킨다

Create a new class named “Honey” in the package “de.laliluna.example”. Add three fields id, name and taste and generate (Context menu -> Source -> Generate Getter and Setter) or type the getters and setters for the fields. Then create an empty constructor.

package de.laliluna.example;

/**
 * @author laliluna
 *
 */
public class Honey {
	private Integer id;
	private String name;
	private String taste;
 
	public Honey(){
 
	}
 
	/**
	 * @return Returns the id.
	 */
	public Integer getId() {
		return id;
	}
	/**
	 * @param id The id to set.
	 */
	public void setId(Integer id) {
		this.id = id;
	}
	/**
	 * @return Returns the name.
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name The name to set.
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return Returns the taste.
	 */
	public String getTaste() {
		return taste;
	}
	/**
	 * @param taste The taste to set.
	 */
	public void setTaste(String taste) {
		this.taste = taste;
	}
}



 

매핑 파일들을 생성시킨다

이미 생성되어 있지 않다면 루트 디렉토리에 “hibernate.cfg.xml”로 명명된 새로운 파일을 생성시킨다.

hibernate 파일 내에 다음을 추가한다. 당신의 데이터베이스 구성에 적합하게 username과 password를 변경하는 것을 잊지 말라.

PostgreSQL 버전:

<?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="connection.url">jdbc:postgresql://localhost/firsthibernate</property>
	<property name="connection.username">postgres</property>
	<property name="connection.driver_class">org.postgresql.Driver</property>
	<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
	<property name="connection.password">p</property>
 <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
    <!--  thread is the short name for
      org.hibernate.context.ThreadLocalSessionContext
      and let Hibernate bind the session automatically to the thread
    -->
    <property name="current_session_context_class">thread</property>
    <!-- this will show us all sql statements -->
    <property name="hibernate.show_sql">true</property>
	<!-- mapping files -->
	<mapping resource="de/laliluna/example/Honey.hbm.xml" />
</session-factory>
</hibernate-configuration>


 

MySQL 버전:


 

<?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="connection.url">jdbc:mysql://localhost/firsthibernate</property>
	<property name="connection.username">root</property>
	<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
	<property name="connection.password">r</property>
 <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
    <!--  thread is the short name for
      org.hibernate.context.ThreadLocalSessionContext
      and let Hibernate bind the session automatically to the thread
    -->
    <property name="current_session_context_class">thread</property>
    <!-- this will show us all sql statements -->
    <property name="hibernate.show_sql">true</property>
 
	<!-- mapping files -->
	<mapping resource="de/laliluna/example/Honey.hbm.xml" />

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


 

이 파일은 데이터베이스에 대한 구성 우리의 경우에는 PostgreSQL 데이터베이스의 구성 그리고 모든 매핑 파일들을 포함한다. 우리의 경우 그것은 단지 파일 Honey.hbm.xml이다. 

<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>

태그는 dialect를 구성한다. 당신의 데이터베이스에 맞게 이것을 변경하라. 당신의 데이터베이스를 위한 dialect를 찾기 위해 Hibernate 레퍼런스의 “SQL Dialects” 장에서 찾아보라.

de.laliluna.example 패키지 내에 Honey.hbm.xml을 생성시키고 그것을 다음으로 변경하라:

PostgreSQL 버전:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
 <class name="de.laliluna.example.Honey" table="honey">
 <id name="id" column="id" type="java.lang.Integer">
		<generator class="sequence">
				<param name="sequence">honey_id_seq</param>
			</generator>

 </id>
 
 <property name="name" column="name" type="java.lang.String" />
 <property name="taste" column="taste" type="java.lang.String" />
 </class>
</hibernate-mapping>


 

MySQL 버전:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
 <class name="de.laliluna.example.Honey" table="honey">
 <id name="id" column="id" type="java.lang.Integer">
 <generator class="increment"/>
 </id>
 <property name="name" column="name" type="java.lang.String" />
 <property name="taste" column="taste" type="java.lang.String" />
 </class>
</hibernate-mapping>


 

이 파일에서 우리의 클래스 Honey로부터 데이터베이스 테이블 honey로의 매핑이 구성되어 있다.

테스트 클라이언트를 생성한다

“de.laliluna.example” 패키지 내에 Java 클래스 “TestClient”를 생성시킨다.

다음 소스 코드를 추가한다. 그것은 데이터베이스 내에 엔트리들을 생성시키는 메소드, 그것들을 업데이트하고 리스트하는 메소드들을 포함하고 있다.

/**
 * Test application for example 
 * @author Sebastian Hennebrueder
 * created Jan 16, 2006
 * copyright 2006 by http://www.laliluna.de
 */

package de.laliluna.example;

import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import de.laliluna.hibernate.InitSessionFactory;

public class TestExample {

	private static Logger log =Logger.getLogger(TestExample.class);
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Honey forestHoney = new Honey();
		forestHoney.setName("forest honey");
		forestHoney.setTaste("very sweet");
		Honey countryHoney = new Honey();
		countryHoney.setName("country honey");
		countryHoney.setTaste("tasty");
		createHoney(forestHoney);
		createHoney(countryHoney);
		// our instances have a primary key now:
		log.debug(forestHoney);
		log.debug(countryHoney);
		listHoney();
		deleteHoney(forestHoney);
		listHoney();

	}

	private static void listHoney() {
		Transaction tx = null;
		Session session = InitSessionFactory.getInstance().getCurrentSession();
		try {
			tx = session.beginTransaction();
			List honeys = session.createQuery("select h from Honey as h")
					.list();
			for (Iterator iter = honeys.iterator(); iter.hasNext();) {
				Honey element = (Honey) iter.next();
				log.debug(element);
			}
			tx.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();

		}
	}

	private static void deleteHoney(Honey honey) {
		Transaction tx = null;
		Session session = InitSessionFactory.getInstance().getCurrentSession();
		try {
			tx = session.beginTransaction();
			session.delete(honey);
			tx.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();
		}
	}

	private static void createHoney(Honey honey) {
		Transaction tx = null;
		Session session = InitSessionFactory.getInstance().getCurrentSession();
		try {
			tx = session.beginTransaction();
			session.save(honey);
			tx.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();
		}
	}
}


 

축하합니다. 당신은 Hibernate 세계에서 당신의 첫 번째 단계들을 마쳤습니다. 

우리는 당신이 Hibernate 세계에 빠르게 진입하기를 원했다. Hibernate를 사용하는 많은 복잡한 토픽들과 더 나은 구현이 존재한다. 예를 들어, 각각의 메소드 내에서 세션을 열고 닫는 것은 좋은 연습이 아니다. 하나의 세션은 재사용될 수 있으며 그 동안에 많은 시간을 절약한다.

당신이 최상의 실전에 대해 더 많은 것을 배우고자 원할 경우 우리의 세미나 또는 다른 튜토리얼을 살펴보길 바란다.

Copyright and disclaimer

This tutorial is copyright of Sebastian Hennebrueder, laliluna.de. You may download a tutorial for your own personal use but not redistribute it. You must not remove or modify this copyright notice.(이 튜토리얼은 Sebastian Hennebrueder, laliluna.de에 저작권이 있다. 당신은 당신 자신의 개인 용도로 튜토리얼을 내려받을 수 있지만 그것을 재배포할 수 없다. 당신은 이 저작권 경고를 제거하지 말아야 하거나 변경시키지 말아야 한다.이하 생략...)

The tutorial is provided as is. I do not give any warranty or guaranty any fitness for a particular purpose. In no event shall I be liable to any party for direct, indirect, special, incidental, or consequential damages, including lost profits, arising out of the use of this tutorial, even if I has been advised of the possibility of such damage.

Posted by 1010
90.개발관련문서2008. 7. 24. 18:10
반응형

Main Page

From MDC

Image:Firefoxlogo2.png

Firefox 3 for developers

Firefox 3 has been released, and is now available for download. See Firefox 3 for developers for developer documentation.

The Truth About JavaScript

Get a sneak peek at upcoming changes to JavaScript from Brendan Eich.

Mozilla Developer Center contents

Topics

Mozilla internals

Application and component framework

Technologies

  • AJAX - Asynchronous JavaScript and XML
  • CSS - Cascading Style Sheets
  • DOM - Document Object Model
  • HTML - Hypertext Markup Language
  • JavaScript
  • NSS - Network Security Services
  • RDF - Resource Description Framework
  • RSS - Really Simple Syndication
  • SVG - Scalable Vector Graphics
  • XBL - Extensible Binding Language
  • XForms - XML Forms
  • XML - Extensible Markup Language
  • XML Web Services - SOAP, XML-RPC, etc.
  • XPath - XML Path Language
  • XSLT - Extensible Stylesheet Language Transformations
  • XUL - XML User Interface Language

Mozilla Developer Center


Mozilla Developer Center blogs

Mozilla Developer News

MDC Webwatch

Posted by 1010
01.JAVA/Java2008. 7. 24. 13:57
반응형
JSP Tips
http://www.okjsp.pe.kr/seq/42732
유효하지 않는 전자메일 2004-03-18 00:19:30.0
park17@empal.com http://www.gampol.net
자바로 썸네일 빈즈를 함 만들어 보았네요..!!!

테스트 환경

j2sdk1.4.x
jai 1.x
window 2000, Linux
Tomcat 4.1.x


www.gampol.net에서 테스트 해 보실수 있습니다.

집에있는 컴이라 보통 저녁 10시까진 On상태이고

제가 잠잘때는 Off상태입니다.


먼저 SUN사이트에서 jai(Java Advanced Imaging 1.1.2)
를 다운로드 받으셔야 합니다.

http://java.sun.com/products/java-media/jai/downloads/download-1_1_2.html

다운 받고 압축이나 실행파일을 실행 하시면

jai_codec.jar, jai_core.jar

파일을 CLASSPATH에 추가하시고

JAVA_OPTS="-Djava.awt.headless=true"

또는

CATALINA_OPTS="-Djava.awt.headless=true"

환경변수를 셋팅하시고

또는 빈즈나 서블릿 실행시

System.setProperty("java.awt.headless", "true");

이걸 추가 하시기 바랍니다.


메소드는 대충 보시면 아실겁니다..

배율, 넓이높이 지정

파일로도 저장 가능하고 서버에 있는 이미지를 웹상에서 걍 보여 줄수도 있습니다.


문의 사항이나 버그가 있으면

park17@empal.com으로 연락 바랍니다.

그럼 유용하게 사용하시기 바랍니다..

출처 : Tong - 설레임중독자님의 JAVA통

Posted by 1010
98..Etc/Etc...2008. 7. 24. 13:40
반응형
 삽질 소감 -
아직 다듬어질려면 멀었고 관련 문서도 없는데가가 거의 이사람 혼자 만들어 공개한것으로 보인다. 소스코드는 제법 튼실해 보이고, 참고할만한 각종 유틸성 기법들이 유용하게 보인다. 그러나 일반 유저가 코드를 돌려보기엔 접근성이 상당히 떨어진다. 잘~ 하면 중간에 흔적도 없이 살아질 프로젝트 같다.

소스코드에서도 확인할수 있고 테스트한 동영상을 봐도 확인할수 있겠지만 이것은 공용(?) 어플리케이션 프레임웍(AP)를 표방(? 흉내?)하고 있다. 그래서 설정이 복잡하다 약간만 환경을 바꾸거나, 꼬여도 에러잡기가 힘들다. (Library의존성은 왜이리 꼬였는지...) Appfuse와는 보다 더 많은걸 구현하다 보니 상당부분 유연성을 포기하고 대신에 틀에 맞는 편리함을 제공하고 있다. 여전히 더 지켜봐야 할것 같다.

그래도 흔적을 남기는 이유는 AP를 구경하기 쉬운게 아니기 때문에....

동영상 및 소스코드 다운로드 : Download Link (동영상은 Demo.rar)


IWebMvc Milestone 3 released

By Jose Noheda

I've been working hard to polish a lot of aspects of IWebMvc for this milestone 3 and finally today I've finished. The result is a much more mature product that starts to resemble a usable framework. Nonetheless, I had time to add new features as well, some of them really important!

Let's review some of them:
  • Security
    IWebMvc now supports Spring security 2.0 based authentication and authorization using the new security namespace possibilities.
    • Spring Security 2.0 RC1
      The new version of Acegi is fully configured. Declarative security enabled.
    • Database realm
      Users / Roles are persisted in DB as any other entity.
    • User Administration
      CRUD operations to add / edit users, assign permissions and toggle (enable/disable) them are provided out-of-the-box.
    • Login / log off widget
      Working and easily integrated form based authentication. Default user/password combination is iwebmvc/iwebmvc (change it in iwebmvc.properties file)
    • Captcha widget
      AJAX validated captcha to enable human detection.
    • Remember me
      The framework will auto-login a user if so desires and will store authentication info using cookies.
  • Preliminary documentation
    A long standing due. A good percentage of the client interface is documented using the demo application.
  • Widgets
    • I18n Text
      A user can attempt to automatically translate texts into any of the supported languages using the Google AJAX Translation API
    • Tree (Hierarchy) widget
      New in this version, a user can build a tree of generic nodes and modify it as wished.
    • Grid (Table) widget
      The new grid supports a contextual menu, filtering (in addition to paging and ordering), inline edition of cell data (with AJAX storage management), cell content view (for data that exceeds column width) and auto width/height
    • Form widget
      Allows to check required fields before submitting and sending complete forms using JSON.
    • Other widgets
      Everything has been revamped a little or a lot.
  • Miscellaneous
    • YUI compression
      All JS is minified before sent (in addition to GZIP). This isn't activated by default in development environments.
    • Audit
      All create / update / delete operations are transparently audited (user, operation type, date/time, affected record, ...)
    • RSS feeds
      A generic framework to obtain RSS feeds of any entity has been developed. Example feeds have been created for audit operations.
    • DWR custom converters
      Working with JPA entities in JS is easier with the UUID and the Class converters.
    • IE7/Opera support
      A lot of work has been invested in making IWebMvc compatible with other browsers. IE7 is fully compatible with this release (though this bug in dojo affects any page that contains an Editor). Opera support is preliminary but a good chunk of the code is working.
    • Upgraded libraries
      In particular, to dojo 1.1 final but Spring, Hibernate and many others as well. Important: Netbeans project files have been migrated to v6.1beta to get rid of some absolute paths and facilitate project sharing (and include sources and ...). I've just tested this release with Netbeans/Glassfish & Ant/Jetty (though Eclipse/tomcat should still work fine).
And dozens of bug fixes and other issues. All in all, a decent work! Remember that you can download it from the repository. Or save time by watching the (trimmed) screencast (you may need this codec). Enjoy it!

출처 :  http://internna.blogspot.com/2008/04/iwebmvc-milestone-3-released.html
Posted by 1010
98..Etc/Etc...2008. 7. 24. 13:39
반응형

이거 한번 돌려 보자.

1. JDK 5.x 이상 버젼에서 돌아간다.
    ( 기본환경은 JDK5.x이상 + Ant1.7.x이상 + Eclipse3.3이상의 환경이다. )
   1.1 대충 눈치껏 설치한다.

2. MySql-5.x이상 다운받아 설치한다.
   2.1 다운 받는다.(나는 인스톨버젼이 아닌 압축버젼을 받았다.)
   2.2 적당한 디렉토리에 압축을 풀고 mysql-nt.exe를 실행시킨다.
   2.3 Dos Command 창에서 해당 디렉토리로 이동한다.
   2.4 mysql -uroot mysql 명령으로 접속후 create database iwebmvc; 명령으로 DB를 생성한다.
   2.5 mysql은 여전히 기동시켜 둔다.

사용자 삽입 이미지

3. ivy를 설치하고 테스트 한다.
   3.1 Apache ivy를 다운로드 한다.(현재 2.0.0 Beta2 이다)
   3.2 적당한 디렉토리에 압축을 풀면 jar파일이 두개 있다. 그걸 Ant의 lib 폴더에 복사한다.
   3.3 Dos Command 창에서 ivy 디렉토리로 이동한다.
   3.4 의 ivy 디렉토리에서 src\example\hello-ivy로 이동한후 ant 를 실행한다.
   3.5 Build가 성공하면 된다.
사용자 삽입 이미지

4. IWebMvc 다운로드 페이지에서 다운로드 받는다.
   4.1 IWebMvc에서 IWebMvc - Milestone 3.zip 을 다운로드 한다.
      (SVN도 제공한다. http://internna.googlecode.com/svn/trunk/IWebMvc)
   4.2 적당한 디렉토리에 압축을 푼다.
   4.3  iwebmvc.properties를 찾아서 mysql설정을 확인한다.(WEB-INF폴더에 있다.)

5. ant 빌드를 한다.
   5.1  Dos Command 창에서 IWebMvc 디렉토리로 이동한다.
   5.2 run.bat를 실행한다. (각종 jar파일을 다운받기 때문에 시간이 걸린다.)
   5.3 에러없이 빌드가 성공되면 정상이다.
       (최종 빌드에서 에러가 나더라도 ivy에서 jar파일 다운로드까지 성공하면 된다.)
사용자 삽입 이미지

6. Eclipse 프로젝트로 import한다.
   6.1 해당 디렉토리를 찾아 import 시킨다.
   6.2 라이브러리 경로가 안맞는다.(소스관리는 징하게 못한다.-_-;;; 좀좀.. 잘 정리하면 안되나?)
        - 신기하게 Unit Test 파일이 없다.(제거하고 배포한건지...)
   6.3 수동으로 찾아서 관련된 *.jar파일을 찾아서 연결하여 오류를 제거한다.
사용자 삽입 이미지

7. Eclipse 내부 Tomcat으로 'Run as'를 실행한다.
   7.1 Run as를 실행한다.
   7.2 만약 DB가 오라클이라면 안된다. (왜? 테이블생성 스크립트가 기본으로 Mysql이다. ㅡㅡ; )
   7.3 DB Table생성까지 성공적으로 되었다면 Tomcat이 정상적으로 올라온다.

8. 해당 사이트를 확인 한다.
   8.1 avi 동영상을 미리 봤다면 알겠지만 해당 화면이 나타난다.
사용자 삽입 이미지

9. CRUD 소개 동영상으로 따라 해본다.
   9.1 두개의 동영상이 있다 각각 다운받아 따라해 보자.
        Link : http://code.google.com/p/internna/downloads/list
Posted by 1010
98..Etc/Etc...2008. 7. 24. 13:22
반응형

원격 데스크탑에서 Ctrl+Alt+Del키를 쓸 일이 있다면 del키 대신 end를 누르면 된다.

Posted by 1010
61.Linux2008. 7. 24. 13:21
반응형

[시큐리티 팁!팁!팁!] OpenVPN을 이용한 VPN 구현

 

VPN의 종류와 필요성에 대해서는 많은 이들이 숙지하고 있다. 하지만 비용이나 불편함 때문에 실제 도입을 꺼려지는 경우가 상당수에 이르는데, 이는 오픈소스로 개발돼 배포중인 OpenVPN이라는 프로그램을 통해 극복할 수 있다. VPN 도입의 가장 큰 걸림돌이었던 비용 문제를 해결하면서 고성능의 VPN을 구현할 수 있도록 지원하는 OpenVPN의 특징에 대해 알아보자.

VPN의 종류와 필요성에 대해서는 많은 이들이 숙지하고 있다. 하지만 비용이나 불편함 때문에 실제 도입을 꺼려지는 경우가 상당수에 이르는데, 이는 오픈소스로 개발돼 배포중인 OpenVPN이라는 프로그램을 통해 극복할 수 있다. VPN 도입의 가장 큰 걸림돌이었던 비용 문제를 해결하면서 고성능의 VPN을 구현할 수 있도록 지원하는 OpenVPN의 특징에 대해 알아보자.

 

- OpenVPN은 하나의 UDP 포트를 통해 모든 트래픽을 터널링할 수 있다. 즉 웹 접속(HTTP)을 하거나 DNS 질의를 할 때(UDP/53), ping(ICMP)을 날려도 중간에 패킷을 캡처하면 500/UDP를 통해 전송되는 것처럼 보이게 한다.


- 안전한 VPN 통신을 위해 별도의 모듈이 필요없이 널리 사용하고 있는 OpenSSL에서 지원하는 강력한 암호화와 인증 기능 등을 그대로 이용할 수 있다.


- OpenVPN은 시스템 내에서 별도의 데몬 형태로 작동하기 때문에 IPsec 기반의 VPN 프로그램처럼 복잡한 커널 패치나 커널 모듈이 필요하지 않으며, 설치 방법도 간단하다.


- 모든 패킷이 VPN을 통해 터널링되고 압축 혹은 암호화됨에도 불구하고 시스템에 부하를 유발하지 않으며, 속도도 빠르다.

 

이외에도 OpenVPN은 많은 특징과 확장 가능성을 가지고 있다. 더 자세한 내용은 홈페이지(http://openvpn.net/)를 참고하기 바란다.


지금부터는 OpenVPN을 이용해 (그림 1)처럼 전자우편이나 웹 서버 등의 용도로 많이 사용되는 리눅스 서버와 윈도우 PC 간에 VPN을 연동해 안전한 네트워크를 구성하는 사례를 살펴보자.



 

(그림 1)처럼 IDC 등의 전산 센터에 있는 서버에 VPN 데몬을, PC에 VPN 클라이언트 프로그램을 설치한다. 그 뒤 VPN 서버에 접속해 인증을 받으면, VPN 서버로부터 별도의 VPN용 IP를 할당받아 VPN 터널을 통해 접속할 수 있다.


물론 이때의 서버 접속은 인터넷은 물론 VPN 터널을 통해서도 가능하다.

 

 

·VPN 서버 설치와 설정


먼저 서버에서 VPN 데몬을 설정하자. OpenVPN에서는 TUN이나 TAP이라는 별도의 가상 인터페이스로 VPN 통신을 하므로, 우선 커널에서 이 드라이버를 지원하도록 다음과 같이 설정한 뒤 커널을 컴파일해야 한다.

 

[*]   Universal TUN/TAP device driver support

 

이후 디바이스를 설정하기 위해 다음의 명령어를 실행하는데, 이미 설정돼 있는 경우가 대부분이다.

 

# mkdir /dev/net
# mknod /dev/net/tun c 10 200
                         
다음으로 OpenVPN을 설치하기 전에 OpenSSL과 LZO라는 두 프로그램을 먼저 설치한다. 이들 프로그램은 VPN 이용 시, 패킷을 암호화하고 압축해 전송할 때 필요한 모듈로, 다음 사이트에서 다운로드해 설치하면 된다.
 
* OpenSSL :
http://www.openssl.org/
* LZO      :
http://www.oberhumer.com/opensource/lzo/

 

프로그램 설치가 끝났으면 OpenVPN 홈페이지에서 소스를 다운로드해 './configure ; make; make install'로 설치하면 된다. VPN 클라이언트와 서버 간 인증을 위해서는 인증서가 필요하므로 먼저 서버에서 인증서를 생성한다. 인증서를 생성할 때나 사인을 할 때는 OpenSSL을 이용하므로 미리 설치돼 있어야 한다.


먼저 Root CA 인증서와 비밀키를 생성해야 하는데, 다음 명령어를 실행하면 1년 동안 유효한 CA와 비밀키(개인키)를 생성할 수 있다.

 

# openssl req -nodes -new -x509 -keyout my-ca.key -out my-ca.crt -days 365

 

다음은 클라이언트와 서버에서 사용할 키를 각각 생성한다.

 

# openssl req -nodes -new -keyout client.key -out client.csr
# openssl req -nodes -new -keyout server.key -out server.csr

 

Root CA를 이용해 서버와 클라이언트 인증서에 각각 사인한다. 

 

# openssl ca -out server.crt -in server.csr
# openssl ca -out client.crt -in client.csr

 

다음으로 서버에서 암호화 협상 시 필요한 Diffe Hellman 파라미터를 생성한다.

 

# openssl dhparam -out dh1024.pem 1024


이제 나머지는 서버에 그대로 두고, client.crt와 client.key 그리고 my-ca.key 파일을 클라이언트 PC의 적당한 디렉토리로 복사하면 된다. 이제 서버의 설정 파일을 살펴보자.

 

[서버 설정 파일 - openvpn.conf]

 

port 500 : OpenVPN은 기본적으로 UDP를 이용해 패킷을 터널링해 전달하는데, 이때 포트는 사용되지 않은 어떤 포트를 사용해도 관계없다.

 

proto udp : 기본 값인 UDP를 사용하는 것이 좋다. TCP는 권장하지 않는다.

 

dev tap : OpenVPN 서버와 클라이언트 상호 통신에 필요한 인터페이스를 지정하는데, TUN이나 TAP을 지정할 수 있다.

 

ifconfig 10.105.11.1 255.255.0.0 : VPN 서버가 사용할 IP를 지정한다. TAP에 이 IP가 할당돼 원격지 PC와  통신할 수 있게 되는데, 가급적 사용하지 않는 사설 IP를 사용하는 것이 좋다.

 

keepalive 10 120 : 클라이언트와 서버 간에 VPN 연동이 활성화됐는지 체크하기 위해 사용되는데, 매 10초마다 ping을 발송해 120초 동안 응답이 없으면 원격지의 네트워크가 다운된 것으로 파악한다는 의미다.

 

comp-lzo : 압축 알고리즘을 사용하도록 한다. 서버에 이 같이 설정했다면, 클라이언트에도 동일하게 설정하도록 한다.

 

persist-key
persist-tun
user nobody          
group nobody   
: 초기화된 후에 OpenVPN 데몬이 nobody 권한으로 작동하도록 한다. 

 

status       openvpn-status.log
log          openvpn.log              
log-append  openvpn.log
: OpenVPN의 로그를 생성하는 설정이다.

 

tls-server : SSL 키 교환 시에 서버 역할을 하므로 tls-server로 지정한다.

 

dh  dh1024.pem
ca  my-ca.crt             
cert  server.crt                  
key server.key
:  CA 파일이나 인증서의 공개키 혹은 비밀키를 지정한다.

 

이후 서버에서 --mode server를 추가해 다음과 같이 실행하면 앞에서 지정한 포트로 데몬이 작동하는 것을 확인할 수 있다.

 

# openvpn --config /etc/server.conf --daemon --mode server



·VPN 클라이언트 설치와 설정


다음으로는 윈도우 PC의 클라이언트 프로그램 설정에 관한 내용을 살펴보자. 윈도우 클라이언트 프로그램으로는 OpenVPN GUI라는 프로그램이 많이 사용되는데, 웹 사이트(
http://openvpn.se/)에서 다운로드해 설치하면 된다. 설치 이후 '시작->프로그램->OpenVPN'을 선택하면 다음과 같은 메뉴가 보이는데, 여기에서 OpenVPN GUI를 실행하면 된다. 이후 우측의 트레이에 생긴 아이콘에 오른쪽 마우스를 클릭하면 사용 가능한 메뉴가 나오는데, 여기에서 Edit Config를 선택하면 메모장이 뜨면서 설정작업을 진행할 수 있다. 서버 설정과 크게 다르지 않으므로 쉽게 이해될 것이다.
                 

(화면 1) OpenVPN 메뉴

 

[클라이언트 설정 파일 - config.ovpn 파일]

 

remote 220.11.xx.xx : VPN 데몬이 설치돼 있는 서버의 IP를 설정한다.

 

port 500 : VPN 서버와 통신할 포트를 지정해야 하는데, 서버에서 지정된 포트와 동일한 포트를 설정한다.

 

proto udp : 역시 기본 값인 UDP를 사용하도록 한다.

 

dev tap : 앞의 서버와 동일하게 설정한다.

 

ifconfig 10.105.11.3 255.255.0.0 : VPN 클라이언트 PC에 할당할 IP를 지정한다.

 

ping 10
verb 4       
: 상호간에 망이 살아있는지 확인하기 위해 매 10초마다 ping을 발송한다. 로그 수준은 4로 지정한다.
 
comp-lzo : 서버에서 지정한대로 압축 알고리즘을 지정한다.

 

tls-client : SSL을 통한 클라이언트 역할을 하므로 tls-client라고 정의한다.
 
ca my-ca.crt
cert client.crt         
key client.key
: 서버에서 살펴본 바와 같이 CA와 클라이언트 키를 지정한다. 나머지는 앞에서 살펴본 내용과 동일하다.

 

설정이 끝난 후 PC에서 OpenVPN GUI를 실행하면 (화면 2, 3과) 같이 서버와 클라이언트 간에 VPN 연동이 되는 것을 알 수 있다. 

(화면 2)OpenVPN GUI를 통해 연결된 화면

 

(화면 3)VPN 연결 후 IP 할당 화면

 

설정이 끝나면 VPN에서 지정된 IP를 할당받게 되고, 비공인 VPN IP로 접속하면 VPN을 통해 안전하게 터널링돼 접속하게 된다. 이때의 VPN 트래픽은 암호화되고 터널링되므로 누군가가 중간에서 가로챘다 하더라도 패킷 내용을 해석할 수 없으므로 스니핑이 불가능하다. 한편, 패킷을 터널링하는 과정으로 인해 다소 속도가 저하될 수 있으나 거의 인지할 수 없는 수준이다.


VPN을 이용하면 패킷을 암호화하는 것뿐만 아니라 파이어월을 사용할 때도 매우 편리하다. 외국  출장 등을 이유로 외부에서 접속하더라도 VPN을 통하면 항시 고정된 IP를 사용할 수 있기 때문이다. 따라서 파이어월에서는 접속을 허용해야 할 사용자가 유동 IP를 사용하더라도 단 한 개의 UDP 포트만 허용하면 되기 때문에 보안과 편리함 모두를 만족시킬 수 있다.
지금까지 단순하면서도 가장 많이 사용하는 구조에서의 VPN 활용 방법에 대해 살펴봤다. VPN은 이외의 다양한 환경에서도 응용이 가능하므로 홈페이지를 통해 자세한 내용을 참고하기 바란다.

 

작성자 : 홍석범 | 오늘과 내일 차장

작성일 : 2006년 7월호

 

 

원   문 : http://www.ionthenet.co.kr/newspaper/view.php?idx=11247

Posted by 1010