Whiteship's Note


9. Tag만들기



CustomTag를 공부 하다가 느낀 점은.. 'servlet으로 html 코드 뿌리는 것 같다.', '복잡하네..언제는 뭐 상속 받고 언제는 뭐 상속 받고...어떤거 구현해줘야 하고 뭐를 리턴 해줘야 하고,,,,'

그런데 TagFile을 사용하면 매우 단순하게 태그를 만들 수 있었습니다.

1. Tag로 만들 부분 물색.
2. Tag를 만들었다는 가정하에 Tag를 사용해서 변경.
3. Tag 파일 작성.
4. 확인.

2번 다음에 확인하고 5. 수정하고 싶은 부분 수정하고 다시 확인 요거만 추가 하면 TDD랑 많이 닮은 것 같네요.

1. Tag로 만들 부분 물색.
사용자 삽입 이미지
2. 먼저 위에 있는 빨간색 부분을 다음과 같이 Tag가 있다고 생각하고 바꿔줍니다.
사용자 삽입 이미지
3. 그리고 WEB-INF/tags/os 안에 새로운 태그를 정의해 줍니다. page라는 태그명을 사용했기 때문에 page.tag라는 파일을 작성합니다.
<%@ attribute name="title" required="true" %>
<html>
    <head>
        <title>${title}</title>
        <link rel="stylesheet" type="text/css" href="/css/style.css" />
    </head>
    <body>
        <jsp:doBody />
    </body>
</html>

JSP 페이지 지시자를 사용해서 태그의 속성을 나타내고 EL태그로 원하는 위치에 사용하면 됩니다. 몸체가 있는 태그라면 하늘색 부분 처럼 몸체가 들어갈 부분에 <jsp:doBody /> 태그를 사용해 주면 됩니다. 이밖에도.. JSTL의 <c:set /> <c:if /> 이런 태그들을 이용해서 속성값에 기본 값을 setting하고 조건에 따라 값을 바꿀 수 있습니다.

4. 확인하기.
사용자 삽입 이미지
이런 에러가 납니다. title이 필수 속성이라고 했는데 왜 안넣어줬느냐!! 라는 것인데.. 전 넣는다고 넣어는데?? 라고 생각하고 소스를 다시 보니.. titile 라고 오타를 쳤네요. ㅠ.ㅠ

사용자 삽입 이미지
OK! 수정하고 새로고침을 해보니깐 제대로 나왔습니다.

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top


8.4. 기능 구현



검색 기능을 구현해 봅니다.

1. Dao 테스트에 다음과 같이 "s"로 검색 했을 때 두명이 나올 것이라고 예상합니다. 이런 예상의 근거는 DBUnit을 사용해서 XML에 있는 Data를 넣어서 사용할 것이기 때문에 XML에 있는 데이타를 근거로 삼았습니다.

    public void testGetMembers() throws Exception{
        insertFlatXmlDataSet("test/src/keesun/kSampleData.xml");
        assertEquals(2, kMemberDao.getMembers("s").size());
    }

2. 그리고 이클립스를 보고 있으면 컴파일 에러가 발생하는 것을 확인할 수 있습니다. 당연하죠. getMembers(String)이라는 인터페이스가 MemberDao 에 없기 때문입니다. 만들어 주면 되죠.

public interface KMemberDao extends GenericDao<KMember, Integer>{

    public List<KMember> getMembers(String string);

}

3. 인터페이스에 추가해 줬더니 이젠 이걸 구현한 쪽에서 에러가 발생합니다. 이것을 구현해 주고 테스트의 결과 녹색불이 들어오면 구현이 끝납니다.

    @SuppressWarnings("unchecked")
    public List<KMember> getMembers(final String name) {
        return getHibernateTemplate().executeFind(new HibernateCallback(){
            public Object doInHibernate(Session s) throws HibernateException, SQLException {
                Query q = s.createQuery("from k_Member m where m.name like :name order by m.name asc")
                           .setParameter("name", "%" + name +"%");
                return q.list();
            }
        });
    }

위 코드에서 getHibernateTemplate()으로 HibernateTemplate객체를 받아오고 이 객체의 executeFind() 메소드를 사용해서 자기가 할일을 남(HibernateCallback)을 시켜서 합니다.

구현을 아래 처럼 간단하게 할 수도 있는데요.
        Session s = getSession();
        Query q = s.createQuery("from k_Member m where m.name like :name order by m.name asc")
                      .setParameter("name", "%" + name +"%");
        return q.list();

callback을 사용하는 이유가 있겠죠? 궁금하네요~ *_*

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top


8.3. Criteria 공부하기



