3

Spring / Hibernate/jspの標準スタックと一般的なレイヤーを使用するJavaEEアプリケーションがあります。

  • @Repository(またはDAO)
  • @サービス
  • @コントローラ

各リポジトリには、いくつかのfind ...メソッドがあります(たとえば、BookRepositoryの場合:単純なfindById、findByTitle、findByAuthor、より複雑なfindMostUsed、findMostCommentedなど)。

サービス層には、リポジトリを呼び出すビジネスロジックが含まれています。

コントローラはサービスメソッドを呼び出し、JSPで使用されるModelAndViewにデータを入力します。

もちろん、サービスには複雑なビジネスロジックを持つメソッドがあります。しかし、次のような愚かな方法がたくさんあるのは面倒です。

public List<Book> findMostUsed() {
    return repository.findMostUsed();
}
public List<Book> findMostCommented (boolean includeRating) {
    return repository.findMostCommented(includeRating);
}
...

したがって、これらは単なる委任です(これらの検索メソッドにはビジネスロジックはありません。リポジトリ内のDBクエリがすべての選択とグループ化を行います)。

リポジトリ内のメソッドを変更する必要がある場合は、サービスも変更する必要があります。2年間の開発の後、これらのメソッドにロジックを追加する必要はありませんでした。クエリとそのパラメータのみが変更されました。

人々がコントローラー->ファサード->サービス->リポジトリ->DAOを作成し、すべてのレイヤーがこのようなメソッドで溢れているという、さらに悪いデザインを見ました。

より良いデザインは何でしょうか?

たぶん、これらすべてのメソッドを削除し、サービスをより汎用的なものに変換します(単一のBookService(単一責任の原則に違反する)ではなく、BookPricingService、BookRatingServiceなど)。次に、コントローラーはサービスレイヤーとリポジトリレイヤーの両方を呼び出しますが、これは適切ではありません。

たぶん、findByCriteria(criteria)などのfindメソッドをより一般的にして、その数を減らします。ただし、問題はクエリが非常に異なることであり、これは、基準タイプに基づいて正しいクエリ/パラメータを選択する一種のswitch-caseブロックで終了します。ところで、Spring-Dataは、@Queryアノテーションを使用してクエリごとに1つのメソッドも推奨しています。

たぶん、これは抽象化レイヤーを持つために支払うべき価格ですか?

4

1 に答える 1

2

そのような単純なゲッターの場合、私は自分のまたは必要な場所に@Repositoryストレートを注入し、リポジトリに。で注釈を付けます。その注釈は、メソッドがトランザクション内で使用される必要があることを示しており、まだ存在しない場合はメソッドを作成します(ただし、トランザクション内にすでに存在する場合は秒を作成しません)。@Controller@Service@Transactional(propagation = Propagation.REQUIRED)

サービスクラスは、複数のルートアグリゲート/エンティティが操作されている場合、つまり2種類のリポジトリがある場合に使用する必要があります。erviceは、1つの作業単位に必要なメソッドをバンドルしているため、同じトランザクションの一部になります。

また、さまざまなパターンや依存関係にうんざりしました。

また、criteraクエリとジェネリックスを使用して、非常によく似たメソッドを多数回避しています。

@Transactional(readOnly = true)
    public <T> List<T> getFieldLike(String fieldName, String value) {
        final Session session = sessionFactory.getCurrentSession();
        final Criteria crit = session.createCriteria(genericType).add(Restrictions.ilike(fieldName, value, MatchMode.ANYWHERE));
        return crit.list();
    }

    @Transactional(readOnly = true)
    public <T> List<T> getFieldsEq( final Map<String, Object> restrictions) {
        final Session session = sessionFactory.getCurrentSession();
        final Criteria crit = session.createCriteria(genericType);
        for (final Map.Entry<String, Object> entry : restrictions.entrySet()) {
            crit.add(Restrictions.eq(entry.getKey(), entry.getValue()));
        }
        return crit.list();
    }
于 2013-03-14T13:45:34.273 に答える