At line 1 changed 1 line. |
__Part I:__ [AppFuse에서 새로운 DAO들과 Object들을 작성하기|CreateDAO] - table을 나타내는 Java Object와 이 Object들을 데이타 베이스에 저장 시키는 Java 클래스들을 만드는 방법. |
__Part I:__ [AppFuse에서 새로운 DAO들과 Object들을 작성하기|CreateDAO] - 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> 만약 당신이 MySQL을 사용하면서 트랜젝션 처리를 원한다면 반드시 InnoDB 테이블을 사용하여야 합니다. InnoDB를 사용 하려면 mysql 설정 파일(/etc/my.cnf or c:\Windows\my.ini)에 다음과 같은 라인을 추가합니다. 두번째 설정(UTF-8 character set) 은 mysql 4.1.7+ 버젼에서 필요한 것입니다. |
<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. |
만약 PostgreSQL 디비를 사용하면서 batch processing 에 관련된 에러가 나게 되면 src/dao/**/hibernate/applicationContext-hibernate.xml 파일에 <tt><prop key="hibernate.jdbc.batch_size">0</prop></tt> 라인을 추가해서 batch processing기능을 끄도록 합니다.</div> |
만약 PostgreSQL 디비를 사용하면서 batch processing 에 관련된 에러가 나게 되면 src/dao/**/hibernate/applicationContext-hibernate.xml 파일에 <tt><prop key="hibernate.jdbc.batch_size">0</prop></tt> 라인을 추가해서 batch processing기능을 끄도록 합니다.</div> |
At line 22 changed 1 line. |
AppFuse 는 persistence layer 로 [Hibernate|http://www.hibernate.org] 를 사용 합니다. Hibernate 는 자바 객체와 데이타베이스 테이블을 관련짓게 하는 __Object/Relational (O/R) Framework__ 로써 자바 객체에 __CRUD (Create, Retrieve, Update, Delete)__ 기능을 매우 쉽게 다루게 합니다. |
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. |
자 그럼 Object, DAO 그리고 Test 를 작성해 봅시다. |
자 그럼 Object, DAO 그리고 Test 를 작성해 봅시다. |
At line 26 changed 7 lines. |
!목차 |
* [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 를 실행시합니다. |
!목차 |
* [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 를 만들고 XDoclet 태그를 추가합니다 [#1] |
먼저 persist 할 object 를 작성합니다. \\ |
id 와 firstName 그리고 lastName 속성을 가지고 있는 간단한 "Person" 객체를 작성합니다.(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. |
이 클래스는 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] 가 있습니다.\\ |
이 클래스는 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>만약 [IntelliJ IDEA|http://www.jetbrains.com/idea]를 사용 한다면 equals() 과 hashCode() 메소드는 만들어 낼 수 있지만 toString() 은 기본적으로 제공되지 않으므로 [ToStringPlugin|http://www.intellij.org/twiki/bin/view/Main/ToStringPlugin] 을 사용 하시면 될겁니다. 전 개인적으로 이 플러그인을 사용해 보지는 않았습니다.</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. |
이제 우리가 만든 POJO 클래스에 대한 Hibernate 맵핑 파일을 만들기 위해 XDoclet 태그를 추가합니다.\\ |
이 맵핑 파일은 Hibernate 가 objects → tables 그리고 properties (variables) → columns 을 맵핑하기 위해 사용 됩니다. |
이제 우리가 만든 POJO 클래스에 대한 Hibernate 맵핑 파일을 만들기 위해 XDoclet 태그를 추가합니다.\\ |
이 맵핑 파일은 Hibernate 가 objects → tables 그리고 properties (variables) → columns 을 맵핑하기 위해 사용 됩니다. |
At line 67 changed 1 line. |
첫째로, Hibernate 에게 이 object 와 관련된 데이타베이스 테이블이 무엇인지 알려주기 위하여 [@hibernate.class|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.class%20(0..1)] 태그를 추가합니다: |
첫째로, Hibernate 에게 이 object 와 관련된 데이타베이스 테이블이 무엇인지 알려주기 위하여 [@hibernate.class|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.class%20(0..1)] 태그를 추가합니다: |
At line 77 changed 2 lines. |
다음으로 primary key 맵핑 태그를 추가해합니다. |
모든 @hibernate.* 태그는 반드시 POJO 클래스의 __getters'__ Javadoc 에 적어야 한다는걸 기억하세요 |
다음으로 primary key 맵핑 태그를 추가해합니다. |
모든 @hibernate.* 태그는 반드시 POJO 클래스의 __getters'__ Javadoc 에 적어야 한다는걸 기억하세요 |
At line 93 changed 1 line. |
;:<font color="blue">''다른 데이타베이스에서 "native"를 사용할때의 [문제들|http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseOnDB2] 때문에 나는 generate-class="native" 대신 generator-class="increment" 를 사용했습니다. 만약 당신이 오직 MySQL 만을 사용한다면 "native" 를 사용할 것을 권장합니다. 이 튜토리얼에서는 increment 를 사용합니다.''</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 를 이용하여 Object 로 부터 데이타베이스 테이블을 만듭니다 [#2] |
이제 콘솔에서 "ant setup-db" 를 실행해서 person 데이타베이스 테이블을 만들 수 있습니다. |
"ant setup-db" 태스크는 Person.hbm.xml 파일과 "person." 테이블을 만듭니다. |
태스크를 실행 시킴으로써 Hibernate 가 만드는 테이블 스키마를 볼 수 있습니다: |
!!Ant 를 이용하여 Object 로 부터 데이타베이스 테이블을 만듭니다 [#2] |
이제 콘솔에서 "ant setup-db" 를 실행해서 person 데이타베이스 테이블을 만들 수 있습니다. |
"ant setup-db" 태스크는 Person.hbm.xml 파일과 "person." 테이블을 만듭니다. |
태스크를 실행 시킴으로써 Hibernate 가 만드는 테이블 스키마를 볼 수 있습니다: |
At line 107 changed 2 lines. |
만약 Hibernate 가 만들어준 Person.hbm.xml 파일을 보고 싶다면 build/dao/gen/**/model 디렉토리를 보십시오 |
여기 Person.hbm.xml의 내용이 있습니다. |
만약 Hibernate 가 만들어준 Person.hbm.xml 파일을 보고 싶다면 build/dao/gen/**/model 디렉토리를 보십시오 |
여기 Person.hbm.xml의 내용이 있습니다. |
At line 147 changed 1 line. |
이제 다른 columns (first_name, last_name) 을 위한 추가적인 [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] 태그를 작성합니다: |
이제 다른 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. |
위 예제에서 column 속성을 기술한 이유는 데이타베이스 컬럼 이름과 POJO 클래스의 속성 이름이 다르기 때문입니다. |
만약 같다면 column 속성을 기술할 필요가 없습니다.\\ |
이 외에 이 태그에서 사용할 수 있는 다른 속성들에 대해 알고 싶으면 [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] 를 참조하세요. |
위 예제에서 column 속성을 기술한 이유는 데이타베이스 컬럼 이름과 POJO 클래스의 속성 이름이 다르기 때문입니다. |
만약 같다면 column 속성을 기술할 필요가 없습니다.\\ |
이 외에 이 태그에서 사용할 수 있는 다른 속성들에 대해 알고 싶으면 [@hibernate.property|http://xdoclet.sourceforge.net/tags/hibernate-tags.html#@hibernate.property%20(0..1)] 를 참조하세요. |
At line 170 changed 1 line. |
새로 만든 속성들을 데이타베이스 테이블의 column 으로 추가하기 위하여 "ant setup-db" 을 다시 실행 합니다. |
새로 만든 속성들을 데이타베이스 테이블의 column 으로 추가하기 위하여 "ant setup-db" 을 다시 실행 합니다. |
At line 179 changed 1 line. |
만약 column 의 사이즈를 바꾸고 싶다면 @hibernate.property 태그에 length="size" 속성을 기술해 주면 됩니다. 또 필수항목(NOT NULL)으로 설정하고 싶다면 not-null="true" 속성을 기술해 주면 됩니다. |
만약 column 의 사이즈를 바꾸고 싶다면 @hibernate.property 태그에 length="size" 속성을 기술해 주면 됩니다. 또 필수항목(NOT NULL)으로 설정하고 싶다면 not-null="true" 속성을 기술해 주면 됩니다. |
At line 181 changed 1 line. |
!!JUnit 으로 DAO 를 테스트 하기위해 DaoTest 클래스를 만듭니다 [#3] |
!!JUnit 으로 DAO 를 테스트 하기위해 DaoTest 클래스를 만듭니다 [#3] |
At line 184 changed 2 lines. |
이 튜토리얼의 나머지 부분의 모든 클래스들을 자동으로 생성해 주는 __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]으로 부터 기증받은 것을 토대로 만들어 졌습니다. |
이 튜토리얼의 나머지 부분의 모든 클래스들을 자동으로 생성해 주는 __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. |
처음에 나는 tables/pojos, DAOs와 Managers 들의 관계를 1-to-1 으로 만들게 하는 이와 같은 코드 생성 툴을 추가하고 싶지 않았었습니다. 대부분 나의 프로젝트에서는 POJOs 보다 DAOs 와 Managers 들의 수가 훨씬 적었습니다. |
처음에 나는 tables/pojos, DAOs와 Managers 들의 관계를 1-to-1 으로 만들게 하는 이와 같은 코드 생성 툴을 추가하고 싶지 않았었습니다. 대부분 나의 프로젝트에서는 POJOs 보다 DAOs 와 Managers 들의 수가 훨씬 적었습니다. |
At line 189 changed 5 lines. |
기본적으로 AppGen 은 오직 Actions/Controllers와 그 테스트, 그리고 테스트 데이타, i18n 키값들 그리고 JSP 들을 만듭니다. |
또한 이 툴은 Actions/Controllers을 구성(설정)해줍니다. |
\\이 툴은 생성되는 파일의 수를 줄이기 위해 포괄적인 BaseManager 와 BaseDaoHibernate 클래스를 사용합니다.\\ |
''(즉, 여러 POJO에 대해 이 툴을 사용 하더라도 한개의 BaseManager 과 한개의 BaseDaoHibernate 를 사용한다는 뜻인듯.)''\\ |
그러나 여러분이 가끔은 모든 DAO 와 Manager 클래스들을 만들기 원하는걸 알았기 때문에, 나는 그 기능을 옵션으로 추가 했습니다. |
기본적으로 AppGen 은 오직 Actions/Controllers와 그 테스트, 그리고 테스트 데이타, i18n 키값들 그리고 JSP 들을 만듭니다. |
또한 이 툴은 Actions/Controllers을 구성(설정)해줍니다. |
\\이 툴은 생성되는 파일의 수를 줄이기 위해 포괄적인 BaseManager 와 BaseDaoHibernate 클래스를 사용합니다.\\ |
''(즉, 여러 POJO에 대해 이 툴을 사용 하더라도 한개의 BaseManager 과 한개의 BaseDaoHibernate 를 사용한다는 뜻인듯.)''\\ |
그러나 여러분이 가끔은 모든 DAO 와 Manager 클래스들을 만들기 원하는걸 알았기 때문에, 나는 그 기능을 옵션으로 추가 했습니다. |
At line 196 changed 1 line. |
이 툴을 사용하기 위해서는 다음의 순서를 따라해 주세요: |
이 툴을 사용하기 위해서는 다음의 순서를 따라해 주세요: |
At line 199 changed 3 lines. |
# 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:__ 이 태스크를 실행하기전에 지금까지 작업한 내용을 백업해 두세요 - 아니면 적어도 소스코드저장소에 올리기 전에 제대로 돌아가는지 기존코드에는 이상이 없는지 등을 확인해 보세요. 내가 이 태스크를 테스트 했을때는 아주 잘 작동한다고 판단했습니다만 이 태스크는 여러분의 소스트리를 수정한다는것을 알아두세요. |
# 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. |
이제 DAO 클래스를 테스트 하기 위한 DaoTest 클래스를 작성합니다.\\ |
__"잠깐~! 우리는 DAO 클래스를 만든적이 없자나"__ 라고 하는 소리가 들리는군요.\\ |
맞습니다.\\ |
그러나 나는 [Test-Driven Development|http://www.artima.com/intv/testdriven.html] 이 보다 높은 퀄리티를 가지는 소프트웨어를 만들어 낸다는 것을 알았습니다.\\ |
몇년간 나는 __클래스를 작성하기 전에 테스트를 먼저 작성하라__는 것은 바보같은 짓이라고 생각했었습니다.\\ |
그러나 나는 그렇게 해 보았고 그 결과 그것이 훌륭하게 작동되는 것을 알았습니다.\\ |
내가 지금 test-driven 을 한는 이유는 그것이 소프트웨어 개발 프로세스의 속도를 무척 빠르게 해준다는걸 알았기 때문입니다. |
이제 DAO 클래스를 테스트 하기 위한 DaoTest 클래스를 작성합니다.\\ |
__"잠깐~! 우리는 DAO 클래스를 만든적이 없자나"__ 라고 하는 소리가 들리는군요.\\ |
맞습니다.\\ |
그러나 나는 [Test-Driven Development|http://www.artima.com/intv/testdriven.html] 이 보다 높은 퀄리티를 가지는 소프트웨어를 만들어 낸다는 것을 알았습니다.\\ |
몇년간 나는 __클래스를 작성하기 전에 테스트를 먼저 작성하라__는 것은 바보같은 짓이라고 생각했었습니다.\\ |
그러나 나는 그렇게 해 보았고 그 결과 그것이 훌륭하게 작동되는 것을 알았습니다.\\ |
내가 지금 test-driven 을 한는 이유는 그것이 소프트웨어 개발 프로세스의 속도를 무척 빠르게 해준다는걸 알았기 때문입니다. |
At line 219 changed 3 lines. |
시작하기 위해서, 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 변수에 의해 사용될 수 있게 됩니다. |
시작하기 위해서, 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">''나는 주로 이미 만들어 놓은 test (i.e. UserDaoTest.java) 를 copy (열기 → 다른이름으로 저장) 한 후에 find/replace 기능을 이용해 [[Uu]ser 를 [[Pp]erson(object name)으로 바꿉니다.''</font> |
;:<font color="blue">''나는 주로 이미 만들어 놓은 test (i.e. UserDaoTest.java) 를 copy (열기 → 다른이름으로 저장) 한 후에 find/replace 기능을 이용해 [[Uu]ser 를 [[Pp]erson(object name)으로 바꿉니다.''</font> |
At line 251 changed 2 lines. |
JUnit 테스트를 위해서 PersonDao 를 initializes(초기화) 하고 destroys (소멸) 하는 기본적인 코드입니다. |
"ctx" object 는 Spring's ApplicationContext 입니다. 이것은[BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/persistence/BaseDaoTestCase.java.html] 클래스의 static block 에서 초기화 됩니다. |
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. |
자 이제는 DAO의 CRUD(create, retrieve, update, delete) 메소드를 테스트를 해야 합니다. |
이 테스트를 위해서 우리는 test(모두 소문자)로 시작하는 메소드를 만들어야 합니다. |
이 메소드가 Ant build.xml 파일의 <junit> 태스크에 의해 불려 질려면 몇가지 규칙이 필요합니다. |
* 메소드 이름이 test(모두 소문자)로 시작해야 한다 |
* public 메소드여야 한다. |
* 리턴타입이 void 이여야 한다. |
* 전달 인자가 없어야 한다. |
자 이제는 DAO의 CRUD(create, retrieve, update, delete) 메소드를 테스트를 해야 합니다. |
이 테스트를 위해서 우리는 test(모두 소문자)로 시작하는 메소드를 만들어야 합니다. |
이 메소드가 Ant build.xml 파일의 <junit> 태스크에 의해 불려 질려면 몇가지 규칙이 필요합니다. |
* 메소드 이름이 test(모두 소문자)로 시작해야 한다 |
* public 메소드여야 한다. |
* 리턴타입이 void 이여야 한다. |
* 전달 인자가 없어야 한다. |
At line 262 changed 3 lines. |
여기 CRUD 테스트를 위한 간단한 테스트 코드가 있습니다. |
중요한 것은 각각의 메소드들은 자발적으로 일어난다는 점 입니다. |
다음의 메소드들을 PersonDaoTest.java 파일에 추가 합니다: |
여기 CRUD 테스트를 위한 간단한 테스트 코드가 있습니다. |
중요한 것은 각각의 메소드들은 자발적으로 일어난다는 점 입니다. |
다음의 메소드들을 PersonDaoTest.java 파일에 추가 합니다: |
At line 320 changed 1 line. |
;:<font color="blue">''testGetPerson 메소드에서 우리는 person 을 생성 한 후에 get 메소드를 호출했습니다. 나는 주로 내가 항상 사용할 수 있는 레코드를 데이타 베이스에 넣습니다. \\그러나 데이타베이스 테스트를 위하여 [DBUnit|http://www.dbunit.org] 이 사용된 이후로는 test 를 실행하기 전에 metadata/sql/sample-data.xml 파일에 간단히 추가할 레코드 정보를 입력해 놓으면 됩니다:''</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">''이것이 testGetPerson 메소드에서 Person 미리 만들어 놔야 하는 코드를 없앨 수 있는 하나의 방법입니다. 만약 SQL 이나 GUI 툴 등을 이용하여 직접 데이타베이스에 레코드를 넣고 싶다면 "ant db-export" 태스크를 실행 시킨 후 "cp db-export.xml metadata/sql/sample-data.xml" 함으로서 sample-data.xml 새로 만들 수 있습니다.''</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. |
위 예제에서 우리는 객체를 저장하기 전에 그 값들을 설정하기 위하여 person.set*(value) 를 호출하였습니다. |
위 예제에서는 무척 간단했지만(속성이 몇개 없기 때문에) 만약 10개의 필수 필드(not-null="true")를 가지는 개체를 저장한다면 이는 보통 성가신 일이 아닐겁니다. |
이것이 내가 BaseDaoTestCase 에서 ResourceBundle 을 생성했던 이유입니다. |
간단히 PersonDaoTest.java 와 같은 디렉토리에 PersonDaoTest.properties 파일을 넣고 이 파일에 속성 값들을 설정합니다. |
위 예제에서 우리는 객체를 저장하기 전에 그 값들을 설정하기 위하여 person.set*(value) 를 호출하였습니다. |
위 예제에서는 무척 간단했지만(속성이 몇개 없기 때문에) 만약 10개의 필수 필드(not-null="true")를 가지는 개체를 저장한다면 이는 보통 성가신 일이 아닐겁니다. |
이것이 내가 BaseDaoTestCase 에서 ResourceBundle 을 생성했던 이유입니다. |
간단히 PersonDaoTest.java 와 같은 디렉토리에 PersonDaoTest.properties 파일을 넣고 이 파일에 속성 값들을 설정합니다. |
At line 347 changed 1 line. |
그러고 나서 person.set* 메소드 대신 BaseDaoTestCase.populate(java.lang.Object) 을 호출 함으로서 object의 값들을 설정할 수 있습니다. |
그러고 나서 person.set* 메소드 대신 BaseDaoTestCase.populate(java.lang.Object) 을 호출 함으로서 object의 값들을 설정할 수 있습니다. |
At line 355 changed 3 lines. |
아직 PersonDao.class 를 만들지 않았기 때문에 PersonDaoTest 클래스는 컴파일 되지 않을겁니다. 우리는 지금 그것을 작성해야만 합니다. |
PersonDao.java 는 interface 입니다. 그리고 PersonDaoHibernate.java 는 그 인터페이스의 Hibernate 를 이용한 구현입니다. |
자 이것들을 만들어 봅시다. |
아직 PersonDao.class 를 만들지 않았기 때문에 PersonDaoTest 클래스는 컴파일 되지 않을겁니다. 우리는 지금 그것을 작성해야만 합니다. |
PersonDao.java 는 interface 입니다. 그리고 PersonDaoHibernate.java 는 그 인터페이스의 Hibernate 를 이용한 구현입니다. |
자 이것들을 만들어 봅시다. |
At line 359 changed 3 lines. |
!!Object 의 CRUD 처리를 위한 DAO 클래스를 만듭니다 [#4] |
첫째로 구현 클래스들을 위한 기본적인 CRUD 메소드들을 정의한 PersonDao.java interface 를 src/dao/**/dao 에 만들고 CRUD 메소드를 정의합니다. |
''나는 요점만 보여주기 위하여 아래 클래스에 JavaDoc 들을 삭제했습니다.'' |
!!Object 의 CRUD 처리를 위한 DAO 클래스를 만듭니다 [#4] |
첫째로 구현 클래스들을 위한 기본적인 CRUD 메소드들을 정의한 PersonDao.java interface 를 src/dao/**/dao 에 만들고 CRUD 메소드를 정의합니다. |
''나는 요점만 보여주기 위하여 아래 클래스에 JavaDoc 들을 삭제했습니다.'' |
At line 376 changed 3 lines. |
위 클래스의 모든 메소드에 예외를 기술하지 않은것은 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 를 구현한 클래스를 작성해야 할 것입니다. |
위 클래스의 모든 메소드에 예외를 기술하지 않은것은 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. |
;:''태스트를 위한 ant task 는 "test-module." 태스크를 호출합니다. 만약 testcase 파라미터(-Dtestcase=name)에 패스 값을 기술한다면 "test-module." 태스크는 **/*${testcase}* - <span style="color: blue">이것은 우리가 Person, PersonDao, PersonDaoTest 중 어떤것을 패스에 넣어도 상관 없다는 것을 말합니다.</span> - 위 세가지 모두 PersonDaoTest 를 수행할 것입니다. '' |
;:''태스트를 위한 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의 메소드를 구현하는 PersonDaoHibernate class 를 작성합시다. 그리고 Hibernate 를 사용하여 Person object 를 get/save/delete 하는 메소드를 작성해봅시다.\\ |
src/dao/**/dao/hibernate 이곳에 PersonDaoHibernate.java 클래스를 만듭니다. 그리고 이를 반드시 BaseDaoHibernate 를 확장(extends)하고 PersonDao 를 구현(implements)하도록 작성합니다. |
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. |
여기서 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행하려 하면 똑같은 에러가 나올 겁니다. |
우리는 PersonDao 의 구현 클래스는 PersonDaoHibernate 라는 것과 Person object 에 대해 Spring 프레임워크가 알수 있도록 몇가지 파일들을 구성해야 합니다. |
여기서 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행하려 하면 똑같은 에러가 나올 겁니다. |
우리는 PersonDao 의 구현 클래스는 PersonDaoHibernate 라는 것과 Person object 에 대해 Spring 프레임워크가 알수 있도록 몇가지 파일들을 구성해야 합니다. |
At line 419 changed 3 lines. |
!!Person object와 PersonDao를 Spring 프레임워크에 알리기 위해 설정파일을 구성합니다 [#5] |
첫째로, 어디에 Hibernate 매핑파일이 있는지 Spring 프레임 워크에 알려줘야 합니다.\\ |
src/dao/**/dao/hibernate/applicationContext-hibernate.xml 파일을 열어서 Person.hbm.xml 을 다음 코드블럭처럼 추가 합니다. |
!!Person object와 PersonDao를 Spring 프레임워크에 알리기 위해 설정파일을 구성합니다 [#5] |
첫째로, 어디에 Hibernate 매핑파일이 있는지 Spring 프레임 워크에 알려줘야 합니다.\\ |
src/dao/**/dao/hibernate/applicationContext-hibernate.xml 파일을 열어서 Person.hbm.xml 을 다음 코드블럭처럼 추가 합니다. |
At line 435 changed 1 line. |
다음으로 PersonDaoHibernate 와 PersonDao 를 연결하기 위해서 다음의 XML 태그를 이 파일에 끝에 추가 합니다. |
다음으로 PersonDaoHibernate 와 PersonDao 를 연결하기 위해서 다음의 XML 태그를 이 파일에 끝에 추가 합니다. |
At line 445 changed 1 line. |
''<bean> 태그에 autowire="byName" 속성을 기술함으로써 "sessionFactory" property 설정을 없앨수도 있습니다. 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 를 실행 합니다. [#6] |
수정한 모든 파일을 저장하고 다시한번 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행 합니다. |
!!DaoTest 를 실행 합니다. [#6] |
수정한 모든 파일을 저장하고 다시한번 "ant test-dao -Dtestcase=PersonDao" 태스크를 실행 합니다. |
At line 456 changed 1 line. |
''Next Up:'' __Part II:__ [새로운 매니저 작성하기|CreateManager] - (''[Session Facades|http://java.sun.com/blueprints/patterns/SessionFacade.html] 와 비슷하지만 EJBs 를 사용하지 않는'')Business Facades 를 작성하는 방법. DAO 계층과 front-end 계층을 연결하는 창구 역할을 합니다. |
''Next Up:'' __Part II:__ [새로운 매니저 작성하기|CreateManager] - (''[Session Facades|http://java.sun.com/blueprints/patterns/SessionFacade.html] 와 비슷하지만 EJBs 를 사용하지 않는'')Business Facades 를 작성하는 방법. DAO 계층과 front-end 계층을 연결하는 창구 역할을 합니다. |