scwanglijun / ehcache-spring-annotations

Automatically exported from code.google.com/p/ehcache-spring-annotations
0 stars 1 forks source link

Hash collision in composite keys #90

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Annotate a method with a composite key, i.e:

@Cacheable(cacheName="customersCache")
public List<Customer> getCustomersForUser(Credentials credentials) {...}

2. Make sure Credentials implements hashcode and equals
3. Create two different Credentials instances c1 and c2 with same hashcode but 
equals() = false

What is the expected output? 

getCustomersForUser(c1)!=getCustomersForUser(c2)

What do you see instead?
getCustomersForUser(c1)==getCustomersForUser(c2)

What version of the product are you using? 
1.1.3

On what operating system?
Ubuntu 10.04 64bit

Please provide any additional information below.

Original issue reported on code.google.com by g.georgovassilis@gmail.com on 4 Nov 2011 at 10:48

GoogleCodeExporter commented 9 years ago
Configure a different CacheKeyGenerator: 
http://code.google.com/p/ehcache-spring-annotations/wiki/CacheKeyGenerators

Original comment by eric.dalquist on 4 Nov 2011 at 12:23

GoogleCodeExporter commented 9 years ago
I have been thinking about the same thing recently.. So you are denying that 
hash-collisions can occur? I believe that ehcache-spring-annotations runs under 
the assumption that hashCode is unique for different identities.

If I am wrong - which cache-key generator will guarantee me the correct result 
for the use case in this issue? 

Original comment by olv...@gmail.com on 11 Jan 2012 at 2:36

GoogleCodeExporter commented 9 years ago
If your method arguments all implement hashCode and equals correctly 
ListCacheKeyGenerator would be the only completely infallible option. It has 
the downside that your method arguments are now stored in the cache as the key.

I'm in no way denying that hash collisions can occur. Which is why I suggested 
you use a key generator that is better suited to your needs. The Java hashCode 
is not a true cryptographic hash so no only will there be collisions they will 
be significantly more common.

If you still want to use hashing based key generation you could use the 
MessageDigestCacheKeyGenerator which uses a true cryptographic hashing 
algorithm though it is still using the hashCode of each key argument as the 
data source which can cause problems.

Original comment by eric.dalquist on 11 Jan 2012 at 4:25

GoogleCodeExporter commented 9 years ago
eric: thank you for pointing out the side effect of storing keys in memory. I 
admit that I was baffled after you rejected this ticket at the apparent blunt 
disregard for java conventions regarding object equality :-) But your last 
remark about having to actually store the key to invoke the equals() method 
totally makes sense.

Original comment by g.georgovassilis@gmail.com on 11 Jan 2012 at 4:35

GoogleCodeExporter commented 9 years ago
No, I completely acknowledge the issues around using hashCode for equality. It 
sucks pretty badly but is there for those that can't use true equality 
comparisons.

MessageDigestCacheKeyGenerator provides a slightly improved option and if your 
objects have toString methods that include all relevant "state" information 
StringCacheKeyGenerator is another option. It does toString on each argument 
and uses the big generated String as the key.

As we look forward to JSR107 and the 2.0 version of this library we will likely 
change our default key generator to ListCacheKeyGenerator

Original comment by eric.dalquist on 11 Jan 2012 at 5:49

GoogleCodeExporter commented 9 years ago
ListCacheKeyGenerator is my friend then - thanks for the explanation. I didn't 
really understand that this generator does what I need from the example in the 
docs.

I also agree that changing to this generator as the default would be a good 
idea - especially since the gotcha communicated by this issue is 
under-communicated in the docs (imho)..

I am used to using EHCache, and sinche it stores the key-object along with the 
value in an Element - I implicitly thought this was the case in this project as 
well. Anyway, I start to know the quirks now, and ehcache-spring-annotations in 
most cases beats working directly with EHCache!

Original comment by olv...@gmail.com on 13 Jan 2012 at 9:01