2013-06-11 12 views
5

私は春の初心者です。私が提供するすべてのことに非常に興奮しています!@Cacheableアノテーションを使用した実世界のDAOのベストプラクティス

今、私は既存のプロジェクトにいくつかのDAOを近代化しようとしています。 具体的には、古いプレーンJDBCコードをSpring Jdbcサポートに置き換え、Springの透過的なキャッシュを導入したいと考えています。

  1. 最初の質問は:私は、DAO層が@Cacheable注釈を追加するための適切な場所である右のことですか?それとも、ビジネス層でやっていますか?

  2. 私はネット上にあるすべての簡単な例に従うことができます。しかし、それはより多くの現実の世界にコードを来るとき、私は立ち往生:

を具体的に、私は私のモデルPublisherのインスタンスを返すいくつかの方法があります。私の手動キャッシュ実装では、常に1つのインスタンスしかキャッシュされておらず、異なるgetPublisher()メソッドに対してフェッチされていることを確認しました。しかし、@Cacheableを使用し、DAO内でキャッシングをカプセル化しようとすると、(プロキシのために)ローカルメソッド呼び出しでアノテーションが機能しないという問題があります。

はここに私のサンプルコードです:

@Cacheable("publisherCache") 
public Publisher getPublisher(int publisherId) 
{ 
    String sql = "SELECT * FROM publisher LEFT JOIN publisherContacts USING (publisherId) WHERE publisherId=? ORDER BY publisherContactId ASC"; 
    return getJdbcTemplate().query(sql, publisherResultSetExtractor, publisherId); 
} 

public List<Publisher> findVisiblePublishers() 
{ 
    List<Publisher> publishers = new LinkedList<Publisher>(); 
    for (int publisherId : findVisiblePublisherIds()) 
    { 
     publishers.add(getPublisher(publisherId)); 
    } 
    return publishers; 
} 

@Cacheable(value = "publisherCache", key = "'list'") 
private List<Integer> findVisiblePublisherIds() 
{ 
    String sql = "SELECT publisherId FROM publisher WHERE isVisible='yes' ORDER BY imprintName"; 
    return getJdbcTemplate().queryForList(sql, Integer.class); 
} 

public Publisher findNearestPublisher(String appx) 
{ 
    appx = "%" + appx + "%"; 
    String sql = "SELECT publisherId FROM publisher WHERE publisherName LIKE ? OR imprintName LIKE ? ORDER BY imprintName DESC LIMIT 1"; 
    Integer publisherId = getJdbcTemplate().queryForObject(sql, Integer.class, appx, appx); 
    if (publisherId == null) 
     return null; 
    else 
     return getPublisher(publisherId); 
} 

これは動作しません、言ったように私の考えでした。

私は今見ることができる唯一の選択肢は以下のとおりです。

A)のみgetPublisher(publisherId)方法をキャッシュし、そのint S(publisherIds)、またはリストを返すようにPublisher sを返します他のすべてのメソッドを定義します。これはAPIの観点から自然なことではありません。サービスやビジネスロジックとして、IDだけでなく、DAOからインスタンスを取得することが期待されます。

b)キャッシュを複製し、必要以上に多くのメモリを使用して、すべてのメソッドに@Cacheableを追加します(多くのパブリッシャが存在し、重いオブジェクトであると仮定します)。

この周辺のベストプラクティスはでなければならない - よくあることに問題がありますか? ありがとうございました。

+0

2つの質問に2つの質問を入れる方が良いです。 – Raedwald

+0

'findVisiblePublishers'メソッドの結果をキャッシュしないのはなぜですか?はい、最初に呼び出されたときに2つのDBクエリを実行しますが、それだけです。私はそれがキャッシュのための良いターゲットだと思う。 – Mikhail

+0

ありがとうMikhail。これは、返された(およびキャッシュされた)パブリッシャのすべてのリストのPublisherオブジェクトをキャッシュするためです。上記のgetPublisher(id)を使用したアプローチは機能しません。同じクラスからgetPublisher(id)を呼び出すと、キャッシュは要求されませんが、毎回DB要求が実行されます。つまり、同じパブリッシャの2つのインスタンスがリストに1回キャッシュされ、1回は1つのアイテムとしてキャッシュされます。もっと似たような方法があると、状況が悪化します。 – marc82ch

答えて

0

共通パターンは次のとおりです。 永続性レイヤーでは、休止状態の第2レベルのキャッシュを使用します。 サービス層では、@Cacheableを使用して、長い計算やWebサービス呼び出しの結果などをキャッシュします。

+0

こんにちはアントン、あなたの答えをありがとう。これは私の最初の質問の一部です。だから、DAOレイヤーでDBの要求を保存する目的(私はHibernate/JPAを使うことはできません)のときに、そうしています。とにかく、サービス層でさえ、私は質問2と同じ問題を抱えています。サービスレベルに@Cacheableを移動しても、重複キャッシュの問題は解決しません。 – marc82ch

関連する問題