특정 Member의 검색을 할 때 이름만 입력할 수도 있고 이메일만 입력할 수도 있습니다. 입력 할 수 있는 곳이 여러 곳이면 둘 다 입력하거나 둘 다 입력하지 않을 수도 있습니다. 이럴 때 입력을 하느냐 안하느냐에 따라 쿼리가 달라지는데요. 이런것을 Dynamic Query라고 하는것 같습니다.

HQL을 이용해서 이러한 쿼리를 다음과 같이 작성할 수 있습니다.
    public void testDynamicQueryByHQL(){
        insertDatas();
        String name = "s";
        String email = null;

        StringBuffer sb = new StringBuffer("from k_Member m where 1=1");
        if(!StringUtils.isEmpty(name)) sb.append(" and m.name like :name");
        if(!StringUtils.isEmpty(email)) sb.append(" and m.email like :email");
        q = s.createQuery(sb.toString());
        if(!StringUtils.isEmpty(name)) q.setParameter("name", "%" + name + "%");
        if(!StringUtils.isEmpty(email)) q.setParameter("email", "%" + email + "%");

        assertEquals(2, q.list().size());
    }

위와 같은 내용의 쿼리를 Criteria를 사용해서 작성하면 다음과 같이 간결해 집니다. 그리고 @Entity의 name속성에 지정해 준 값을 사용하는 것이 아니라 진짜 클래스 명을 사용해야 합니다.
    public void testDynamicQueryByCriteria(){
        insertDatas();
        String name = "s";
        String email = "keesun@os.net";

        Criteria c = s.createCriteria(KMember.class);
        if(!StringUtils.isEmpty(email)) c.add(Restrictions.eq("email", email));
        if(!StringUtils.isEmpty(name)) c.add(Restrictions.like("name", "%" + name + "%"));

        assertEquals(1, c.list().size());
    }

Criteria의 add 메소드는 인자로 Criterion을 넘겨 주어야 하는데요. Restrictions라는 팩토리를 사용해서 Criterion을 받아 오게 됩니다. Restrictions 클래스에는 쿼리에 덧붙일 수 있는 여러 메소드들이 있습니다.

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top


8.2. HQL 공부하기



8.2.1. HQL 공부하기 - select절
8.2.2. HQL 공부하기 - where절
8.2.3. HQL 공부하기 - order by절
8.2.4. HQL 공부하기 - inner join

참조 : http://openframework.or.kr/JSPWiki/Wiki.jsp?page=Javacanhibernate7

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top

TAG HQL

8.2.4. HQL 공부하기 - inner join



insertDatas() 메소드에서 집어 넣는 데이타에서 Member와 Messenger의 모습을 보면 다음과 같습니다.

사용자 삽입 이미지

seal 멤버만 두개의 Messenger 정보를 가지고 있습니다. 이 때 inner join을 하면 다음과 같이 두개의 레코드가 생기게 됩니다.
사용자 삽입 이미지
inner join을 HQL로 하는 방법은 s.create("from Member m inner join m.messengers") 이렇게 콜렉션을 가리키면 됩니다.

public void testJoinHQL(){

       insertDatas();

       q = s.createQuery("from k_Member m inner join m.messengers");

       List<Object> result = q.list();

       // Member m1 | Messenger msg1("keesun", MSN)

       // Member m1 | Messenger msg2("keesun2", Skype)

       assertEquals(2, result.size());

       Object[] result1 = (Object[]) result.get(0);

       assertTrue(result1[0] instanceof KMember);

       assertTrue(result1[1] instanceof KMessenger);

       KMessenger msg1 = (KMessenger) result1[1];

       assertEquals("seal", msg1.getM_id());

       assertEquals(KMessengerType.MSN, msg1.getM_type());

}

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top


8.2.3. HQL 공부하기 - order by절



public void testOrderByHQL(){

       insertDatas();

       q = s.createQuery("select m.name from k_Member m");

       List<String> names1 = q.list();

       StringBuffer sb = new StringBuffer();

       for(String name : names1)

             sb.append(name);

       assertEquals("sealparadozzkeesun", sb.toString());

 

       q = s.createQuery("select m.name from k_Member m order by m.name");

       List<String> names2 = q.list();

       assertEquals(3, names2.size());

       assertEquals("keesun", names2.get(0));

       assertEquals("paradozz", names2.get(1));

       assertEquals("seal", names2.get(2));

}


위에 있는 테스트 코드를 보시면 원래 테이블에 들어있는 이름의 순서는 seal -> paradozz -> keesun 이였는데 두번째 쿼리에서 order by를 사용하고 보니 keesun이 첫번째로 나오게 되는 것을 확인할 수 있습니다.

'Hibernate > 주소록 만들기' 카테고리의 다른 글

9. Tag만들기  (0) 2007.02.12
8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
top

TAG HQL, order by

8.2.2. HQL 공부하기 - where절



