둘러보기 생략.
 

GenericDao에 적합한 Domain 구조가 궁금합니다.

안녕하세요
질문하나 드립니다.

GenericService, GenericDao를 적용하기에 적합한 Domain 구조가 궁금합니다.
질문이 좀 모호한데요....

업무를 설계할때 GenericService, GenericDao를 적용해 CRUD 관점에서 접근하려다 보니
Domain을 테이블 단위로 설계할때에는 전혀 문제가 없어 보이는데
여러가지 업무가 복합된 도메인을 설계하게 되면 CUD 처리가 조금 애매해 보입니다.
단위 테이블을 도메인화 했을 경우만 Generic을 써야하는건지...

혹시나, 이런 부분에 대한 가이드 라인이 있는지 궁금합니다.

Re] GenericDao에 적합한 Domain 구조가 궁금합니다.

GenericService는 단위 테이블과 매핑된 Domain 객체를 기반으로 기본적인 CRUD를 제공하는 서비스입니다. 단 테이블간의 관계 정보를 해당 Domain 객체에 반영할 수 있습니다.

예를 들어, Movie.java와 Genre.java라는 도메인 클래스가 있고 이들은 각각 MOVIE, GENRE 테이블과 매핑된다라고 가정해 보겠습니다.
테이블 GENRE : MOVIE = 1:M 단방향 관계를 가지고 있다면 이 관계를 도메인 클래스에 반영하여 Movie.java 클래스 내에 Genre 객체를 포함하게 됩니다.

public class Movie implements Serializable {
    private String movieId;
    ...
    private Genre genre;
    //getter, setter
}
public class Genre implements Serializable {
   ...
}

위와 같은 경우 MOVIE 테이블에 Movie 정보를 입력하기 위해서 Movie 객체를 전달해야 할 것입니다. 이때, Movie 객체는 내부의 Genre 객체를 통해 Genre 정보를 포함하고 있을 수 있습니다.
GenericService + QueryService를 사용하는 경우라면 QueryService 실행을 위한 매핑 XML 파일 내에 INSERT문을 다음과 같이 정의할 수 있습니다.

<query id="createMovie">
    <statement>
	INSERT INTO MOVIE (movie_id, title, director, genre_id, actors, runtime, release_date, ticket_price, 
            now_playing, poster_file)
	VALUES (:vo.movieId, :vo.title, :vo.director, :vo.genre.genreId, :vo.actors, :vo.runtime, 
            :vo.releaseDate, :vo.ticketPrice, :vo.nowPlaying, :vo.posterFile)
    </statement>
</query>

또한 입력된 MOVIE 정보를 조회하기 위한 SELECT문은 다음과 같이 정의할 수 있습니다.

<query id="findMovieList">
    <statement>
	SELECT movie.movie_id, movie.title, movie.director, genre.name, movie.actors, 
            movie.release_date, movie.now_playing, movie.poster_file, movie.ticket_price
	FROM MOVIE movie, GENRE genre
	WHERE movie.genre_id = genre.genre_id 
	AND title like '%' || :vo.title || '%'
	AND movie.now_playing = :vo.nowPlaying
    </statement>
    <result class="myapp.domain.Movie">
        <result-mapping column="{name}" attribute="{genre.name}" />
    </result>
</query>

GenericService 기반에서 테이블 간의 관계를 반영한 도메인 클래스를 사용한다면 복합 정보 처리는 가능합니다.

친절한 답변 감사드립니다.

안녕하세요~
우선 친절한 답변 감사드립니다.

업무 진행에 상당히 도움이 될듯 합니다^^
한가지 더 질문드리려고 합니다.

Genre를 구성하고 있는 Movie 객체가 존재할 경우에 대해서
위의 예제에서는 Genre 데이터는 이미 DB에 모두 존재하고
Movie 데이터를 생성할때 Genre ID를 Movie의 Field에 반영하도록 했는데요

예를 들어, Movie 데이터를 생성할 때 Genre의 데이터 또한 같이 생성되어야 하는 경우에는 어떻게 처리되어야 할까요?
이 경우에 저는, Movie Service에 Genre Dao도 별도로 주입하여 Genre 데이터를 생성해야하는 경우에는 Genre Dao를 통해 인서트하고
Movie 데이터는 Movie Service에 연결되어 있는 Movie Dao를 통해서 인서트 하도록 작업했었는데요..
이런 방법이 괜찮은지.. 아니면 더 나은 방법이 있는지 궁금합니다.

다시 한번 답변 부탁드리겠습니다~

답변드립니다. ^^

Generic Service의 경우 대표적인 ORM(Object Relational Mapping) 도구인 Hibernate 개념을 일부 도입하여 개발되었습니다.
Hibernate의 경우 속성 정의에 따라 별도 쿼리문의 정의 없이 내부 복합 객체의 정보가 존재하지 않는 경우 그 객체 정보도 함께 INSERT하게 됩니다.
그런데 Generic Service의 경우에는 아직 이 부분까지 구현되어 있지 않으므로 각각의 도메인에 대해 INSERT가 이루어져야 하며, 언급하신 바와 같이 작업하시면 무리는 없을 것 같습니다.
단, Genre와 Movie 정보가 하나의 컴포넌트 내에서 다루게 될 경우 각 구현체에서 Injetion해서 사용 가능하나 만일 Genre와 Movie가 별도의 컴포넌트로 분리되어 설계된 경우에는 Movie Service에서 GenreDao를 직접 Injection하지 않고 Genre Service를 통해 처리하도록 하는 것이 좋을 것 같습니다.
즉, 컴포넌트간의 Communication은 인터페이스를 통해서 이루어지도록 설계함으로써 해당 컴포넌트의 Contract와 Implementation 영역을 명확히 분리(Separate of Concern)할 수 있고 이로 인해 구현체의 변경이 유리합니다.

감사합니다~

조금 명확해진 기분이네요~
답변 감사드립니다.