-
Notifications
You must be signed in to change notification settings - Fork 5
FAQ
Q. What @Cached annotation can be used for?
A. Any method that has realization and returns the value can be cached. Thus the following can not be cached:
- abstract method
- native method
- interface method
- void method
The annotation is used for THIS ONLY method and does not apply to overriding methods and methods that invoke it
The method can have a random number of parameters (or can’t have it at all). The methods parameters must realize correctly methods equals and hashCode (to put it in hash vocabulary) or can be primitive (int, float, etc.).
Cached methods with several parameters can have significantly worse productivity than methods with one parameter (although that can also depends on its realization)
By default cached methods are synchronized by Read-Write lock'у ( ordinary Lock is used beginning with 2.0.5 version)
Q. Can arrays be used as cache keys?
A. Yes. Arrays will be compared elementwise with the help of Arrays.equals, and hash will be calculated through Arrays.hashCode
Q. Can some parameter be ignored?
A. Yes. Use the annotation @Ignore for this parameter. Ignoring a parameter usually says of bad design.
Q. What if I am not satisfied with standart keys hashCode and equals? (I want the cache to ignore case of String-keys)
A. With the @HashingStrategy annotation for each parameter of cache method, it can be used you strategy of hashing and Trove. These strategies must inherit from the corresponding class TXxxHashingStrategy, where Xxx – is the name of primitive type or Object.
For reference types redefinition of method equals is allowed
There are few default hashing strategies
-
TObjectIdentityHashingStrategy– compares objects to referential equality; -
ArrayHashingStrategy- compares arrays with the help of methodsArrays.deepEquals,Arrays.deepHashCode; -
XxxArrayHashingStrategy(Xxx– primitive name) - compares arrays with the help of methodsArrays.equals,Arrays.hashCode; - The cited strategies are used by default for arrays, and to indicate the strategy
TObjectIdentityHashingStrategysimple annotation@IdentityHashingcan be used.
@Cached
Value cached(
int[][] key1, // this key will be compared for equality content
@IdentityHashing int[][] key2) // this key will be compared for referential equalityQ. How to clean my cache?
A. The right way – is to organize the right work of the resources so it would be cleaned automatically
There is another way – use methods MxCache.getCleaner() for cleaning
MxCache.getCleaner().clearCacheByClass(MyClassWithCaches.class); // cleans all copies cache of its class and all statistic cache of the class
MxCache.getCleaner().clearCacheByInstance(instanceOfClassWithCaches); // cleans all caches of the transferred copy
MxCache.getCleaner().clearCacheByAnnotation(MyAnnotation.class); // cleans all caches with given annotationYou can also clean cache on purpose by setting the app
MxCache.getCleaner().clearCacheByGroup("group name"); // cleans all caches that have the indicated group
MxCache.getCleaner().clearCacheByTag("tag name"); // cleans all caches that have the transmitted tag in its tag list.Example:
@Cached(group = "DB", tags = "ClearWhenDBUpdated.someTable")
public Value someMethod(Key key) {
return executeSQL("SELECT * FROM someTable");
}
statement.executeUpdate("DELETE FROM someTable WHERE dt < '2012-04-03'");
MxCache.getCleaner().clearCacheByTag("ClearWhenDBUpdated.someTable");More correct variant that prevents dirty read:
MxResource someTable = MxResourceFactory.getResource("DB.someTable");
@Cached
public Value someMethod(Key key) {
someTable.readStart();
try {
return executeSQL("SELECT * FROM someTable");
} finally {
someTable.readEnd();
}
}
someTable.writeStart();
try {
statement.executeUpdate("DELETE FROM someTable WHERE dt < '2012-04-03'")) {
} finally {
someTable.writeEnd(); // all dependant resources are cleared
}The following variant is completely analogical but is shorter:
@Cached
@ResourceDependency("DB.someTable")
public Value someMethod(Key key) {
return executeSQL("SELECT * FROM someTable");
}
MxResource someTable = MxResourceFactory.getResource("DB.someTable");
someTable.writeStart();
try {
statement.executeUpdate("DELETE FROM someTable WHERE dt < '2012-04-03'")) {
} finally {
someTable.writeEnd(); // all dependant resources are cleared
}Q. What if I want to perform an action without hitting the cache?
A. You can execute an action by wrapping your code into Runnable and passign it to MxCache.withoutCache(Runnable). All the code inside your runnable will be performed without affecting cache (it will not be used both for reading and writing).
Example:
public class Test {
private static String value = "initial value";
@Cached
public static String get() {
return value;
}
public static void main(String[] args) {
System.out.println(get()); // it will output "initial value"
value = "new value";
System.out.println(get()); // it will output "initial value" as the value hasn't changed
MxCache.withoutCache(new Runnable() {
public void run() {
System.out.println(get()); // it will output "new value" as it completely ignores cache
}
});
System.out.println(get()); // it will output "initial value" again as cache is not affected by MxCache.withoutCache, the saved value remains the same
MxCache.getCleaner().clearCacheByClass(Test.class);
System.out.println(get()); // now it will output "new value" as previous line clears the cache
}
}Sample output:
initial value
initial value
new value
initial value
new value