가장 간단하게 Where 절을 사용한 HQL은 다음과 같습니다.
s.createQuery("from Member m where m.name = '기선'");

위에서 '기선'과 같은 부분을 파라미터화 하는 방법에는 두 가지가 있습니다.
1. ? 를 사용하는 방법과
2. :를 사용하는 방법이 있습니다.

1. s.createQuery("from Member m where m.name = ? "); 이렇게 파라미터화 할 부분을 ? 로 표시하고 fluent interface 형태로 구현해 놓았기 때문에 뒤에 연달아서 .setParameter(0, "기선"); 을 덧 붙여 주면 됩니다.

2. s.createQuery("from Member m where m.name = :name "); 이렇게 :뒤에 변수 처럼 사용할 이름을 적어주고 .setParameter("name", "기선"); 이렇게 덧붙여 주면 됩니다. 파라미터가 여러개라면 이렇게 이름을 줘서 사용하는 것이 가독성이 좋을 듯 합니다.
이 때 파라미터의 타입을 명확히 주고 싶다면 setString과 같은 메소드를 setParameter대신에 사용하면 됩니다.

3. and 를 사용해서 여러 개의 조건을 줄 수도 있습니다.
이 때 여러 개의 조건을 줄 때 쿼리 결과를 최소한으로 줄여주는 조건문을 앞에 두는 것이 좋습니다.

public void testWhereHQL(){

       insertDatas();

       q = s.createQuery("select m from k_Member m where name='keesun'");

       assertEquals(1, q.list().size());

       //1

       q = s.createQuery("select m from k_Member m where name = ?")

              .setParameter(0, "keesun");

       assertEquals(1, q.list().size());

       //2

       q = s.createQuery("select m from k_Member m where name = :name")

              .setParameter("name", "keesun");

       assertEquals(1, q.list().size());

       //3

       q = s.createQuery("select m from k_Member m where name like :name and email like :email")

              .setString("name", "%a%")

              .setString("email", "%os.net");

       assertEquals(2, q.list().size());

}

'Hibernate > 주소록 만들기' 카테고리의 다른 글

8.4. 기능 구현  (0) 2007.01.25
8.3. Criteria 공부하기  (0) 2007.01.25
8.2. HQL 공부하기  (0) 2007.01.24
8.2.4. HQL 공부하기 - inner join  (0) 2007.01.24
8.2.3. HQL 공부하기 - order by절  (0) 2007.01.24
8.2.2. HQL 공부하기 - where절  (0) 2007.01.24
8.2.1. HQL 공부하기 - select절  (0) 2007.01.24
8.1. DbUnit 사용하기  (0) 2007.01.24
8. DAO 기능 구현하기  (4) 2007.01.23
7.3. 새로운 타입으로 맵핑하기.  (0) 2007.01.22
7.2. 기존 코드 수정하기.  (0) 2007.01.22
top

TAG HQL, where절

8.2.1. HQL 공부하기 - select절



Session에 있는 createQuery(Sring) 메소드를 이용해서 HQL을 사용할 수 있습니다.

가장 간단한 HQL은 다음과 같습니다.
s.createQuery("from Member");

여기서 " "사이에 들어간 부분이 HQL로 SQL과는 차이가 있으며 클래스의 이름은 @Entity의 name속성에 지정한 값을 쿼리에서 사용해야 합니다.[각주:1]

select문 사용하기

1. 모든 멤버를 가져오고 싶을 때 select * from Member SQL에서 이렇게 썼는데요. HQL은 이렇게 쓰면 에러가 발생합니다. select m from Member m 처럼 마치 레퍼런스 변수 만들듯이 표현해 주어야 합니다.

2. 특정 변수만 가져오고 싶을 때는 select m.name from Member m 처럼 가져오고 싶은 필드 명을 m이라는 Member의 인스턴스를 통하여 가져오듯이 표현합니다.

3. 여러개의 변수를 읽어 오면(ex select m.name, m.email from Member) 배열의 리스트로 받아 옵니다. 근데 가져온 값을 사용하기가 좀 복잡하네요.

4. SQL 함수인 count, avg, sum, max, min등의 함수도 사용할 수 있습니다.

public void testSelectHQL() {

       insertDatas();

       //1

       q = s.createQuery("select m from k_Member m");

       assertEquals(3, q.list().size());

       //2

       q = s.createQuery("select m.name from k_Member m");

       List<String> names = q.list();

       assertEquals(3,  names.size());

       assertEquals("seal", names.get(0));

       //3

       q = s.createQuery("select m.name, m.email from k_Member m");

       List<Object> datas = q.list();

       Object[] line1 = (Object[]) datas.get(0);

       assertEquals("seal", (String)line1[0]);

       assertEquals("seal@os.net", (String)line1[1]);

       //4

       q = s.createQuery("select count(*) from k_Member");

       assertEquals(new Long(3), q.uniqueResult());

}

