Redis RedisTemplate 的 execute()方法
Redis 批量操作
如果频繁地使用Redis,比如在 for循环中调用 redis,有时可能会报错: Could not get a resource from the pool。
这是因为 Redis的连接数是有限的,打开了Redis的连接,用完记得要关闭,如果连接数不够了就会报错。
Redis 批量操作,可以使用 RedisTemplate 的 execute()方法。
RedisTemplate 源码
-
org.springframework.data.redis.core.RedisOperations
-
org.springframework.data.redis.core.RedisTemplate
RedisTemplate 的 execute()方法
org.springframework.data.redis.core.RedisTemplate#execute(org.springframework.data.redis.core.SessionCallback
execute() 方法,可以在一次连接中进行多个命令操作。执行完会自动关闭连接。
/**
* Executes a Redis session. Allows multiple operations to be executed in the same session enabling 'transactional'
* capabilities through {@link #multi()} and {@link #watch(Collection)} operations.
*
* @param <T> return type
* @param session session callback. Must not be {@literal null}.
* @return result object returned by the action or <tt>null</tt>
*/
@Override
public <T> T execute(SessionCallback<T> session) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// 打开连接
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return session.execute(this);
} finally {
//执行完会自动关闭连接
RedisConnectionUtils.unbindConnection(factory);
}
}
execute()的SessionCallback参数和RedisCallback参数
SessionCallback 比 RedisCallck 更好些,优先使用 SessionCallback 。
使用SessionCallback , 还可以配合multi() 和 watch() 进行事务操作。
/**
* Executes the given action within a Redis connection. Application exceptions thrown by the action object get
* propagated to the caller (can only be unchecked) whenever possible. Redis exceptions are transformed into
* appropriate DAO ones. Allows for returning a result object, that is a domain object or a collection of domain
* objects. Performs automatic serialization/deserialization for the given objects to and from binary data suitable
* for the Redis storage. Note: Callback code is not supposed to handle transactions itself! Use an appropriate
* transaction manager. Generally, callback code must not touch any Connection lifecycle methods, like close, to let
* the template do its work.
*
* @param <T> return type
* @param action callback object that specifies the Redis action. Must not be {@literal null}.
* @return a result object returned by the action or <tt>null</tt>
*/
@Nullable
<T> T execute(RedisCallback<T> action);
/**
* Executes a Redis session. Allows multiple operations to be executed in the same session enabling 'transactional'
* capabilities through {@link #multi()} and {@link #watch(Collection)} operations.
*
* @param <T> return type
* @param session session callback. Must not be {@literal null}.
* @return result object returned by the action or <tt>null</tt>
*/
@Nullable
<T> T execute(SessionCallback<T> session);
execute() 使用示例:
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void testExecute() {
String userId = "userId";
stringRedisTemplate.opsForValue().set(userId+"123", "lin");
stringRedisTemplate.opsForValue().set(userId+"456", "wu");
stringRedisTemplate.opsForValue().set(userId+"789", "chen");
Map<String, String> map = new HashMap<>();
stringRedisTemplate.execute(new SessionCallback<String>() {
@Override
public <K, V> String execute(@NonNull RedisOperations<K, V> redisOperations) throws DataAccessException {
List<String> list = Arrays.asList("123", "456", "789");
for (String id : list) {
String key = userId + id;
String value = (String) redisOperations.opsForValue().get(key);
map.put(key, value);
}
return null;
}
});
map.forEach((k, v) -> System.out.println(k + ",val:" + v));
}