Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
Articles
Articles_ko
CreateActions_ko
CreateDAOiBATIS_ko
CreateManager_ko
LeftMenu




JSPWiki v2.2.33

[RSS]


Hide Menu

CreateDAO_ko


Difference between version 4 and version 1:

At line 1 changed 1 line.
__Part I:__ [AppFuse에서 새로운 DAO들과 Object들을 작성하기|CreateDAO] - table을 나타내는 Java Object와 이 Object들을 데이타 베이스에 저장 시키는 Java 클래스들을 만드는 방법.
__Part I:__ [AppFuse에서 새로운 DAO들과 Object들을 작성하기|CreateDAO_ko] - table을 나타내는 Java Object와 이 Object들을 데이타 베이스에 저장 시키는 Java 클래스들을 만드는 방법.
At line 4 changed 1 line.
이 튜토리얼에서는 데이타베이스에 새로운 테이블을 만드는 방법과 그 테이블에 접근하는 자바 코드를 작성하는 방법을 알려줍니다.
이 튜토리얼에서는 데이타베이스에 새로운 테이블을 만드는 방법과 그 테이블에 접근하는 자바 코드를 작성하는 방법을 알려줍니다.
At line 6 changed 1 line.
우리는 어떤 객체와 그 객체를 데이타베이스에 __persist (save/retrieve/delete)__ 하기 위한 몇가지 클래스들을 만들것입니다. 자바에서는 이 객체를 __Plain Old Java Object__ (a.k.a. a [POJO|http://forum.java.sun.com/thread.jsp?forum=92&thread=425300&tstart=0&trange=15]) 라고 부릅니다. 이 객체는 기본적으로 데이타베이스 테이블을 표현합니다.
우리는 어떤 객체와 그 객체를 데이타베이스에 __persist (save/retrieve/delete)__ 하기 위한 몇가지 클래스들을 만들것입니다. 자바에서는 이 객체를 __Plain Old Java Object__ (a.k.a. a [POJO|http://forum.java.sun.com/thread.jsp?forum=92&thread=425300&tstart=0&trange=15]) 라고 부릅니다. 이 객체는 기본적으로 데이타베이스 테이블을 표현합니다.
At line 8 changed 1 line.
우리가 만들 몇가지 클래스들은 다음과 같습니다:
우리가 만들 몇가지 클래스들은 다음과 같습니다:
At line 10 changed 2 lines.
* Data Access Object (a.k.a. a [DAO|http://java.sun.com/blueprints/patterns/DAO.html]) [Interface|http://java.sun.com/docs/books/tutorial/java/concepts/interface.html] 와 그 Interface의 Hibernate 구현
* DAO 를 테스트 하기 위한 [JUnit|http://www.junit.org] class
* Data Access Object (a.k.a. a [DAO|http://java.sun.com/blueprints/patterns/DAO.html]) [Interface|http://java.sun.com/docs/books/tutorial/java/concepts/interface.html] 와 그 Interface의 Hibernate 구현
* DAO 를 테스트 하기 위한 [JUnit|http://www.junit.org] class
At line 14 changed 1 line.
<b>NOTE:</b> &#47564;&#50557; &#45817;&#49888;&#51060; MySQL&#51012; &#49324;&#50857;&#54616;&#47732;&#49436; &#53944;&#47004;&#51229;&#49496; &#52376;&#47532;&#47484; &#50896;&#54620;&#45796;&#47732; &#48152;&#46300;&#49884; InnoDB &#53580;&#51060;&#48660;&#51012; &#49324;&#50857;&#54616;&#50668;&#50556; &#54633;&#45768;&#45796;. InnoDB&#47484; &#49324;&#50857; &#54616;&#47140;&#47732; mysql &#49444;&#51221; &#54028;&#51068;(/etc/my.cnf or c:\Windows\my.ini)&#50640; &#45796;&#51020;&#44284; &#44057;&#51008; &#46972;&#51064;&#51012; &#52628;&#44032;&#54633;&#45768;&#45796;. &#46160;&#48264;&#51704; &#49444;&#51221;(UTF-8 character set) &#51008; mysql 4.1.7+ &#48260;&#51260;&#50640;&#49436; &#54596;&#50836;&#54620; &#44163;&#51077;&#45768;&#45796;.
<b>NOTE:</b> 만약 당신이 MySQL을 사용하면서 트랜젝션 처리를 원한다면 반드시 InnoDB 테이블을 사용하여야 합니다. InnoDB를 사용 하려면 mysql 설정 파일(/etc/my.cnf or c:\Windows\my.ini)에 다음과 같은 라인을 추가합니다. 두번째 설정(UTF-8 character set) 은 mysql 4.1.7+ 버젼에서 필요한 것입니다.
At line 20 changed 1 line.
&#47564;&#50557; PostgreSQL &#46356;&#48708;&#47484; &#49324;&#50857;&#54616;&#47732;&#49436; batch processing &#50640; &#44288;&#47144;&#46108; &#50640;&#47084;&#44032; &#45208;&#44172; &#46104;&#47732; src/dao/**/hibernate/applicationContext-hibernate.xml &#54028;&#51068;&#50640; <tt>&lt;prop key="hibernate.jdbc.batch_size">0&lt;/prop></tt> &#46972;&#51064;&#51012; &#52628;&#44032;&#54644;&#49436; batch processing&#44592;&#45733;&#51012; &#45124;&#46020;&#47197; &#54633;&#45768;&#45796;.</div>
만약 PostgreSQL 디비를 사용하면서 batch processing 에 관련된 에러가 나게 되면 src/dao/**/hibernate/applicationContext-hibernate.xml 파일에 <tt>&lt;prop key="hibernate.jdbc.batch_size">0&lt;/prop></tt> 라인을 추가해서 batch processing기능을 끄도록 합니다.</div>
At line 22 changed 1 line.
AppFuse &#45716; persistence layer &#47196; [Hibernate|http://www.hibernate.org] &#47484; &#49324;&#50857; &#54633;&#45768;&#45796;. Hibernate &#45716; &#51088;&#48148; &#44061;&#52404;&#50752; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51012; &#44288;&#47144;&#51667;&#44172; &#54616;&#45716; __Object/Relational (O/R) Framework__ &#47196;&#50024; &#51088;&#48148; &#44061;&#52404;&#50640; __CRUD (Create, Retrieve, Update, Delete)__ &#44592;&#45733;&#51012; &#47588;&#50864; &#49789;&#44172; &#45796;&#47336;&#44172; &#54633;&#45768;&#45796;.
AppFuse 는 persistence layer 로 [Hibernate|http://www.hibernate.org] 를 사용 합니다. Hibernate 는 자바 객체와 데이타베이스 테이블을 관련짓게 하는 __Object/Relational (O/R) Framework__ 로써 자바 객체에 __CRUD (Create, Retrieve, Update, Delete)__ 기능을 매우 쉽게 다루게 합니다.
At line 24 changed 1 line.
&#51088; &#44536;&#47100; Object, DAO &#44536;&#47532;&#44256; Test &#47484; &#51089;&#49457;&#54644; &#48389;&#49884;&#45796;.
자 그럼 Object, DAO 그리고 Test 를 작성해 봅시다.
At line 26 changed 7 lines.
!&#47785;&#52264;
* [1] Object &#47484; &#47564;&#46308;&#44256; [XDoclet|http://xdoclet.sf.net] &#53468;&#44536;&#47484; &#52628;&#44032;&#54633;&#45768;&#45796;.
* [2] Ant &#47484; &#51060;&#50857;&#54616;&#50668; Object &#47196; &#48512;&#53552; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51012; &#47564;&#46317;&#45768;&#45796;.
* [3] JUnit &#51004;&#47196; DAO &#47484; &#53580;&#49828;&#53944; &#54616;&#44592;&#50948;&#54644; DaoTest &#53364;&#47000;&#49828;&#47484; &#47564;&#46317;&#45768;&#45796;.
* [4] Object &#51032; CRUD &#52376;&#47532;&#47484; &#50948;&#54620; DAO &#53364;&#47000;&#49828;&#47484; &#47564;&#46317;&#45768;&#45796;.
* [5] Person object&#50752; PersonDao&#47484; Spring &#54532;&#47112;&#51076;&#50892;&#53356;&#50640; &#50508;&#47532;&#44592; &#50948;&#54644; &#49444;&#51221;&#54028;&#51068;&#51012; &#44396;&#49457;&#54633;&#45768;&#45796;.
* [6] DaoTest &#47484; &#49892;&#54665;&#49884;&#54633;&#45768;&#45796;.
!목차
* [1] Object 를 만들고 [XDoclet|http://xdoclet.sf.net] 태그를 추가합니다.
* [2] Ant 를 이용하여 Object 로 부터 데이타베이스 테이블을 만듭니다.
* [3] JUnit 으로 DAO 를 테스트 하기위해 DaoTest 클래스를 만듭니다.
* [4] Object 의 CRUD 처리를 위한 DAO 클래스를 만듭니다.
* [5] Person object와 PersonDao를 Spring 프레임워크에 알리기 위해 설정파일을 구성합니다.
* [6] DaoTest 를 실행시합니다.
At line 34 changed 3 lines.
!!Object &#47484; &#47564;&#46308;&#44256; XDoclet &#53468;&#44536;&#47484; &#52628;&#44032;&#54633;&#45768;&#45796; [#1]
&#47676;&#51200; persist &#54624; object &#47484; &#51089;&#49457;&#54633;&#45768;&#45796;. \\
id &#50752; firstName &#44536;&#47532;&#44256; lastName &#49549;&#49457;&#51012; &#44032;&#51648;&#44256; &#51080;&#45716; &#44036;&#45800;&#54620; "Person" &#44061;&#52404;&#47484; &#51089;&#49457;&#54633;&#45768;&#45796;.(in the src/dao/**/model directory)
!!Object 를 만들고 XDoclet 태그를 추가합니다 [#1]
먼저 persist 할 object 를 작성합니다. \\
id 와 firstName 그리고 lastName 속성을 가지고 있는 간단한 "Person" 객체를 작성합니다.(in the src/dao/**/model directory)
At line 55 changed 4 lines.
&#51060; &#53364;&#47000;&#49828;&#45716; 3&#44060;&#51032; abstract method (equals(), hashCode() and toString())&#47484; &#44032;&#51648;&#44256; &#51080;&#45716; [BaseObject|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/model/BaseObject.java.html] &#47484; &#49345;&#49549; &#48155;&#50520;&#44256; &#51060;&#44163;&#51008; Person class&#50640;&#49436; &#48152;&#46300;&#49884; &#44396;&#54788; &#46104;&#50612;&#51256;&#50556; &#54633;&#45768;&#45796;.\\
&#51060;&#51473; &#46160; &#47700;&#49548;&#46300;(equals(), hashCode())&#45716; &#54616;&#51060;&#48260;&#45348;&#51060;&#53944;&#50640; &#51032;&#54644; &#50836;&#44396;&#46104;&#50612;&#51648;&#45716; &#47700;&#49548;&#46300; &#51077;&#45768;&#45796;.\\
&#51060; &#47700;&#49548;&#46300;&#46308;&#51012; &#52628;&#44032; &#54616;&#45716; &#44032;&#51109; &#49772;&#50868; &#48169;&#48277;&#51008; [Commonclipse|http://commonclipse.sourceforge.net/] &#47484; &#49324;&#50857;&#54616;&#45716; &#44163;&#51077;&#45768;&#45796;. &#51060; &#53812;&#51032; &#49324;&#50857;&#48277;&#51008; [Lee Grey's site|http://www.leegrey.com/hmm/2004/09/29/1096491256000.html] &#50640;&#49436; &#52286;&#50500;&#48380; &#49688; &#51080;&#49845;&#45768;&#45796;.\\
&#45796;&#47480; &#51060;&#53364;&#47549;&#49828; &#54540;&#47084;&#44536;&#51064;&#51004;&#47196;&#45716; [Commons4E|http://www.jiayun.org/mediawiki/index.php?title=Commons4E] &#44032; &#51080;&#49845;&#45768;&#45796;.\\
이 클래스는 3개의 abstract method (equals(), hashCode() and toString())를 가지고 있는 [BaseObject|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/model/BaseObject.java.html] 를 상속 받았고 이것은 Person class에서 반드시 구현 되어져야 합니다.\\
이중 두 메소드(equals(), hashCode())는 하이버네이트에 의해 요구되어지는 메소드 입니다.\\
이 메소드들을 추가 하는 가장 쉬운 방법은 [Commonclipse|http://commonclipse.sourceforge.net/] 를 사용하는 것입니다. 이 툴의 사용법은 [Lee Grey's site|http://www.leegrey.com/hmm/2004/09/29/1096491256000.html] 에서 찾아볼 수 있습니다.\\
다른 이클립스 플러그인으로는 [Commons4E|http://www.jiayun.org/mediawiki/index.php?title=Commons4E] 가 있습니다.\\
At line 61 changed 1 line.
<dt></dt><dd><i>&#47564;&#50557; [IntelliJ IDEA|http://www.jetbrains.com/idea]&#47484; &#49324;&#50857; &#54620;&#45796;&#47732; equals() &#44284; hashCode() &#47700;&#49548;&#46300;&#45716; &#47564;&#46308;&#50612; &#45244; &#49688; &#51080;&#51648;&#47564; toString() &#51008; &#44592;&#48376;&#51201;&#51004;&#47196; &#51228;&#44277;&#46104;&#51648; &#50506;&#51004;&#48064;&#47196; [ToStringPlugin|http://www.intellij.org/twiki/bin/view/Main/ToStringPlugin] &#51012; &#49324;&#50857; &#54616;&#49884;&#47732; &#46112;&#44161;&#45768;&#45796;. &#51204; &#44060;&#51064;&#51201;&#51004;&#47196; &#51060; &#54540;&#47084;&#44536;&#51064;&#51012; &#49324;&#50857;&#54644; &#48372;&#51648;&#45716; &#50506;&#50520;&#49845;&#45768;&#45796;.</i></dd>
<dt></dt><dd><i>만약 [IntelliJ IDEA|http://www.jetbrains.com/idea]를 사용 한다면 equals() 과 hashCode() 메소드는 만들어 낼 수 있지만 toString() 은 기본적으로 제공되지 않으므로 [ToStringPlugin|http://www.intellij.org/twiki/bin/view/Main/ToStringPlugin] 을 사용 하시면 될겁니다. 전 개인적으로 이 플러그인을 사용해 보지는 않았습니다.</i></dd>
At line 64 changed 2 lines.
&#51060;&#51228; &#50864;&#47532;&#44032; &#47564;&#46304; POJO &#53364;&#47000;&#49828;&#50640; &#45824;&#54620; Hibernate &#47605;&#54609; &#54028;&#51068;&#51012; &#47564;&#46308;&#44592; &#50948;&#54644; XDoclet &#53468;&#44536;&#47484; &#52628;&#44032;&#54633;&#45768;&#45796;.\\
&#51060; &#47605;&#54609; &#54028;&#51068;&#51008; Hibernate &#44032; objects &rarr; tables &#44536;&#47532;&#44256; properties (variables) &rarr; columns &#51012; &#47605;&#54609;&#54616;&#44592; &#50948;&#54644; &#49324;&#50857; &#46121;&#45768;&#45796;.
이제 우리가 만든 POJO 클래스에 대한 Hibernate 맵핑 파일을 만들기 위해 XDoclet 태그를 추가합니다.\\
이 맵핑 파일은 Hibernate 가 objects &rarr; tables 그리고 properties (variables) &rarr; columns 을 맵핑하기 위해 사용 됩니다.
At line 67 changed 1 line.
&#52395;&#51704;&#47196;, Hibernate &#50640;&#44172; &#51060; object &#50752; &#44288;&#47144;&#46108; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51060; &#47924;&#50631;&#51064;&#51648; &#50508;&#47140;&#51452;&#44592; &#50948;&#54616;&#50668; [@hibernate.class|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.class%20(0..1)] &#53468;&#44536;&#47484; &#52628;&#44032;&#54633;&#45768;&#45796;:
첫째로, Hibernate 에게 이 object 와 관련된 데이타베이스 테이블이 무엇인지 알려주기 위하여 [@hibernate.class|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.class%20(0..1)] 태그를 추가합니다:
At line 77 changed 2 lines.
&#45796;&#51020;&#51004;&#47196; primary key &#47605;&#54609; &#53468;&#44536;&#47484; &#52628;&#44032;&#54644;&#54633;&#45768;&#45796;.
&#47784;&#46304; @hibernate.* &#53468;&#44536;&#45716; &#48152;&#46300;&#49884; POJO &#53364;&#47000;&#49828;&#51032; __getters'__ Javadoc &#50640; &#51201;&#50612;&#50556; &#54620;&#45796;&#45716;&#44152; &#44592;&#50613;&#54616;&#49464;&#50836;
다음으로 primary key 맵핑 태그를 추가해합니다.
모든 @hibernate.* 태그는 반드시 POJO 클래스의 __getters'__ Javadoc 에 적어야 한다는걸 기억하세요
At line 93 changed 1 line.
;:<font color="blue">''&#45796;&#47480; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828;&#50640;&#49436; "native"&#47484; &#49324;&#50857;&#54624;&#46412;&#51032; [&#47928;&#51228;&#46308;|http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseOnDB2] &#46412;&#47928;&#50640; &#45208;&#45716; generate-class="native" &#45824;&#49888; generator-class="increment" &#47484; &#49324;&#50857;&#54664;&#49845;&#45768;&#45796;. &#47564;&#50557; &#45817;&#49888;&#51060; &#50724;&#51649; MySQL &#47564;&#51012; &#49324;&#50857;&#54620;&#45796;&#47732; "native" &#47484; &#49324;&#50857;&#54624; &#44163;&#51012; &#44428;&#51109;&#54633;&#45768;&#45796;. &#51060; &#53916;&#53664;&#47532;&#50620;&#50640;&#49436;&#45716; increment &#47484; &#49324;&#50857;&#54633;&#45768;&#45796;.''</font>
;:<font color="blue">''다른 데이타베이스에서 "native"를 사용할때의 [문제들|http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseOnDB2] 때문에 나는 generate-class="native" 대신 generator-class="increment" 를 사용했습니다. 만약 당신이 오직 MySQL 만을 사용한다면 "native" 를 사용할 것을 권장합니다. 이 튜토리얼에서는 increment 를 사용합니다.''</font>
At line 95 changed 4 lines.
!!Ant &#47484; &#51060;&#50857;&#54616;&#50668; Object &#47196; &#48512;&#53552; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51012; &#47564;&#46317;&#45768;&#45796; [#2]
&#51060;&#51228; &#53080;&#49556;&#50640;&#49436; "ant setup-db" &#47484; &#49892;&#54665;&#54644;&#49436; person &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51012; &#47564;&#46308; &#49688; &#51080;&#49845;&#45768;&#45796;.
"ant setup-db" &#53468;&#49828;&#53356;&#45716; Person.hbm.xml &#54028;&#51068;&#44284; "person." &#53580;&#51060;&#48660;&#51012; &#47564;&#46317;&#45768;&#45796;.
&#53468;&#49828;&#53356;&#47484; &#49892;&#54665; &#49884;&#53428;&#51004;&#47196;&#50024; Hibernate &#44032; &#47564;&#46300;&#45716; &#53580;&#51060;&#48660; &#49828;&#53412;&#47560;&#47484; &#48380; &#49688; &#51080;&#49845;&#45768;&#45796;:
!!Ant 를 이용하여 Object 로 부터 데이타베이스 테이블을 만듭니다 [#2]
이제 콘솔에서 "ant setup-db" 를 실행해서 person 데이타베이스 테이블을 만들 수 있습니다.
"ant setup-db" 태스크는 Person.hbm.xml 파일과 "person." 테이블을 만듭니다.
태스크를 실행 시킴으로써 Hibernate 가 만드는 테이블 스키마를 볼 수 있습니다:
At line 107 changed 2 lines.
&#47564;&#50557; Hibernate &#44032; &#47564;&#46308;&#50612;&#51456; Person.hbm.xml &#54028;&#51068;&#51012; &#48372;&#44256; &#49910;&#45796;&#47732; build/dao/gen/**/model &#46356;&#47113;&#53664;&#47532;&#47484; &#48372;&#49901;&#49884;&#50724;
&#50668;&#44592; Person.hbm.xml&#51032; &#45236;&#50857;&#51060; &#51080;&#49845;&#45768;&#45796;.
만약 Hibernate 가 만들어준 Person.hbm.xml 파일을 보고 싶다면 build/dao/gen/**/model 디렉토리를 보십시오
여기 Person.hbm.xml의 내용이 있습니다.
At line 147 changed 1 line.
&#51060;&#51228; &#45796;&#47480; columns (first_name, last_name) &#51012; &#50948;&#54620; &#52628;&#44032;&#51201;&#51064; [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] &#53468;&#44536;&#47484; &#51089;&#49457;&#54633;&#45768;&#45796;:
이제 다른 columns (first_name, last_name) 을 위한 추가적인 [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] 태그를 작성합니다:
At line 166 changed 3 lines.
&#50948; &#50696;&#51228;&#50640;&#49436; column &#49549;&#49457;&#51012; &#44592;&#49696;&#54620; &#51060;&#50976;&#45716; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#52972;&#47100; &#51060;&#47492;&#44284; POJO &#53364;&#47000;&#49828;&#51032; &#49549;&#49457; &#51060;&#47492;&#51060; &#45796;&#47476;&#44592; &#46412;&#47928;&#51077;&#45768;&#45796;.
&#47564;&#50557; &#44057;&#45796;&#47732; column &#49549;&#49457;&#51012; &#44592;&#49696;&#54624; &#54596;&#50836;&#44032; &#50630;&#49845;&#45768;&#45796;.\\
&#51060; &#50808;&#50640; &#51060; &#53468;&#44536;&#50640;&#49436; &#49324;&#50857;&#54624; &#49688; &#51080;&#45716; &#45796;&#47480; &#49549;&#49457;&#46308;&#50640; &#45824;&#54644; &#50508;&#44256; &#49910;&#51004;&#47732; [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] &#47484; &#52280;&#51312;&#54616;&#49464;&#50836;.
위 예제에서 column 속성을 기술한 이유는 데이타베이스 컬럼 이름과 POJO 클래스의 속성 이름이 다르기 때문입니다.
만약 같다면 column 속성을 기술할 필요가 없습니다.\\
이 외에 이 태그에서 사용할 수 있는 다른 속성들에 대해 알고 싶으면 [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] 를 참조하세요.
At line 170 changed 1 line.
&#49352;&#47196; &#47564;&#46304; &#49549;&#49457;&#46308;&#51012; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#51060;&#48660;&#51032; column &#51004;&#47196; &#52628;&#44032;&#54616;&#44592; &#50948;&#54616;&#50668; "ant setup-db" &#51012; &#45796;&#49884; &#49892;&#54665; &#54633;&#45768;&#45796;.
새로 만든 속성들을 데이타베이스 테이블의 column 으로 추가하기 위하여 "ant setup-db" 을 다시 실행 합니다.
At line 179 changed 1 line.
&#47564;&#50557; column &#51032; &#49324;&#51060;&#51592;&#47484; &#48148;&#44984;&#44256; &#49910;&#45796;&#47732; @hibernate.property &#53468;&#44536;&#50640; length="size" &#49549;&#49457;&#51012; &#44592;&#49696;&#54644; &#51452;&#47732; &#46121;&#45768;&#45796;. &#46608; &#54596;&#49688;&#54637;&#47785;(NOT NULL)&#51004;&#47196; &#49444;&#51221;&#54616;&#44256; &#49910;&#45796;&#47732; not-null="true" &#49549;&#49457;&#51012; &#44592;&#49696;&#54644; &#51452;&#47732; &#46121;&#45768;&#45796;.
만약 column 의 사이즈를 바꾸고 싶다면 @hibernate.property 태그에 length="size" 속성을 기술해 주면 됩니다. 또 필수항목(NOT NULL)으로 설정하고 싶다면 not-null="true" 속성을 기술해 주면 됩니다.
At line 181 changed 1 line.
!!JUnit &#51004;&#47196; DAO &#47484; &#53580;&#49828;&#53944; &#54616;&#44592;&#50948;&#54644; DaoTest &#53364;&#47000;&#49828;&#47484; &#47564;&#46317;&#45768;&#45796; [#3]
!!JUnit 으로 DAO 를 테스트 하기위해 DaoTest 클래스를 만듭니다 [#3]
At line 184 changed 2 lines.
&#51060; &#53916;&#53664;&#47532;&#50620;&#51032; &#45208;&#47672;&#51648; &#48512;&#48516;&#51032; &#47784;&#46304; &#53364;&#47000;&#49828;&#46308;&#51012; &#51088;&#46041;&#51004;&#47196; &#49373;&#49457;&#54644; &#51452;&#45716; __AppGen__ &#53812;&#51012; AppFuse &#48260;&#51260; 1.61 &#51032; &#51068;&#48512;&#47196; &#54252;&#54632; &#49884;&#53040;&#49845;&#45768;&#45796;.
&#51060; &#53812;&#51008; [Lance Lavandowska|https://appfuse.dev.java.net/issues/show_bug.cgi?id=60] &#50752; [Ben Gill|https://appfuse.dev.java.net/issues/show_bug.cgi?id=78]&#51004;&#47196; &#48512;&#53552; &#44592;&#51613;&#48155;&#51008; &#44163;&#51012; &#53664;&#45824;&#47196; &#47564;&#46308;&#50612; &#51276;&#49845;&#45768;&#45796;.
이 튜토리얼의 나머지 부분의 모든 클래스들을 자동으로 생성해 주는 __AppGen__ 툴을 AppFuse 버젼 1.61 의 일부로 포함 시켰습니다.
이 툴은 [Lance Lavandowska|https://appfuse.dev.java.net/issues/show_bug.cgi?id=60] 와 [Ben Gill|https://appfuse.dev.java.net/issues/show_bug.cgi?id=78]으로 부터 기증받은 것을 토대로 만들어 졌습니다.
At line 187 changed 1 line.
&#52376;&#51020;&#50640; &#45208;&#45716; tables/pojos, DAOs&#50752; Managers &#46308;&#51032; &#44288;&#44228;&#47484; 1-to-1 &#51004;&#47196; &#47564;&#46308;&#44172; &#54616;&#45716; &#51060;&#50752; &#44057;&#51008; &#53076;&#46300; &#49373;&#49457; &#53812;&#51012; &#52628;&#44032;&#54616;&#44256; &#49910;&#51648; &#50506;&#50520;&#50632;&#49845;&#45768;&#45796;. &#45824;&#48512;&#48516; &#45208;&#51032; &#54532;&#47196;&#51229;&#53944;&#50640;&#49436;&#45716; POJOs &#48372;&#45796; DAOs &#50752; Managers &#46308;&#51032; &#49688;&#44032; &#55016;&#50476; &#51201;&#50632;&#49845;&#45768;&#45796;.
처음에 나는 tables/pojos, DAOs와 Managers 들의 관계를 1-to-1 으로 만들게 하는 이와 같은 코드 생성 툴을 추가하고 싶지 않았었습니다. 대부분 나의 프로젝트에서는 POJOs 보다 DAOs 와 Managers 들의 수가 훨씬 적었습니다.
At line 189 changed 5 lines.
&#44592;&#48376;&#51201;&#51004;&#47196; AppGen &#51008; &#50724;&#51649; Actions/Controllers&#50752; &#44536; &#53580;&#49828;&#53944;, &#44536;&#47532;&#44256; &#53580;&#49828;&#53944; &#45936;&#51060;&#53440;, i18n &#53412;&#44050;&#46308; &#44536;&#47532;&#44256; JSP &#46308;&#51012; &#47564;&#46317;&#45768;&#45796;.
&#46608;&#54620; &#51060; &#53812;&#51008; Actions/Controllers&#51012; &#44396;&#49457;(&#49444;&#51221;)&#54644;&#51469;&#45768;&#45796;.
\\&#51060; &#53812;&#51008; &#49373;&#49457;&#46104;&#45716; &#54028;&#51068;&#51032; &#49688;&#47484; &#51460;&#51060;&#44592; &#50948;&#54644; &#54252;&#44292;&#51201;&#51064; BaseManager &#50752; BaseDaoHibernate &#53364;&#47000;&#49828;&#47484; &#49324;&#50857;&#54633;&#45768;&#45796;.\\
''(&#51593;, &#50668;&#47084; POJO&#50640; &#45824;&#54644; &#51060; &#53812;&#51012; &#49324;&#50857; &#54616;&#45908;&#46972;&#46020; &#54620;&#44060;&#51032; BaseManager &#44284; &#54620;&#44060;&#51032; BaseDaoHibernate &#47484; &#49324;&#50857;&#54620;&#45796;&#45716; &#46907;&#51064;&#46319;.)''\\
&#44536;&#47084;&#45208; &#50668;&#47084;&#48516;&#51060; &#44032;&#45140;&#51008; &#47784;&#46304; DAO &#50752; Manager &#53364;&#47000;&#49828;&#46308;&#51012; &#47564;&#46308;&#44592; &#50896;&#54616;&#45716;&#44152; &#50508;&#50520;&#44592; &#46412;&#47928;&#50640;, &#45208;&#45716; &#44536; &#44592;&#45733;&#51012; &#50741;&#49496;&#51004;&#47196; &#52628;&#44032; &#54664;&#49845;&#45768;&#45796;.
기본적으로 AppGen 은 오직 Actions/Controllers와 그 테스트, 그리고 테스트 데이타, i18n 키값들 그리고 JSP 들을 만듭니다.
또한 이 툴은 Actions/Controllers을 구성(설정)해줍니다.
\\이 툴은 생성되는 파일의 수를 줄이기 위해 포괄적인 BaseManager 와 BaseDaoHibernate 클래스를 사용합니다.\\
''(즉, 여러 POJO에 대해 이 툴을 사용 하더라도 한개의 BaseManager 과 한개의 BaseDaoHibernate 를 사용한다는 뜻인듯.)''\\
그러나 여러분이 가끔은 모든 DAO 와 Manager 클래스들을 만들기 원하는걸 알았기 때문에, 나는 그 기능을 옵션으로 추가 했습니다.
At line 196 changed 1 line.
&#51060; &#53812;&#51012; &#49324;&#50857;&#54616;&#44592; &#50948;&#54644;&#49436;&#45716; &#45796;&#51020;&#51032; &#49692;&#49436;&#47484; &#46384;&#46972;&#54644; &#51452;&#49464;&#50836;:
이 툴을 사용하기 위해서는 다음의 순서를 따라해 주세요:
At line 199 changed 3 lines.
# POJO &#47484; model &#46356;&#47113;&#53664;&#47532;&#50640; &#51089;&#49457;&#54616;&#44256; applicationContext-hibernate.xml &#54028;&#51068;&#50640; &#47588;&#54609; &#54028;&#51068;(*.hbm.xml)&#51012; [&#49444;&#51221;|5]&#54633;&#45768;&#45796;.
# extras/appgen &#46356;&#47113;&#53664;&#47532;&#47196; &#51060;&#46041;&#54620;&#46244; "__ant -Dobject.name=Person -Dappgen.type=pojo__" &#53468;&#49828;&#53356;&#47484; &#49892;&#54665;&#49884;&#53429;&#45768;&#45796;. &#51060; &#50696;&#51228;&#50640;&#49436;, Person &#53364;&#47000;&#49828;&#45716; &#48152;&#46300;&#49884; model &#54056;&#53412;&#51648;&#50640; &#51316;&#51116;&#54644; &#51080;&#50612;&#50556; &#54633;&#45768;&#45796;. &#51060; &#53468;&#49828;&#53356;&#45716; &#51060; &#53916;&#53664;&#47532;&#50620;&#51032; &#47784;&#46304; &#54028;&#51068;&#46308;&#51012; &#47564;&#46308;&#50612; &#51469;&#45768;&#45796;.
# "__ant install -Dmodel.name=Person -Dmodel.name.lowercase=person__" &#51012; &#49892;&#54665;&#54616;&#47732; &#47784;&#46304; &#54028;&#51068;&#46308;&#51060; &#51064;&#49828;&#53672; &#46121;&#45768;&#45796;.(&#44592;&#51316; &#54028;&#51068;&#51032; &#49688;&#51221;&#46020; &#51060;&#47336;&#50612;&#51664;)\\__WARNING:__ &#51060; &#53468;&#49828;&#53356;&#47484; &#49892;&#54665;&#54616;&#44592;&#51204;&#50640; &#51648;&#44552;&#44620;&#51648; &#51089;&#50629;&#54620; &#45236;&#50857;&#51012; &#48177;&#50629;&#54644; &#46160;&#49464;&#50836; - &#50500;&#45768;&#47732; &#51201;&#50612;&#46020; &#49548;&#49828;&#53076;&#46300;&#51200;&#51109;&#49548;&#50640; &#50732;&#47532;&#44592; &#51204;&#50640; &#51228;&#45824;&#47196; &#46028;&#50500;&#44032;&#45716;&#51648; &#44592;&#51316;&#53076;&#46300;&#50640;&#45716; &#51060;&#49345;&#51060; &#50630;&#45716;&#51648; &#46321;&#51012; &#54869;&#51064;&#54644; &#48372;&#49464;&#50836;. &#45236;&#44032; &#51060; &#53468;&#49828;&#53356;&#47484; &#53580;&#49828;&#53944; &#54664;&#51012;&#46412;&#45716; &#50500;&#51452; &#51096; &#51089;&#46041;&#54620;&#45796;&#44256; &#54032;&#45800;&#54664;&#49845;&#45768;&#45796;&#47564; &#51060; &#53468;&#49828;&#53356;&#45716; &#50668;&#47084;&#48516;&#51032; &#49548;&#49828;&#53944;&#47532;&#47484; &#49688;&#51221;&#54620;&#45796;&#45716;&#44163;&#51012; &#50508;&#50500;&#46160;&#49464;&#50836;.
# POJO 를 model 디렉토리에 작성하고 applicationContext-hibernate.xml 파일에 매핑 파일(*.hbm.xml)을 [설정|5]합니다.
# extras/appgen 디렉토리로 이동한뒤 "__ant -Dobject.name=Person -Dappgen.type=pojo__" 태스크를 실행시킵니다. 이 예제에서, Person 클래스는 반드시 model 패키지에 존재해 있어야 합니다. 이 태스크는 이 튜토리얼의 모든 파일들을 만들어 줍니다.
# "__ant install -Dmodel.name=Person -Dmodel.name.lowercase=person__" 을 실행하면 모든 파일들이 인스톨 됩니다.(기존 파일의 수정도 이루어짐)\\__WARNING:__ 이 태스크를 실행하기전에 지금까지 작업한 내용을 백업해 두세요 - 아니면 적어도 소스코드저장소에 올리기 전에 제대로 돌아가는지 기존코드에는 이상이 없는지 등을 확인해 보세요. 내가 이 태스크를 테스트 했을때는 아주 잘 작동한다고 판단했습니다만 이 태스크는 여러분의 소스트리를 수정한다는것을 알아두세요.
At line 211 changed 7 lines.
&#51060;&#51228; DAO &#53364;&#47000;&#49828;&#47484; &#53580;&#49828;&#53944; &#54616;&#44592; &#50948;&#54620; DaoTest &#53364;&#47000;&#49828;&#47484; &#51089;&#49457;&#54633;&#45768;&#45796;.\\
__"&#51104;&#44624;~! &#50864;&#47532;&#45716; DAO &#53364;&#47000;&#49828;&#47484; &#47564;&#46304;&#51201;&#51060; &#50630;&#51088;&#45208;"__ &#46972;&#44256; &#54616;&#45716; &#49548;&#47532;&#44032; &#46308;&#47532;&#45716;&#44400;&#50836;.\\
&#47582;&#49845;&#45768;&#45796;.\\
&#44536;&#47084;&#45208; &#45208;&#45716; [Test-Driven Development|http://www.artima.com/intv/testdriven.html] &#51060; &#48372;&#45796; &#45458;&#51008; &#53252;&#47532;&#54000;&#47484; &#44032;&#51648;&#45716; &#49548;&#54532;&#53944;&#50920;&#50612;&#47484; &#47564;&#46308;&#50612; &#45240;&#45796;&#45716; &#44163;&#51012; &#50508;&#50520;&#49845;&#45768;&#45796;.\\
&#47751;&#45380;&#44036; &#45208;&#45716; __&#53364;&#47000;&#49828;&#47484; &#51089;&#49457;&#54616;&#44592; &#51204;&#50640; &#53580;&#49828;&#53944;&#47484; &#47676;&#51200; &#51089;&#49457;&#54616;&#46972;__&#45716; &#44163;&#51008; &#48148;&#48372;&#44057;&#51008; &#51667;&#51060;&#46972;&#44256; &#49373;&#44033;&#54664;&#50632;&#49845;&#45768;&#45796;.\\
&#44536;&#47084;&#45208; &#45208;&#45716; &#44536;&#47111;&#44172; &#54644; &#48372;&#50520;&#44256; &#44536; &#44208;&#44284; &#44536;&#44163;&#51060; &#54988;&#47469;&#54616;&#44172; &#51089;&#46041;&#46104;&#45716; &#44163;&#51012; &#50508;&#50520;&#49845;&#45768;&#45796;.\\
&#45236;&#44032; &#51648;&#44552; test-driven &#51012; &#54620;&#45716; &#51060;&#50976;&#45716; &#44536;&#44163;&#51060; &#49548;&#54532;&#53944;&#50920;&#50612; &#44060;&#48156; &#54532;&#47196;&#49464;&#49828;&#51032; &#49549;&#46020;&#47484; &#47924;&#52377; &#48736;&#47476;&#44172; &#54644;&#51456;&#45796;&#45716;&#44152; &#50508;&#50520;&#44592; &#46412;&#47928;&#51077;&#45768;&#45796;.
이제 DAO 클래스를 테스트 하기 위한 DaoTest 클래스를 작성합니다.\\
__"잠깐~! 우리는 DAO 클래스를 만든적이 없자나"__ 라고 하는 소리가 들리는군요.\\
맞습니다.\\
그러나 나는 [Test-Driven Development|http://www.artima.com/intv/testdriven.html] 이 보다 높은 퀄리티를 가지는 소프트웨어를 만들어 낸다는 것을 알았습니다.\\
몇년간 나는 __클래스를 작성하기 전에 테스트를 먼저 작성하라__는 것은 바보같은 짓이라고 생각했었습니다.\\
그러나 나는 그렇게 해 보았고 그 결과 그것이 훌륭하게 작동되는 것을 알았습니다.\\
내가 지금 test-driven 을 한는 이유는 그것이 소프트웨어 개발 프로세스의 속도를 무척 빠르게 해준다는걸 알았기 때문입니다.
At line 219 changed 3 lines.
&#49884;&#51089;&#54616;&#44592; &#50948;&#54644;&#49436;, test/dao/**/dao &#46356;&#47113;&#53664;&#47532;&#50640; PersonDaoTest.java &#47484; &#47564;&#46317;&#45768;&#45796;. &#51060; &#53364;&#47000;&#49828;&#45716; &#44057;&#51008; &#54056;&#53412;&#51648;&#50640; &#46308;&#50612;&#51080;&#45716; [BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDaoTestCase.java.html] &#53364;&#47000;&#49828;&#47484; &#54869;&#51109;&#54644;&#50556; &#54633;&#45768;&#45796;.
&#51060; &#48512;&#47784; &#53364;&#47000;&#49828;&#45716; [Spring's|http://www.springframework.org] ApplicationContext&#51012; &#51069;&#50612; &#46308;&#51060;&#45716; &#44163;&#44284; *Test.class &#50752; &#44057;&#51008; &#51060;&#47492;&#51012; &#44032;&#51648;&#45716; .properties &#54028;&#51068; (ResourceBundle)&#51012; &#51088;&#46041;&#51004;&#47196; &#51069;&#50612;&#46308;&#51060;&#45716;&#45936; &#49324;&#50857; &#46121;&#45768;&#45796;.
&#51060; &#50696;&#51228;&#50640;&#49436;&#45716; PersonDaoTest.properties &#54028;&#51068;&#51012; PersonDaoTest.java &#50752; &#44057;&#51008; &#46356;&#47113;&#53664;&#47532;&#50640; &#45459;&#51004;&#47732; &#51060; &#54028;&#51068;&#50640; &#44592;&#49696;&#46108; &#49549;&#49457;&#46308;&#51008; rb &#48320;&#49688;&#50640; &#51032;&#54644; &#49324;&#50857;&#46112; &#49688; &#51080;&#44172; &#46121;&#45768;&#45796;.
시작하기 위해서, test/dao/**/dao 디렉토리에 PersonDaoTest.java 를 만듭니다. 이 클래스는 같은 패키지에 들어있는 [BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDaoTestCase.java.html] 클래스를 확장해야 합니다.
이 부모 클래스는 [Spring's|http://www.springframework.org] ApplicationContext을 읽어 들이는 것과 *Test.class 와 같은 이름을 가지는 .properties 파일 (ResourceBundle)을 자동으로 읽어들이는데 사용 됩니다.
이 예제에서는 PersonDaoTest.properties 파일을 PersonDaoTest.java 와 같은 디렉토리에 놓으면 이 파일에 기술된 속성들은 rb 변수에 의해 사용될 수 있게 됩니다.
At line 223 changed 1 line.
;:<font color="blue">''&#45208;&#45716; &#51452;&#47196; &#51060;&#48120; &#47564;&#46308;&#50612; &#45459;&#51008; test (i.e. UserDaoTest.java) &#47484; copy (&#50676;&#44592; &rarr; &#45796;&#47480;&#51060;&#47492;&#51004;&#47196; &#51200;&#51109;) &#54620; &#54980;&#50640; find/replace &#44592;&#45733;&#51012; &#51060;&#50857;&#54644; [[Uu]ser &#47484; [[Pp]erson(object name)&#51004;&#47196; &#48148;&#45001;&#45768;&#45796;.''</font>
;:<font color="blue">''나는 주로 이미 만들어 놓은 test (i.e. UserDaoTest.java) 를 copy (열기 &rarr; 다른이름으로 저장) 한 후에 find/replace 기능을 이용해 [[Uu]ser 를 [[Pp]erson(object name)으로 바꿉니다.''</font>
At line 251 changed 2 lines.
JUnit &#53580;&#49828;&#53944;&#47484; &#50948;&#54644;&#49436; PersonDao &#47484; initializes(&#52488;&#44592;&#54868;) &#54616;&#44256; destroys (&#49548;&#47736;) &#54616;&#45716; &#44592;&#48376;&#51201;&#51064; &#53076;&#46300;&#51077;&#45768;&#45796;.
"ctx" object &#45716; Spring's ApplicationContext &#51077;&#45768;&#45796;. &#51060;&#44163;&#51008;[BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/persistence/BaseDaoTestCase.java.html] &#53364;&#47000;&#49828;&#51032; static block &#50640;&#49436; &#52488;&#44592;&#54868; &#46121;&#45768;&#45796;.
JUnit 테스트를 위해서 PersonDao 를 initializes(초기화) 하고 destroys (소멸) 하는 기본적인 코드입니다.
"ctx" object 는 Spring's ApplicationContext 입니다. 이것은[BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/persistence/BaseDaoTestCase.java.html] 클래스의 static block 에서 초기화 됩니다.
At line 254 changed 7 lines.
&#51088; &#51060;&#51228;&#45716; DAO&#51032; CRUD(create, retrieve, update, delete) &#47700;&#49548;&#46300;&#47484; &#53580;&#49828;&#53944;&#47484; &#54644;&#50556; &#54633;&#45768;&#45796;.
&#51060; &#53580;&#49828;&#53944;&#47484; &#50948;&#54644;&#49436; &#50864;&#47532;&#45716; test(&#47784;&#46160; &#49548;&#47928;&#51088;)&#47196; &#49884;&#51089;&#54616;&#45716; &#47700;&#49548;&#46300;&#47484; &#47564;&#46308;&#50612;&#50556; &#54633;&#45768;&#45796;.
&#51060; &#47700;&#49548;&#46300;&#44032; Ant build.xml &#54028;&#51068;&#51032; &lt;junit&gt; &#53468;&#49828;&#53356;&#50640; &#51032;&#54644; &#48520;&#47140; &#51656;&#47140;&#47732; &#47751;&#44032;&#51648; &#44508;&#52825;&#51060; &#54596;&#50836;&#54633;&#45768;&#45796;.
* &#47700;&#49548;&#46300; &#51060;&#47492;&#51060; test(&#47784;&#46160; &#49548;&#47928;&#51088;)&#47196; &#49884;&#51089;&#54644;&#50556; &#54620;&#45796;
* public &#47700;&#49548;&#46300;&#50668;&#50556; &#54620;&#45796;.
* &#47532;&#53556;&#53440;&#51077;&#51060; void &#51060;&#50668;&#50556; &#54620;&#45796;.
* &#51204;&#45804; &#51064;&#51088;&#44032; &#50630;&#50612;&#50556; &#54620;&#45796;.
자 이제는 DAO의 CRUD(create, retrieve, update, delete) 메소드를 테스트를 해야 합니다.
이 테스트를 위해서 우리는 test(모두 소문자)로 시작하는 메소드를 만들어야 합니다.
이 메소드가 Ant build.xml 파일의 &lt;junit&gt; 태스크에 의해 불려 질려면 몇가지 규칙이 필요합니다.
* 메소드 이름이 test(모두 소문자)로 시작해야 한다
* public 메소드여야 한다.
* 리턴타입이 void 이여야 한다.
* 전달 인자가 없어야 한다.
At line 262 changed 3 lines.
&#50668;&#44592; CRUD &#53580;&#49828;&#53944;&#47484; &#50948;&#54620; &#44036;&#45800;&#54620; &#53580;&#49828;&#53944; &#53076;&#46300;&#44032; &#51080;&#49845;&#45768;&#45796;.
&#51473;&#50836;&#54620; &#44163;&#51008; &#44033;&#44033;&#51032; &#47700;&#49548;&#46300;&#46308;&#51008; &#51088;&#48156;&#51201;&#51004;&#47196; &#51068;&#50612;&#45212;&#45796;&#45716; &#51216; &#51077;&#45768;&#45796;.
&#45796;&#51020;&#51032; &#47700;&#49548;&#46300;&#46308;&#51012; PersonDaoTest.java &#54028;&#51068;&#50640; &#52628;&#44032; &#54633;&#45768;&#45796;:
여기 CRUD 테스트를 위한 간단한 테스트 코드가 있습니다.
중요한 것은 각각의 메소드들은 자발적으로 일어난다는 점 입니다.
다음의 메소드들을 PersonDaoTest.java 파일에 추가 합니다:
At line 320 changed 1 line.
;:<font color="blue">''testGetPerson &#47700;&#49548;&#46300;&#50640;&#49436; &#50864;&#47532;&#45716; person &#51012; &#49373;&#49457; &#54620; &#54980;&#50640; get &#47700;&#49548;&#46300;&#47484; &#54840;&#52636;&#54664;&#49845;&#45768;&#45796;. &#45208;&#45716; &#51452;&#47196; &#45236;&#44032; &#54637;&#49345; &#49324;&#50857;&#54624; &#49688; &#51080;&#45716; &#47112;&#53076;&#46300;&#47484; &#45936;&#51060;&#53440; &#48288;&#51060;&#49828;&#50640; &#45347;&#49845;&#45768;&#45796;. \\&#44536;&#47084;&#45208; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828; &#53580;&#49828;&#53944;&#47484; &#50948;&#54616;&#50668; [DBUnit|http://www.dbunit.org] &#51060; &#49324;&#50857;&#46108; &#51060;&#54980;&#47196;&#45716; test &#47484; &#49892;&#54665;&#54616;&#44592; &#51204;&#50640; metadata/sql/sample-data.xml &#54028;&#51068;&#50640; &#44036;&#45800;&#55176; &#52628;&#44032;&#54624; &#47112;&#53076;&#46300; &#51221;&#48372;&#47484; &#51077;&#47141;&#54644; &#45459;&#51004;&#47732; &#46121;&#45768;&#45796;:''</font>
;:<font color="blue">''testGetPerson 메소드에서 우리는 person 을 생성 한 후에 get 메소드를 호출했습니다. 나는 주로 내가 항상 사용할 수 있는 레코드를 데이타 베이스에 넣습니다. \\그러나 데이타베이스 테스트를 위하여 [DBUnit|http://www.dbunit.org] 이 사용된 이후로는 test 를 실행하기 전에 metadata/sql/sample-data.xml 파일에 간단히 추가할 레코드 정보를 입력해 놓으면 됩니다:''</font>
At line 337 changed 1 line.
;:<font color="blue">''&#51060;&#44163;&#51060; testGetPerson &#47700;&#49548;&#46300;&#50640;&#49436; Person &#48120;&#47532; &#47564;&#46308;&#50612; &#45460;&#50556; &#54616;&#45716; &#53076;&#46300;&#47484; &#50630;&#50536; &#49688; &#51080;&#45716; &#54616;&#45208;&#51032; &#48169;&#48277;&#51077;&#45768;&#45796;. &#47564;&#50557; SQL &#51060;&#45208; GUI &#53812; &#46321;&#51012; &#51060;&#50857;&#54616;&#50668; &#51649;&#51217; &#45936;&#51060;&#53440;&#48288;&#51060;&#49828;&#50640; &#47112;&#53076;&#46300;&#47484; &#45347;&#44256; &#49910;&#45796;&#47732; "ant db-export" &#53468;&#49828;&#53356;&#47484; &#49892;&#54665; &#49884;&#53416; &#54980; "cp db-export.xml metadata/sql/sample-data.xml" &#54632;&#51004;&#47196;&#49436; sample-data.xml &#49352;&#47196; &#47564;&#46308; &#49688; &#51080;&#49845;&#45768;&#45796;.''</font>
;:<font color="blue">''이것이 testGetPerson 메소드에서 Person 미리 만들어 놔야 하는 코드를 없앨 수 있는 하나의 방법입니다. 만약 SQL 이나 GUI 툴 등을 이용하여 직접 데이타베이스에 레코드를 넣고 싶다면 "ant db-export" 태스크를 실행 시킨 후 "cp db-export.xml metadata/sql/sample-data.xml" 함으로서 sample-data.xml 새로 만들 수 있습니다.''</font>
At line 339 changed 4 lines.
&#50948; &#50696;&#51228;&#50640;&#49436; &#50864;&#47532;&#45716; &#44061;&#52404;&#47484; &#51200;&#51109;&#54616;&#44592; &#51204;&#50640; &#44536; &#44050;&#46308;&#51012; &#49444;&#51221;&#54616;&#44592; &#50948;&#54616;&#50668; person.set*(value) &#47484; &#54840;&#52636;&#54616;&#50688;&#49845;&#45768;&#45796;.
&#50948; &#50696;&#51228;&#50640;&#49436;&#45716; &#47924;&#52377; &#44036;&#45800;&#54664;&#51648;&#47564;(&#49549;&#49457;&#51060; &#47751;&#44060; &#50630;&#44592; &#46412;&#47928;&#50640;) &#47564;&#50557; 10&#44060;&#51032; &#54596;&#49688; &#54596;&#46300;(not-null="true")&#47484; &#44032;&#51648;&#45716; &#44060;&#52404;&#47484; &#51200;&#51109;&#54620;&#45796;&#47732; &#51060;&#45716; &#48372;&#53685; &#49457;&#44032;&#49888; &#51068;&#51060; &#50500;&#45776;&#44161;&#45768;&#45796;.
&#51060;&#44163;&#51060; &#45236;&#44032; BaseDaoTestCase &#50640;&#49436; ResourceBundle &#51012; &#49373;&#49457;&#54664;&#45912; &#51060;&#50976;&#51077;&#45768;&#45796;.
&#44036;&#45800;&#55176; PersonDaoTest.java &#50752; &#44057;&#51008; &#46356;&#47113;&#53664;&#47532;&#50640; PersonDaoTest.properties &#54028;&#51068;&#51012; &#45347;&#44256; &#51060; &#54028;&#51068;&#50640; &#49549;&#49457; &#44050;&#46308;&#51012; &#49444;&#51221;&#54633;&#45768;&#45796;.
위 예제에서 우리는 객체를 저장하기 전에 그 값들을 설정하기 위하여 person.set*(value) 를 호출하였습니다.
위 예제에서는 무척 간단했지만(속성이 몇개 없기 때문에) 만약 10개의 필수 필드(not-null="true")를 가지는 개체를 저장한다면 이는 보통 성가신 일이 아닐겁니다.
이것이 내가 BaseDaoTestCase 에서 ResourceBundle 을 생성했던 이유입니다.
간단히 PersonDaoTest.java 와 같은 디렉토리에 PersonDaoTest.properties 파일을 넣고 이 파일에 속성 값들을 설정합니다.
At line 347 changed 1 line.
&#44536;&#47084;&#44256; &#45208;&#49436; person.set* &#47700;&#49548;&#46300; &#45824;&#49888; BaseDaoTestCase.populate(java.lang.Object) &#51012; &#54840;&#52636; &#54632;&#51004;&#47196;&#49436; object&#51032; &#44050;&#46308;&#51012; &#49444;&#51221;&#54624; &#49688; &#51080;&#49845;&#45768;&#45796;.
그러고 나서 person.set* 메소드 대신 BaseDaoTestCase.populate(java.lang.Object) 을 호출 함으로서 object의 값들을 설정할 수 있습니다.
At line 355 changed 3 lines.
&#50500;&#51649; PersonDao.class &#47484; &#47564;&#46308;&#51648; &#50506;&#50520;&#44592; &#46412;&#47928;&#50640; PersonDaoTest &#53364;&#47000;&#49828;&#45716; &#52980;&#54028;&#51068; &#46104;&#51648; &#50506;&#51012;&#44161;&#45768;&#45796;. &#50864;&#47532;&#45716; &#51648;&#44552; &#44536;&#44163;&#51012; &#51089;&#49457;&#54644;&#50556;&#47564; &#54633;&#45768;&#45796;.
PersonDao.java &#45716; interface &#51077;&#45768;&#45796;. &#44536;&#47532;&#44256; PersonDaoHibernate.java &#45716; &#44536; &#51064;&#53552;&#54168;&#51060;&#49828;&#51032; Hibernate &#47484; &#51060;&#50857;&#54620; &#44396;&#54788;&#51077;&#45768;&#45796;.
&#51088; &#51060;&#44163;&#46308;&#51012; &#47564;&#46308;&#50612; &#48389;&#49884;&#45796;.
아직 PersonDao.class 를 만들지 않았기 때문에 PersonDaoTest 클래스는 컴파일 되지 않을겁니다. 우리는 지금 그것을 작성해야만 합니다.
PersonDao.java 는 interface 입니다. 그리고 PersonDaoHibernate.java 는 그 인터페이스의 Hibernate 를 이용한 구현입니다.
자 이것들을 만들어 봅시다.
At line 359 changed 3 lines.
!!Object &#51032; CRUD &#52376;&#47532;&#47484; &#50948;&#54620; DAO &#53364;&#47000;&#49828;&#47484; &#47564;&#46317;&#45768;&#45796; [#4]
&#52395;&#51704;&#47196; &#44396;&#54788; &#53364;&#47000;&#49828;&#46308;&#51012; &#50948;&#54620; &#44592;&#48376;&#51201;&#51064; CRUD &#47700;&#49548;&#46300;&#46308;&#51012; &#51221;&#51032;&#54620; PersonDao.java interface &#47484; src/dao/**/dao &#50640; &#47564;&#46308;&#44256; CRUD &#47700;&#49548;&#46300;&#47484; &#51221;&#51032;&#54633;&#45768;&#45796;.
''&#45208;&#45716; &#50836;&#51216;&#47564; &#48372;&#50668;&#51452;&#44592; &#50948;&#54616;&#50668; &#50500;&#47000; &#53364;&#47000;&#49828;&#50640; JavaDoc &#46308;&#51012; &#49325;&#51228;&#54664;&#49845;&#45768;&#45796;.''
!!Object 의 CRUD 처리를 위한 DAO 클래스를 만듭니다 [#4]
첫째로 구현 클래스들을 위한 기본적인 CRUD 메소드들을 정의한 PersonDao.java interface 를 src/dao/**/dao 에 만들고 CRUD 메소드를 정의합니다.
''나는 요점만 보여주기 위하여 아래 클래스에 JavaDoc 들을 삭제했습니다.''
At line 376 changed 3 lines.
&#50948; &#53364;&#47000;&#49828;&#51032; &#47784;&#46304; &#47700;&#49548;&#46300;&#50640; &#50696;&#50808;&#47484; &#44592;&#49696;&#54616;&#51648; &#50506;&#51008;&#44163;&#51008; Spring &#54532;&#47112;&#51076;&#50892;&#53356;&#44032; RuntimeException &#46308;&#51012; &#44048;&#49912;&#44256;(wrap) &#51080;&#44592; &#46412;&#47928;&#51077;&#45768;&#45796;.
&#50668;&#44592;&#49436; "ant compile-dao" &#53468;&#49828;&#53356;&#47484; &#51060;&#50857;&#54616;&#50668; src/dao &#50752; test/dao &#50640; &#51080;&#45716; &#47784;&#46304; &#49548;&#49828;&#53076;&#46300;&#46308;&#51012; &#52980;&#54028;&#51068; &#54624; &#49688; &#51080;&#51012;&#44161;&#45768;&#45796;.
&#44536;&#47084;&#45208; &#47564;&#50557; "ant test-dao -Dtestcase=PersonDao" &#53468;&#49828;&#53356;&#47484; &#49892;&#54665; &#54616;&#47140; &#54620;&#45796;&#47732; &#50640;&#47084;&#44032; &#45216; &#44163;&#51077;&#45768;&#45796;:<span style="color: red">No bean named 'personDao' is defined</span>. &#51060;&#44163;&#51008; Spring &#50640; &#51032;&#54644;&#49436; &#45208;&#53440;&#45212; &#50640;&#47084; &#47700;&#49464;&#51648;&#51077;&#45768;&#45796;. &#51060; &#47700;&#49464;&#51648;&#51032; &#51032;&#48120;&#45716; applicationContext-hibernate.xml &#50640; personDAO &#46972;&#45716; bean &#51012; &#51221;&#51032; &#54644;&#50556; &#54620;&#45796;&#45716; &#44163;&#51077;&#45768;&#45796;. &#51060; bean &#51012; &#51221;&#51032;&#54616;&#44592; &#51204;&#50640; &#47676;&#51200; &#50864;&#47532;&#45716; PersonDao &#47484; &#44396;&#54788;&#54620; &#53364;&#47000;&#49828;&#47484; &#51089;&#49457;&#54644;&#50556; &#54624; &#44163;&#51077;&#45768;&#45796;.
위 클래스의 모든 메소드에 예외를 기술하지 않은것은 Spring 프레임워크가 RuntimeException 들을 감싸고(wrap) 있기 때문입니다.
여기서 "ant compile-dao" 태스크를 이용하여 src/dao 와 test/dao 에 있는 모든 소스코드들을 컴파일 할 수 있을겁니다.
그러나 만약 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행 하려 한다면 에러가 날 것입니다:<span style="color: red">No bean named 'personDao' is defined</span>. 이것은 Spring 에 의해서 나타난 에러 메세지입니다. 이 메세지의 의미는 applicationContext-hibernate.xml 에 personDAO 라는 bean 을 정의 해야 한다는 것입니다. 이 bean 을 정의하기 전에 먼저 우리는 PersonDao 를 구현한 클래스를 작성해야 할 것입니다.
At line 380 changed 1 line.
;:''&#53468;&#49828;&#53944;&#47484; &#50948;&#54620; ant task &#45716; "test-module." &#53468;&#49828;&#53356;&#47484; &#54840;&#52636;&#54633;&#45768;&#45796;. &#47564;&#50557; testcase &#54028;&#46972;&#48120;&#53552;(-Dtestcase=name)&#50640; &#54056;&#49828; &#44050;&#51012; &#44592;&#49696;&#54620;&#45796;&#47732; "test-module." &#53468;&#49828;&#53356;&#45716; **/*${testcase}* - <span style="color: blue">&#51060;&#44163;&#51008; &#50864;&#47532;&#44032; Person, PersonDao, PersonDaoTest &#51473; &#50612;&#46500;&#44163;&#51012; &#54056;&#49828;&#50640; &#45347;&#50612;&#46020; &#49345;&#44288; &#50630;&#45796;&#45716; &#44163;&#51012; &#47568;&#54633;&#45768;&#45796;.</span> - &#50948; &#49464;&#44032;&#51648; &#47784;&#46160; PersonDaoTest &#47484; &#49688;&#54665;&#54624; &#44163;&#51077;&#45768;&#45796;. ''
;:''태스트를 위한 ant task 는 "test-module." 태스크를 호출합니다. 만약 testcase 파라미터(-Dtestcase=name)에 패스 값을 기술한다면 "test-module." 태스크는 **/*${testcase}* - <span style="color: blue">이것은 우리가 Person, PersonDao, PersonDaoTest 중 어떤것을 패스에 넣어도 상관 없다는 것을 말합니다.</span> - 위 세가지 모두 PersonDaoTest 를 수행할 것입니다. ''
At line 382 changed 2 lines.
PersonDao interface&#51032; &#47700;&#49548;&#46300;&#47484; &#44396;&#54788;&#54616;&#45716; PersonDaoHibernate class &#47484; &#51089;&#49457;&#54633;&#49884;&#45796;. &#44536;&#47532;&#44256; Hibernate &#47484; &#49324;&#50857;&#54616;&#50668; Person object &#47484; get/save/delete &#54616;&#45716; &#47700;&#49548;&#46300;&#47484; &#51089;&#49457;&#54644;&#48389;&#49884;&#45796;.\\
src/dao/**/dao/hibernate &#51060;&#44275;&#50640; PersonDaoHibernate.java &#53364;&#47000;&#49828;&#47484; &#47564;&#46317;&#45768;&#45796;. &#44536;&#47532;&#44256; &#51060;&#47484; &#48152;&#46300;&#49884; BaseDaoHibernate &#47484; &#54869;&#51109;(extends)&#54616;&#44256; PersonDao &#47484; &#44396;&#54788;(implements)&#54616;&#46020;&#47197; &#51089;&#49457;&#54633;&#45768;&#45796;.
PersonDao interface의 메소드를 구현하는 PersonDaoHibernate class 를 작성합시다. 그리고 Hibernate 를 사용하여 Person object 를 get/save/delete 하는 메소드를 작성해봅시다.\\
src/dao/**/dao/hibernate 이곳에 PersonDaoHibernate.java 클래스를 만듭니다. 그리고 이를 반드시 BaseDaoHibernate 를 확장(extends)하고 PersonDao 를 구현(implements)하도록 작성합니다.
At line 416 changed 2 lines.
&#50668;&#44592;&#49436; "ant test-dao -Dtestcase=PersonDao" &#53468;&#49828;&#53356;&#47484; &#49892;&#54665;&#54616;&#47140; &#54616;&#47732; &#46609;&#44057;&#51008; &#50640;&#47084;&#44032; &#45208;&#50732; &#44161;&#45768;&#45796;.
&#50864;&#47532;&#45716; PersonDao &#51032; &#44396;&#54788; &#53364;&#47000;&#49828;&#45716; PersonDaoHibernate &#46972;&#45716; &#44163;&#44284; Person object &#50640; &#45824;&#54644; Spring &#54532;&#47112;&#51076;&#50892;&#53356;&#44032; &#50508;&#49688; &#51080;&#46020;&#47197; &#47751;&#44032;&#51648; &#54028;&#51068;&#46308;&#51012; &#44396;&#49457;&#54644;&#50556; &#54633;&#45768;&#45796;.
여기서 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행하려 하면 똑같은 에러가 나올 겁니다.
우리는 PersonDao 의 구현 클래스는 PersonDaoHibernate 라는 것과 Person object 에 대해 Spring 프레임워크가 알수 있도록 몇가지 파일들을 구성해야 합니다.
At line 419 changed 3 lines.
!!Person object&#50752; PersonDao&#47484; Spring &#54532;&#47112;&#51076;&#50892;&#53356;&#50640; &#50508;&#47532;&#44592; &#50948;&#54644; &#49444;&#51221;&#54028;&#51068;&#51012; &#44396;&#49457;&#54633;&#45768;&#45796; [#5]
&#52395;&#51704;&#47196;, &#50612;&#46356;&#50640; Hibernate &#47588;&#54609;&#54028;&#51068;&#51060; &#51080;&#45716;&#51648; Spring &#54532;&#47112;&#51076; &#50892;&#53356;&#50640; &#50508;&#47140;&#51480;&#50556; &#54633;&#45768;&#45796;.\\
src/dao/**/dao/hibernate/applicationContext-hibernate.xml &#54028;&#51068;&#51012; &#50676;&#50612;&#49436; Person.hbm.xml &#51012; &#45796;&#51020; &#53076;&#46300;&#48660;&#47085;&#52376;&#47100; &#52628;&#44032; &#54633;&#45768;&#45796;.
!!Person object와 PersonDao를 Spring 프레임워크에 알리기 위해 설정파일을 구성합니다 [#5]
첫째로, 어디에 Hibernate 매핑파일이 있는지 Spring 프레임 워크에 알려줘야 합니다.\\
src/dao/**/dao/hibernate/applicationContext-hibernate.xml 파일을 열어서 Person.hbm.xml 을 다음 코드블럭처럼 추가 합니다.
At line 430 removed 1 line.
<value>org/appfuse/model/UserCookie.hbm.xml</value>
At line 435 changed 1 line.
&#45796;&#51020;&#51004;&#47196; PersonDaoHibernate &#50752; PersonDao &#47484; &#50672;&#44208;&#54616;&#44592; &#50948;&#54644;&#49436; &#45796;&#51020;&#51032; XML &#53468;&#44536;&#47484; &#51060; &#54028;&#51068;&#50640; &#45149;&#50640; &#52628;&#44032; &#54633;&#45768;&#45796;.
다음으로 PersonDaoHibernate 와 PersonDao 를 연결하기 위해서 다음의 XML 태그를 이 파일에 끝에 추가 합니다.
At line 445 changed 1 line.
''<bean> &#53468;&#44536;&#50640; autowire="byName" &#49549;&#49457;&#51012; &#44592;&#49696;&#54632;&#51004;&#47196;&#50024; "sessionFactory" property &#49444;&#51221;&#51012; &#50630;&#50536;&#49688;&#46020; &#51080;&#49845;&#45768;&#45796;. Personally, I like having the dependencies of my objects documented (in XML). ''
''<bean> 태그에 autowire="byName" 속성을 기술함으로써 "sessionFactory" property 설정을 없앨수도 있습니다. Personally, I like having the dependencies of my objects documented (in XML). ''
At line 447 changed 2 lines.
!!DaoTest &#47484; &#49892;&#54665; &#54633;&#45768;&#45796;. [#6]
&#49688;&#51221;&#54620; &#47784;&#46304; &#54028;&#51068;&#51012; &#51200;&#51109;&#54616;&#44256; &#45796;&#49884;&#54620;&#48264; "ant test-dao -Dtestcase=PersonDao" &#53468;&#49828;&#53356;&#47484; &#49892;&#54665; &#54633;&#45768;&#45796;.
!!DaoTest 를 실행 합니다. [#6]
수정한 모든 파일을 저장하고 다시한번 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행 합니다.
At line 456 changed 1 line.
''Next Up:'' __Part II:__ [&#49352;&#47196;&#50868; &#47588;&#45768;&#51200; &#51089;&#49457;&#54616;&#44592;|CreateManager] - (''[Session Facades|http://java.sun.com/blueprints/patterns/SessionFacade.html] &#50752; &#48708;&#49847;&#54616;&#51648;&#47564; EJBs &#47484; &#49324;&#50857;&#54616;&#51648; &#50506;&#45716;'')Business Facades &#47484; &#51089;&#49457;&#54616;&#45716; &#48169;&#48277;. DAO &#44228;&#52789;&#44284; front-end &#44228;&#52789;&#51012; &#50672;&#44208;&#54616;&#45716; &#52285;&#44396; &#50669;&#54624;&#51012; &#54633;&#45768;&#45796;.
''Next Up:'' __Part II:__ [새로운 매니저 작성하기|CreateManager_ko] - (''[Session Facades|http://java.sun.com/blueprints/patterns/SessionFacade.html] 와 비슷하지만 EJBs 를 사용하지 않는'')Business Facades 를 작성하는 방법. DAO 계층과 front-end 계층을 연결하는 창구 역할을 합니다.

Back to CreateDAO_ko, or to the Page History.