top


8.1. DbUnit 사용하기



1. 먼저 DB에 입력할 dataset을 xml 형태로 작성 합니다.

이 때 주의 하실 점은 Entity와 Attribute의 이름들은 Object의 식별자를 사용하는 것이 아니라 Relation에서 사용되는 이름으로 사용해야 합니다.


2. 입력한 샘플 데이타를 테스트할 메소드를 만들고 DbUnit을 사용하여 DB에 넣습니다.

public void testWithSampleData() throws Exception{

     insertFlatXmlDataSet("test/src/keesun/kSampleData.xml");

}


이상태에서 test를 돌려보고 DbUnit이 동작하는데 이상은 없는지 확인합니다. 만약 위에서 작성한 xml에 매칭되는 컬럼을 못찾을 경우 에러가 발생합니다.

3. 입력한 샘플을 기반으로 간단한 쿼리를 날려서 결과를 확인해 봅니다.

public void testWithSampleData() throws Exception{

      insertFlatXmlDataSet("test/src/keesun/kSampleData.xml");

 

      assertEquals(3, kMemberDao.getAll().size());

      assertEquals(2, kGroupDao.getAll().size());

      assertEquals(4, kMemberGroupDao.getAll().size());

      assertEquals(4, kMessengerDao.getAll().size());

}


테스트는 통과 합니다~ :)
좀더 복잡한 쿼리를 날리기 위해서는 HQL과 Criteria를 공부해야 합니다. 하지만 그다지 어렵지 않다는거~

사용자 삽입 이미지
top


8. DAO 기능 구현하기



5. 모델, DAO 까지 개발 공정
위에서 만들었던 DAO는 기본적이고 매우 널리 사용되는 기능만 있었기 때문에 검색을 하는등의 개발 대상에 특화된 기능을 구현하는 시간을 가졌습니다.

1. 테스트 데이타를 XML -> Table 로 바로 넣어 주는 DBUnit을 사용했습니다.
2. HQL 과 Criteria 를 공부했습니다.
3. Context[각주:1]를 공부했습니다.
  1. http 에서 사용하는 것은 전부 String이기 때문에 적절한 타입으로 변경해 주는 역할도 할 수 있고 객체 단위로 값들을 묶을 수 있는 녀석 [본문으로]
top


7.3. 새로운 타입으로 맵핑하기.



@Type 어노테이션의 type과 parameters 속성에 다음과 같이 설정해 줍니다.

 @Column(nullable = false)
 @Type(type = "net.openseed.core.persist.hibernate.usertype.GenericEnumUserType", parameters = { @Parameter(name = "genericEnumClass", value = "keesun.model.enumeration.KMessengerType") })

 public KMessengerType getM_type() {
  return m_type;
 }

여기서 @Type이랑 @Parameter를 알아봐야겠습니다.

@Type 에 대한 Hibernate Reference에는 이렇게 쓰여있습니다.
@org.hibernate.annotations.Type overrides the default hibernate type used: this is generally not necessary since the type is correctly inferred by Hibernate. Please refer to the Hibernate reference guide for more informations on the Hibernate types.
기본 type을 재정의 하는데 사용되는 어노테이션이군요.

@Parameter에 대한 설명은 찾기가 조금 힘드네요. 레퍼런스를 보니까 @TypeDef라는 어노테이션 안에서 비슷하게 사용된 것을 볼 수 있었습니다.

HIA2판을 뒤져 봤습니다. 5.3.4 Creating a UserType 이라는 장부터 5.3.7 Mapping Enumeration에 걸쳐서 Hibernate에 있는 컬럼의 기본 타입이 아닌 새로운 타입으로 지정하고 싶을 때 위와 같은 방식을 사용한 것 같습니다.
top


7.2. 기존 코드 수정하기.



1. Messenger 클래스의 m_type 변수의 타입을 MessengerType으로 수정하기.

 KMessengerType m_type;

2. Getter, Setter코드 부분을 다음과 같이 수정합니다.

 public KMessengerType getM_type() {
  return m_type;
 }

 public void setM_type(KMessengerType m_type) {
  this.m_type = m_type;
 }

3. Test 코드에서 발생하는 에러도 수정합니다.

//KMessengerDaoTest.java
KMessenger m = KMessengerFixture.getAMessenger("keesun", KMessengerType.Skype);

//KMessengerFixture.java
public static KMessenger getAMessenger(String m_id, KMessengerType m_type)

이렇게 수정을 하는데에는 몇분이 채 소요되지 않으며 이클립스의 도움이 큽니다. 에러가 나는 부분에는 전부 빨간 불이 들어오고 Ctrl + 1로 제안을 볼 수 있어서 매우 편했습니다.

top


