I’m testing out Spring’s @Cacheable features with EHCache but I can’t find anything on whether this works with Spring’s @Transactional annotations.
I am placing @Cacheable and @CacheEvict on DAO methods while @Transactional are on service methods.
Suppose my User DAO looks like this:
@Cacheable(value="users", key="#id")
User find(BigInteger id);
@CacheEvict(value="users", key="#user.id")
void update(User user);
@CacheEvict(value="users", key="#id")
void delete(BigInteger id);
A problem may arise when, for example, getUser() is called while removeFriend() is in progress, because the user with the stale friend count would be re-cached (or would it?):
public User getUser(userId) {
return userDao.find(userId);
}
@Transactional
public void removeFriend(userId, friendId) {
friendDao.remove(friendId);
user.setFriendCount(--numFriends);
userDao.update(user);
// do some other stuff
}
How can I ensure that this doesn’t update the cache before the database transaction has completed? Do I place @CacheEvict on service methods in addition to the DAO methods? Or, do I add read/write locking to the service methods? And if so to locking, are there any libraries to lock based on id since I would only want to lock on each user instead of locking globally, e.g. @GuardedBy("userLocks.getReadLock(#userId)")? Is there a generally accepted way of handling caching and transactions?
Many thanks!
I should’ve looked into EHCache documentation a bit more because the answer is here.
EHCache 2.4+ works with Spring’s @Transactional annotation. Just need to configure a transaction manager lookup.