RedisTemplate:execute与executePipelined

1.官网注释

execute
@Nullable
public <T> T execute(RedisCallback<T> action)
  • Description copied from interface: RedisOperations
    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.

Specified by:
execute in interface RedisOperations

  • Type Parameters:
    T – return type
  • Parameters:
    • callback object that specifies the Redis action. Must not be null.
  • Returns:
  1. result object returned by the action or null

从以上注释可知,该方法执行给定的Action在一次redis连接中。执行完成之后可以返回多个结果(List)。但是需要注意的是,它本身不支持解决事务,如果需要多个操作为一个事务,需要使用专门的TransactionSynchronizationManager。当然了,如果我们一系列操作都是查询,不需要开启事务,使用这个很好。

executePipelined
public List<Object> executePipelined(SessionCallback<?> session)
  • Description copied from interface: RedisOperations
    Executes the given Redis session on a pipelined connection. Allows transactions to be pipelined. Note that the callback cannot return a non-null value as it gets overwritten by the pipeline.

Specified by:
executePipelined in interface RedisOperations

  • Parameters:
    • Session callback
  • Returns:
  1. of objects returned by the pipeline

所以,两者的区别就在注释中一目了然了。executePipelined是可以允许我们执行事务的。executePipelined还有一个需要注意的点,就是虽然重写了回调函数,但是回调函数还是有可能返回空值的。注释里说是在被管道覆盖的时候,这是在说什么呢?

2.executePipelined

public List<Object> executePipelined(final SessionCallback<?> session, final RedisSerializer<?> resultSerializer) {
        Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
        Assert.notNull(session, "Callback object must not be null");

        RedisConnectionFactory factory = getConnectionFactory();
        // bind connection
        RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
        try {
            return execute(new RedisCallback<List<Object>>() {
                public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.openPipeline();
                    boolean pipelinedClosed = false;
                    try {
                        Object result = executeSession(session);
                        if (result != null) {
                            throw new InvalidDataAccessApiUsageException(
                                    "Callback cannot return a non-null value as it gets overwritten by the pipeline");
                        }
                        List<Object> closePipeline = connection.closePipeline();
                        pipelinedClosed = true;
                        return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
                    } finally {
                        if (!pipelinedClosed) {
                            connection.closePipeline();
                        }
                    }
                }
            });
        } finally {
            RedisConnectionUtils.unbindConnection(factory);
        }
    }

这里判断了executeSession的返回结果是否非空,这个函数最终会调用下面这个函数:

    /**
     * Executes all the given operations inside the same session.
     * 
     * @param operations Redis operations
     * @return return value
     */
    <K, V> T execute(RedisOperations<K, V> operations) throws DataAccessException;

正如注释中所说的那样,这个函数会执行当前会话中的所有的operation,以判断是否已经有了操作,保证该事务不被其它操作干扰。

点赞