7.1. MessengerType 클래스 작성.



1. GenericDao 상속 받기.

public class KMessengerType extends GenericEnum

2. GenericDao<클래스명, 값의 타입> 입력하기.

public class KMessengerType extends GenericEnum<KMessengerType, String>

3. 생성자는 private 타입으로 변경하기.

    private KMessengerType(String value, String descr) {
        super(value, descr);
    }

4. 원하는 enum을 public final static 변수로 생성하기.

    public static final KMessengerType MSN = new KMessengerType("M", "MSN");
    public static final KMessengerType NATE = new KMessengerType("N", "Nate On");
    public static final KMessengerType GOOGLE = new KMessengerType("G", "Google Talk");
    public static final KMessengerType Skype = new KMessengerType("S", "Skype");

5. DB에 어떻게 저장되어야 할지 나타내 주는 getType 메소드 정의하기.

    public static int getType() {
        return Types.CHAR;
    }

전체 코드 보기
top


7. Enumeration 사용하도록 리팩터링



Messenger의 Type과 Member의 Role에 특정 값만 들어 갈 수 있도록 하는 것이 보다 효율적으로 판단되어 Enum을 사용하도록 수정합니다.

1. GenericEnum 을 상속 받는 MessengerType고 RoleType 클래스를 작성합니다.

2. Messenger 클래스와 MemberGroup 클래스에 있는 messegerType과 role변수의 타입을 변경합니다.

3. 새로운 타입으로 매핑하기.
top


6.5. DAO 테스트에서 연관 관계 테스팅



테스트의 시나리오는 다음과 같습니다.

멤버1 = 기선, 멤버2 = 승택님, 멤버3 = 물개 선생님
그룹1 = Agile Java Network, 그룹2 = OpenSeed

이들의 관계는 다음 그림과 같습니다.
사용자 삽입 이미지
위와 같은 멤버의 그룹정보를 세팅하고 맞게 들어갔는지 각 멤버가 소속된 그룹의 갯수를 확인하여 봅시다.

테스트 코드 보기

하늘색 부분이
        keesun.join(agileJavaNetwork, "운영 요원");
        keesun.join(openSeed, "일반 회원");
        paradozz.join(openSeed, "일반 회원");
        seal.join(openSeed, "운영자");
이런 식으로 처리가 되면 좋겠다는 생각을 해봅니다.
top


6.4. 연관 관계 처리를 위한 메소드 구현.



Member와 Messenger의 연관 관계에서 만약에 어떤 Member 객체가 새로운 메신저 정보를 추가했다면 Member에 있는 messengers에 새로운 Messenger 객체가 추가 되어야 하고, 추가되는 Messenger 객체에 있는 member라는 멤버 변수는 자기 자신으로 세팅되어야 합니다.

즉 다음과 같은 두 줄의 코드가 필요합니다.
getMessengers().add(messenger);
messenger.setMember(this);
이 두줄의 코드는 항상 붙어있어야 하기 때문에 하나의 메소드로 묶어 둡니다.

삭제도 마찬자기로 다음의 두 줄의 코드가 묶여 있어야 합니다.
getMessengers().remove(messenger);
messenger.setMember(null);

위 코드들을 Member 클래스의 messenger의 게터 세터 아래에 구현해 둡니다.
    @OneToMany(mappedBy="member")
    public Set<KMessenger> getMessengers() {
        if(messengers == null) messengers = new HashSet<KMessenger>();
        return messengers;
    }
    public void setMessengers(Set<KMessenger> messengers) {
        this.messengers = messengers;
    }
    public void addMessenger(KMessenger messenger){
        getMessengers().add(messenger);
        messenger.setMember(this);
    }
    public void deleteMessenger(KMessenger messenger){
        getMessengers().remove(messenger);
        messenger.setMember(null);
    }

게터에 보시면 빨간 줄로 한줄의 코드가 삽입 되었는데요. 이 것은 처음으로 새로운 Messenger 정보를 추가하려고 할 때 getMessengers()를 출력하는데 이 때 Set 객체가 없기 때문에 null pointer exception이 발생하기 때문입니다.
top


6.3. 연관 매핑 정보 입력하기



Member와 MemberGroup의 1대다 관계를 표시해 보겠습니다.

1. Member의 getMemberGroup 메소드 위에 @OneToMany 어노테이션을 사용해서 Member입장에서 이 관계가 1대다 임을 표시합니다.

이때 @OneToMane의 속성중에 mappedBy의 값에 상대방 객체에서 자기 자신의 객체를 참조하는 멤버 변수 이름을 적어 줍니다.
MemberGroup에서는 Member객체를 member라는 변수로 참조 하고 있기 때문에 다음과 같이 적어 줍니다.

    @OneToMany(mappedBy="member")
    public Set<MemberGroup> getMemberGroups() {
        return memberGroups;
    }

