2013-04-22 5 views
8

ベストプラクティスはサービス層とダオ層の両方を持ち、サービスレベルで@Transactionalアノテーションを追加することです。しかし、私の場合、それは私のサービスクラスの大半がDAOメソッドを繰り返すために作られたことを意味しています...それはかなり刺激的です。サービスクラスのrepeatig DAOメソッドを避けるには? @トランザクションアノテートされたDAOクラスとサービスクラス - それは受け入れられるものですか?

例えば、

public interface FooDAO { 
public List<FooVO> list(int cathegoryId); 
public List<FooVO> list(int cathegoryId, int ownerId); 
} 

@Service 
@Transactional 
public class FooService { 
    protected @Autowired FooDAO dao; 
    public List<FooVO> list(int cathegoryId) { 
     dao.list(cathegoryId); 
    } 
    public List<FooVO> list(int cathegoryId, int authorId) { 
     dao.list(cathegoryId, authorId) 
    } 
} 

どのようにダムですか?

ほとんどの場合、私は本当に魅力的なサービス方法は必要ありません。通常、それは例えばgetingの問題です。カテーテルの記述と、カテーテルと一致するエンティティのリスト。だからこそ私は単純化されたソリューションを探しています。 DAOを繰り返さないようにジェネリック薬を使用するのと同じくらい鮮明なもの:D http://www.javablog.fr/javahibernate-dont-repeat-the-dao-with-a-genericdao.html

私は答えを探しました。他の中で私は Where does the @Transactional annotation belong? を読んだがまだ私の答えが見つかりませんでした。

@TransactionalでDAOメソッドを注釈するのは本当に悪い考えですか? http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategyに触発されて解決策を見つけました。私は(本当に必要とされている)だけで一つのサービスクラスを持っているし、他のすべての(単純)例のための@Transactional

  • とそのメソッドに注釈を付ける

    • :私は@TransactionalとDAOのメソッドに注釈を付けるWHAT IF

      (伝播= Propagation.MANDATORY)と@Transactionalと私のコントローラメソッド(伝播= Propagation.REQUIRES_NEW)

    ** UPDATE 1 **

    これは次のようになります:

    public interface FooDAO { 
    @Transactional(propagation = Propagation.MANDATORY, readOnly=true) 
    public List<FooVO> list(int cathegoryId); 
    ... 
    } 
    
    @Service 
    public class FooService { 
        protected @Autowired FooDAO dao; 
    
        @Transactional // propagation REQUIRED 
        public List<FooVO> magic(FooVO fooVO) { 
         //do sth complicated here ;) 
        } 
        // We do not repeat DAO methods in the Service class. 
        // No wrapping methods here !!! 
    } 
    
    @Controller 
    public class FooMagicController { 
        protected @Autowired FooService fooService; 
        ... 
         fooService.magic(fooVO); 
        ... 
    } 
    @Controller 
    public class FooController { 
        protected @Autowired FooDAO dao; //DAO wired directly in the Controller class !!! 
    
        @Transactional(propagation = Propagation.REQUIRES_NEW) 
        @RequestMapping(".....") 
        public String listFoo(Model model,...) throws Exception { 
         model.addAttribute("list", dao.list(13)); 
         return "xyz"; 
        } 
    } 
    

    いずれの場合も、DAOは「上に」管理されているセッションを使用します。

    非常に悪い考えですか?私が必要とするものを達成するためのより良い方法はありますか?

  • +0

    私は同様の質問を発見しました:http://stackoverflow.com/questions/4462785/transactional-controller-vs-service "はい、あなたのコントローラメソッドに@Transactionalを追加することは完全に有効です。" "コントローラは永続レイヤを意識するべきではなく、コントローラレイヤが存在しないデスクトップアプリケーションでビジネスロジックを再利用する必要があります。" –

    答えて

    2

    アプリケーションを設計するために選択した状況によりますが、それは悪い考えではありません。

    あなたが感じるのであれば、サービスクラス(すなわち、純粋なDAO APIを超えるAPIを持つクラス)は必要ありません。サービスクラスを避け、コントローラに直接自動配線されたDAO実装を使用する方が良いと感じています。 。

    しかし、ロジックを追加してAPIとして公開する必要がある場合は、そのカスタムロジックを実装するサービスクラスと、上記のDAOメソッドのラッパー関数を記述することができます)。これにより、サービスクラスをコントローラに配線するだけで、サービスクラスのラッパーAPIを使用してDAO呼び出しを行うことができます。

    カスタムAPIのサービスクラスのみを保持し、DAOのラッパーAPIを持たない場合、データアクセス呼び出しを行う必要がある場合は、DAOをコントローラクラスに接続する必要があります。この場合、事実上、DAOをServiceクラスとControllerクラスで結ぶことになります。

    UPDATE 1ここで

    は、サンプルプロジェクトの1

    コントローラーから私のコントローラとサービスクラスです

    public class HomePageController { 
    
    
    @Autowired 
    private VideoService videoService; 
    
        //Controller method 
    @RequestMapping(value = "/tag/mostviewed") 
    public @ResponseBody 
    Map<String, List<Video>> showMostViewedVideosForTag(){ 
          //service api 
          videoService.getMostViewedVideo(curatorTagName) 
         } 
    
    } 
    

    Serviceクラス

    @Service(value = "videoService") 
    @Transactional(readOnly = true) 
    public class VideoServiceImpl implements VideoService { 
    
    @Autowired 
    private VideoDAO videoDAO; 
    
    @Autowired 
    private TagDAO tagDAO; 
    
    // WRAPPER API FOR THE DAO 
    
    @Override 
    public List<Video> getMostViewedVideo(String tagName) { 
        return videoDAO.getMostViewedVideo(tagName); 
    } 
    
    
    // A non wrapper API which does some business logic 
    @Override 
    @Transactional 
    public void assignTagsToVideo(String videoId, String userId, String... tags) { 
    
         for (String tag : tags) { 
          if (tagHeritageDAO.getTagHeritage(tag, videoId, userId) == null) { 
           Tag tagObj = tagDAO.getTag(tag); 
           if (tagObj != null) { 
            //some logic here to add tags to video 
           } 
          } 
         } 
    
        videoDAO.update(video); 
    } 
    } 
    

    ご覧のとおり唯一のサービスはワイヤーですdをコントローラクラスに、daoをサービスクラスに接続します。これは私が混在モードを意味するものです。私があなたを混乱させたら謝ります。

    +0

    最後の段落で私のケースが説明されています。つまり、トランザクション型サービスとtrnsactional DAOを混在させることは悪い習慣ではありません。そして、私が理解しているように、あなたは私に何か他の人に助言してくれなかったので、おそらくこの状況では最高の解決策でしょうか? –

    +0

    はい。私は混合モードでそれを使用しているので、私のコントローラーはダオのものではなく、サービスクラスにしか話していません。それは論理のより良い分離です。 –

    +1

    待ち合わせ、混在モードは私のために何かを意味します。つまり、サービスを使用するコントローラもあれば、DAOを使用するコントローラもあります。私はそれが混乱するかもしれないことを知っている(私は自分のコードで作業する人を意味する)が、私の場合は意味をなさない。 –

    関連する問題