88

のドキュメントから:

@Cacheable(value="bookCache", key="isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

キーとして@Cachable使用するようisbnに指定するにはどうすればよいですか?checkWarehouse

4

6 に答える 6

104

更新: 現在の Spring キャッシュ実装は、特に指定されていない限り、すべてのメソッド パラメーターをキャッシュ キーとして使用します。選択したキーを使用する場合は、一意のキーを作成する最も簡単な方法であるSpEL リストを使用するArjan の回答を参照してください。{#isbn, #includeUsed}

春のドキュメントから

デフォルトの鍵生成戦略は、Spring 4.0 のリリースで変更されました。Spring の以前のバージョンでは、複数のキー パラメーターに対して、パラメーターの hashCode() のみを考慮し、equals() を考慮しないキー生成戦略を使用していました。これにより、予期しないキーの競合が発生する可能性があります (背景については、SPR-10237 を参照してください)。新しい「SimpleKeyGenerator」は、このようなシナリオに複合キーを使用します。

Spring 4.0 より前

Spel 式のパラメーターの値を のようなものと連結することをお勧めしますkey="#checkWarehouse.toString() + #isbn.toString()")。org.springframework.cache.interceptor.ExpressionEvaluator が Object を返すため、これは機能するはずです。これは後でキーとして使用されるため、提供する必要はありません。intSPEL 式の an 。

衝突確率の高いハッシュコードはキーとして使えません。

このスレッドの誰かが使用を提案しまし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 が出力されます。

PS実際には、私たちが持っている参照ドキュメントで

@Cacheable(value="books", key="T(someType).hash(#isbn)") 
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

キーは一意である必要があるため、この例は間違っていて誤解を招くものであり、ドキュメントから削除する必要があると思います。

PPSは、デフォルトのキー生成に関するいくつかの興味深いアイデアについて、https: //jira.springsource.org/browse/SPR-9036 も参照してください。

正確さのために、そして楽しい数学的/コンピューター科学の事実として、組み込みハッシュとは異なり、MD5 や SHA256 などの安全な 暗号化ハッシュ関数を使用することを追加したいと思います。そのような関数のプロパティにより、これ絶対に可能です。ただし、毎回計算するにはコストがかかりすぎる可能性があります。詳細については、たとえば Dan Boneh 暗号化コースを参照してください。

于 2012-12-29T01:16:51.293 に答える
90

Spring 3.2 でいくつかの限定的なテストを行った後、SpEL list: を使用できるようです{..., ..., ...}。これには、null値を含めることもできます。Spring はリストをキーとして実際のキャッシュ実装に渡します。Ehcache を使用すると、ある時点でList#hashCode()が呼び出され、すべての項目が考慮されます。(Ehcache がハッシュ コードのみに依存しているかどうかはわかりません。)

これを共有キャッシュに使用します。この場合、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" />

...と:

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;
    }
}
于 2013-07-01T14:13:37.787 に答える
5

たとえば、JDK 1.7 では、Spring-EL 式を使用できます。

@Cacheable(value="bookCache", key="T(java.util.Objects).hash(#p0,#p1, #p2)")
于 2012-12-28T16:24:17.070 に答える
1

これはうまくいきます

@Cacheable(value="bookCache", key="#checkwarehouse.toString().append(#isbn.toString())")
于 2013-05-31T12:38:09.410 に答える
-1

これを使って

@Cacheable(value="bookCache", key="#isbn + '_' + #checkWarehouse + '_' + #includeUsed")
于 2014-06-11T03:04:56.540 に答える