2. MemberGroup의 getMember 메소드 위에는 @ManyToOne 을 사용해서 MemberGroup 입장에서는 이 관계가 다대1 임을 표시합니다.

이 때 Owner Side를 1대다 관계에서 '다'쪽에 해당하는 MemberGroup으로 정하기위해서 @JoinColumn을 추가하고 속성중에 name 속성을 참조하는 객체가 가지고 있는 주키에 해당하는 멤버변수의 이름(Join관계에서 자신의 FK에 해당하는 상대방의 PK)을 적어 줍니다.

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="memberId")
    public Member getMember() {
        return member;
    }

3. 클래스를 로딩할 시점에 이 객체와 연관된 다른 객체들을 미리 읽어 들이겠냐는 설정을 합니다.

위에 보이는 FetchType.LAZY 로 설정하면 getMember 메소드가 호출 될 시점에 연관된 객체들을 불러 오게 됩니다. 이와 반대로 연관된 객체를 클래스 로딩 시점에서 모두 읽어들이고 싶을 때는 FetchType.EAGER 로 설정을 하면 됩니다. 저희가 사용하고 있는 JPA의 default 값은 EAGER 입니다.
top


6.2. 필요한 멤버 변수 추가



1. 연관을 맺기 위해서 필요한 필드들을 새로 추가합니다.

Member 모델에 필요한 필드
- Set<MemberGroup> memberGroups;
- Set<Messenger> messengers;

Messenger 모델에 필요한 필드
- Member member;

Group 모델에 필요한 필드
- Set<MemberGroup> memberGroups;

MemberGroup 모델에 필요한 필드
- Member member;
- Group group;

2. 각각의 세터 게터들을 추가합니다.

Alt + Shift + S -> R 단축키 사용.
게터 세터 추가하실 때 팁은.. 새로 추가되는 메소드를 맨 뒤에 생성하기 위해서 커서를 마지막 메소드 아래에 위치 하시고 추가하시면 좋습니다. 게터 세터 메소드를 추가하는 기본 위치 설정이 현재 커서의 위치로 되어 있어서요. :)
top


6.1. 모델 간의 연관 관계 파악



1. Cardinality 파악
사용자 삽입 이미지

한 명의 멤버는 여러 개의 메신저 정보를 가질 수 있습니다.
하나의 메신저 정보는 한 명의 멤버에 매칭 됩니다.

한 명의 멤버는 여러 개의 그룹 정보를 가질 수 있으며
하나의 그룹은 여러 명의 멤버 정보를 가질 수 있습니다.

But... 둘 사이의 연관으로 인해 Role(그룹에서의 멤버의 역할)이라는 정보와 Joined(멤버가 그룹에 가입한 날짜)와 같은 추가적인 정보가 발생합니다. 이러한 Data는 Member나 Group 어느 한쪽에 포함되는 것 보다는 연관으로 인해 발생하는 Data이기 때문에 연관 개체가 필요한 듯 싶어서 MemberGroup 모델을 만들었습니다.

따라서, 한 명의 멤버는 여러 개의 멤버그룹 정보를 가질 수 있으며
하나의 그룹은 여러 개의 멤버그룹 정보를 가질 수 있습니다.
하나의 멤버 그룸 정보는 한명의 멤버 정보와 한명의 그룹 정보에 매칭이 됩니다.

2. Direction 파악
사용자 삽입 이미지
모든 연관 관계가 전부 양방향성을 가지고 있다고 생각했습니다.
혹시 이 중에서 단방향성을 가지고 있는 것은 없는지 생각해 봐야겠습니다.

top


6. 연관 관계 매핑하기



1. 모델 간의 연관 관계 파악
1.1. cardinality 파악. 1대1, 1대다, 다대다 확인.
1.2. direction 파악. 단방향, 양방향 확인.

2. 필요한 멤버 변수 추가.
Set, Map, List and so on.

3. JPA(Java Persistent API) 사용하여 모델위에 매핑 정보 표시.
2.1. cardinality 표현.
2.2. direction 표현.
2.3. Fetching Strategy 설정. FetchType.EAGER or FetchType.LAZY

4. 연관 관계를 처리하기 위한 메소드 구현.

5. DAO 테스트에서 연관 관계 테스팅.
top


5-4. DAO 테스트 만들기



1. test/src 소스 폴더에 keesun.messenger 패키지 안에 MessengerDaoTest 클래스를 생성합니다.
사용자 삽입 이미지
2. 이 클래스는 AbstractTransactionalDataSourceSpringContextDaoTest 이 클래스를 상속 받습니다. 이 클래스는 Spring에 있는 AbstractTransactionalDataSourceSpringContextTests 클래스를 상속하여 만들어진 클래스 입니다.

