私は春の初心者です。私が提供するすべてのことに非常に興奮しています!@Cacheableアノテーションを使用した実世界のDAOのベストプラクティス
今、私は既存のプロジェクトにいくつかのDAOを近代化しようとしています。 具体的には、古いプレーンJDBCコードをSpring Jdbcサポートに置き換え、Springの透過的なキャッシュを導入したいと考えています。
最初の質問は:私は、DAO層が
@Cacheable
注釈を追加するための適切な場所である右のことですか?それとも、ビジネス層でやっていますか?私はネット上にあるすべての簡単な例に従うことができます。しかし、それはより多くの現実の世界にコードを来るとき、私は立ち往生:
を具体的に、私は私のモデル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
を追加します(多くのパブリッシャが存在し、重いオブジェクトであると仮定します)。
この周辺のベストプラクティスはでなければならない - よくあることに問題がありますか? ありがとうございました。
2つの質問に2つの質問を入れる方が良いです。 – Raedwald
'findVisiblePublishers'メソッドの結果をキャッシュしないのはなぜですか?はい、最初に呼び出されたときに2つのDBクエリを実行しますが、それだけです。私はそれがキャッシュのための良いターゲットだと思う。 – Mikhail
ありがとうMikhail。これは、返された(およびキャッシュされた)パブリッシャのすべてのリストのPublisherオブジェクトをキャッシュするためです。上記のgetPublisher(id)を使用したアプローチは機能しません。同じクラスからgetPublisher(id)を呼び出すと、キャッシュは要求されませんが、毎回DB要求が実行されます。つまり、同じパブリッシャの2つのインスタンスがリストに1回キャッシュされ、1回は1つのアイテムとしてキャッシュされます。もっと似たような方法があると、状況が悪化します。 – marc82ch