@Cacheable(value="bookCache", key="isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
キーとしてisbn
およびcheckWarehouse
を使用するように@Cachable
を指定するにはどうすればよいですか?
Update:現在指定されていない場合、現在のSpringキャッシュ実装はすべてのメソッドパラメータをキャッシュキーとして使用します。選択したキーを使用する場合は、 Arjan's answer を参照してください。これは、一意のキーを作成する最も簡単な方法であるSpELリスト{#isbn, #includeUsed}
を使用します。
From Spring Documentation
デフォルトのキー生成戦略は、Spring 4.0のリリースで変更されました。 Springの以前のバージョンでは、複数のキーパラメーターに対して、equals()ではなくパラメーターのhashCode()のみを考慮したキー生成戦略を使用していました。これにより、予期しないキーの衝突が発生する可能性があります(背景については、SPR-10237を参照してください)。新しい「SimpleKeyGenerator」は、このようなシナリオに複合キーを使用します。
Spring 4.0以前
Spel式のパラメーターの値をkey="#checkWarehouse.toString() + #isbn.toString()")
のようなものと連結することをお勧めします。 SPEL式でint
を指定する必要はありません。
衝突確率が高いハッシュコードについては、をキーとして使用できません。
このスレッドの誰かがT(Java.util.Objects).hash(#p0,#p1, #p2)
を使用することを提案していますが、うまくいかず、このアプローチは簡単に破られます。たとえば、 SPR-9377 からのデータを使用しました:
System.out.println( Objects.hash("someisbn", new Integer(109), new Integer(434)));
System.out.println( Objects.hash("someisbn", new Integer(110), new Integer(403)));
私の環境では両方の行が-636517714を出力します。
追伸実際に参照ドキュメントにあります
@Cacheable(value="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
キーは一意である必要があるため、この例は間違っており、誤解を招くものであり、ドキュメントから削除する必要があると思います。
P.P.S.デフォルトのキー生成に関する興味深いアイデアについては、 https://jira.springsource.org/browse/SPR-9036 も参照してください。
正確さのために、そしてSHA256のような安全な 暗号化ハッシュ関数 を使用して、そのような関数のプロパティのために_が_であることを面白い事実として追加したいと思いますこのタスクでは可能ですが、毎回計算するのは費用がかかりすぎる可能性があります。
Spring 3.2での限られたテストの後、SpELリスト{..., ..., ...}
を使用できるようです。これには、null
値を含めることもできます。 Springは、リストをキーとして実際のキャッシュ実装に渡します。 Ehcacheを使用すると、そのような時点で List#hashCode() が呼び出され、すべてのアイテムが考慮されます。 (Ehcacheonlyがハッシュコードに依存しているかどうかはわかりません。)
これを共有キャッシュに使用します。共有キャッシュでは、キーにも メソッド名を含む 、Springのデフォルトキージェネレーター 含まない を使用します。この方法で、さまざまな方法で一致するキーを危険にさらすことなく(多すぎる...)、(単一の)キャッシュを簡単に消去できます。好む:
@Cacheable(value="bookCache",
key="{ #root.methodName, #isbn?.id, #checkWarehouse }")
public Book findBook(ISBN isbn, boolean checkWarehouse)
...
@Cacheable(value="bookCache",
key="{ #root.methodName, #asin, #checkWarehouse }")
public Book findBookByAmazonId(String asin, boolean checkWarehouse)
...
もちろん、多くのメソッドがこれを必要とし、常にキーにすべてのパラメーターを使用している場合、クラスとメソッド名を含むカスタムキージェネレーターを定義することもできます。
<cache:annotation-driven mode="..." key-generator="cacheKeyGenerator" />
<bean id="cacheKeyGenerator" class="net.example.cache.CacheKeyGenerator" />
... with:
public class CacheKeyGenerator
implements org.springframework.cache.interceptor.KeyGenerator {
@Override
public Object generate(final Object target, final Method method,
final Object... params) {
final List<Object> key = new ArrayList<>();
key.add(method.getDeclaringClass().getName());
key.add(method.getName());
for (final Object o : params) {
key.add(o);
}
return key;
}
}
たとえば、JDK 1.7でSpring-EL式を使用できます。
@Cacheable(value="bookCache", key="T(Java.util.Objects).hash(#p0,#p1, #p2)")
これは動作します
@Cacheable(value="bookCache", key="#checkwarehouse.toString().append(#isbn.toString())")