public class MessengerDaoTest extends AbstractTransactionalDataSourceSpringContextDaoTest{

 

3. 테스트 대상인 MessengerDao를 protected로 변수를 만들고 다음과 같이 bean이 생성됐는지 확인하는 테스트를 만듭니다.

       protected MessengerDao messengerDao;

 

       public void testValidBean(){

             assertNotNull(messengerDao);

       }


테스트는 실패 합니다. 이전 글에서 등록한 빈의 이름이 memberDao로 쓰였네요;; 오타입니다. messengerDao로 수정을 하고 다시 테스트를 하면 통과합니다.

4. Member 객체를 memberDao를 이용해서 DB에 집어 넣는 테스트를 해봅니다. 이 때 MessengerFixture라는 객체를 만들어서 넘겨주는 클래스를 만들어서 사용합니다.

       public void testModel(){

             Messenger m = MessengerFixture.getAMessenger();

             messengerDao.add(m);

             assertTrue(m.getMessengerId()>0);

       }

//MessengerFixture.java

public class MessengerFixture {

 

       public static Messenger getAMessenger() {

             return new Messenger();

       }

}


5. 하지만 이 때 에러가 발생하는데 이유는 필수 요소인(nullable=false) 필드들의 값을 입력하지 안았기 때문에 발생하게 됩니다. 따라서 다음과 같이 수정을 하면 테스트가 통과 합니다.

public void testModel(){

      Messenger m = MessengerFixture.getAMessenger("keesun", "skype");

      messengerDao.add(m);

      assertTrue(m.getMessengerId()>0);

}
//MessengerFixture.java

public static Messenger getAMessenger(String m_id, String m_type) {

     Messenger messenger = new Messenger();

     messenger.setM_id(m_id);

     messenger.setM_type(m_type);

     return messenger;

}

top


5-3. DAO 만들기



1. MessengerDao 인터페이스를 src 소스폴더에 keesun.member.dao 패키지 안에 만듭니다.
사용자 삽입 이미지

2. MessengerDao 인터페이스는 GenericDao 인터페이스를 상속받습니다. GenericDao는 generic을 사용하고 있는데요 첫번째 인자는 클래스 타입이고 두번째 인자는 클래스의 주키값의 타입을 넣습니다.

public interface MessengerDao extends GenericDao<Messenger, Integer>{

 

}


3. MessengerDao를 구현할 MessengerDaoHibernate 클래스를 만듭니다. 이 클래스는 MessengerDao를 implements하고 GenericDao를 구현해 둔 AbstractHibernateGenericDao 클래스를 상속 받습니다.

public class MessengerDaoHibernate extends AbstractHibernateGenericDao<Messenger, Integer>

implements MessengerDao{

}


4. 그러면 에러가 발생하는데 이 때 다음과 생성자를 만들면 에러가 사라집니다. 이것으로 Dao 구현이 끝났습니다.

       protected MessengerDaoHibernate() {

             super(Messenger.class);

       }


5. 방금 만든 dao를 bean으로 등록합니다.

사용자 삽입 이미지

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.3. 연관 매핑 정보 입력하기  (2) 2007.01.18
6.2. 필요한 멤버 변수 추가  (0) 2007.01.18
6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
top


5-2. 간단한 모델 테스트



1. 간단한 테스트를 위해서 sandbox.keesun 패키지 안에 MessengerTest.java를 만듭니다.
사용자 삽입 이미지
2. MessengerTest는 AbstractTransactionalDataSourceSpringContextDaoTest 클래스를 상속 받습니다.

public class MessengerTest extends AbstractTransactionalDataSourceSpringContextDaoTest


3. 다음과 같이 코딩합니다.

       public void testCRUD() {

             Messenger m = new Messenger();

             m.setM_id("keesun");

             m.setM_type("skype");

             s.save(m);

             assertTrue(m.getMessengerId() > 0);

       }


DB에 저장이 된다면 객체에 messengerId가 데이타를 가지게 되므로 그것을 확인하는 코드입니다.

테스트를 돌리면 실패합니다. bean을 등록하지 않아서 그렇습니다. 헤헷;
bean은 다음과 같이 applicationContext-dao.xml에 등록합니다.

사용자 삽입 이미지

4. 이제 테스트를 돌리면 pass합니다. :)
사용자 삽입 이미지

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.2. 필요한 멤버 변수 추가  (0) 2007.01.18
6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
top


5-1. 모델 만들기



Messenger 모델을 만들도록 하겠습니다.

1. 프로젝트에서 keesun.model 패키지 안에 Messenger.java파일을 만듭니다.
사용자 삽입 이미지
2. Messenger 객체가 가지고 있어야 할 정보들과 주키 역할을 할 surrogate key[각주:1]를 지정합니다.

public class Messenger {

       Integer messengerId;

 

       String m_id;

 

       String m_type;

}

3. Alt + Shift + S -> R 단축키를 사용해서 먼저 ID에 해당하는 messengerId 에 대한 게터 세터를 만들어 줍니다.
사용자 삽입 이미지
4. 그런 뒤 나머지 프로퍼티에 대한 게터 세터로 같은 방법으로 만들어 줍니다. 이렇게 하는 이유는 주키에 관한 프로퍼티가 제일 위에 만들어지게 하기 위한 것이죠. 헤헷 일종의 센스인듯 합니다.

5. 이제 매핑 정보를 입력합니다. 매핑 정보는 여기서 다룬적이 있기 때문에 패스 합니다. :)
지금은 모델들 간의 연관관계는 신경쓰지 않고 딱 모델신경을 쓰고 있습니다.
  1. natural key와 surrogate key에 대한 내용은 여기를 참조 하세요. [본문으로]

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top


5. 모델, DAO 까지 개발 공정



1. 모델 만들기 - 모델에 두 가지 정보가 들어감.(객체에 관한 정보 + 맵핑에 관한 정보)
-> model bean 등록
2. 간단한 모델 테스트 - 하이버네이트의 Sesssion 객체를 이용한 CRUD 테스트.
3. DAO 만들기 - 인터페이스 사용, GenericDao를 사용하여 만들기.
-> dao bean 등록
4. DAO 테스트 만들기 - 롤백, JUnit의 테스트를 이용할 수 있슴.


'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top


4. CSS 적용




사용자 삽입 이미지

얼추 페이지들이 만들어졌습니다. 확장자만 JSP로 바꿨을 뿐 모두 빈껍데기 라는거~

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top


3. 화면 만들기



디자인이 전~혀 없는 완전 HTML 뼈다귀 입니다.
index.html -> memberList.html 로 갑니다.
사용자 삽입 이미지
위에서 Add New Member를 클릭하면 memberInput.html 로 갑니다.

위에서 멤버의 이름을 클릭하면 그 사람의 정보를 자세히 볼 수 있는 memberView.html로 이동합니다.

첫화면에서 검색창에 찾을 키워드를 입력한 뒤 엔터를 치면 search,html로 이동합니다.

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top


2. 주소록 ERD 수정



생각해보니...블로그를 두 개이상 운영하는 경우가 적어서 Member 테이블의 컬럼으로 추가했습니다.
사용자 삽입 이미지
우와~ 테이블 하나 쭐었다~
사용자 삽입 이미지

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top

TAG ERD

1. 주소록 ERD



물개 선생님과 함께 개발할 주소록의 ERD를 그려봤습니다. 프로젝트 일정은 매우 빡쎕니다. 하지만 내기를 했기 때문에 해내야 합니다.
사용자 삽입 이미지
Member와 Group의 관계에 대한 설명
한명의 멤버는 여러개의 그룹에 소속될 수 있으며
하나의 그룹은 여러 명의 멤버를 포함합니다.
이 때 멤버는 그룹에 반드시 속해야 하는 것은 아닙니다.
하지만 그룹은 적어도 2명의 멤버가 있어야 존재 합니다.

Member와 Messengers의 관계에 대한 설명
한명의 멤버는 여러개의 메신저ID를 가질 수 있고
하나의 메신저 ID는 한명의 멤버에 대한 것입니다.

Member와 Bolgs의 관계에 대한 설명
한명의 멤버는 여러개의 블로그를 가지고 있을 수 있고
하나의 블로그는 한명의 관리자가 있습니다.
(팀블로그의 경우 팀블로그 회원이 아닌 팀블로그 마스터가 관리자입니다.)

컬럼 들이랑 주키를 표현한 것인데 FK를 어떻게 나타내는 것인지 몰라서 Member_id 와 같은 식으로 FK를 나타냈습니다.
사용자 삽입 이미지
Spring 으로 개발 중인 주소록은 Member 테이블 달랑 하난데 이거 큰일났군요.

'Hibernate > 주소록 만들기' 카테고리의 다른 글

6.1. 모델 간의 연관 관계 파악  (0) 2007.01.18
6. 연관 관계 매핑하기  (0) 2007.01.18
5-4. DAO 테스트 만들기  (2) 2007.01.11
5-3. DAO 만들기  (0) 2007.01.11
5-2. 간단한 모델 테스트  (0) 2007.01.11
5-1. 모델 만들기  (0) 2007.01.11
5. 모델, DAO 까지 개발 공정  (0) 2007.01.11
4. CSS 적용  (0) 2007.01.08
3. 화면 만들기  (0) 2007.01.07
2. 주소록 ERD 수정  (0) 2007.01.06
1. 주소록 ERD  (0) 2007.01.06
top

TAG ERD