spring-projects / spring-data-redis

Provides support to increase developer productivity in Java when using Redis, a key-value store. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
https://spring.io/projects/spring-data-redis/
Apache License 2.0
1.77k stars 1.17k forks source link

`StringRedisConnection` returns `null` using read operations during transactions #2953

Open CHYhave opened 3 months ago

CHYhave commented 3 months ago

A minimize cases as belong, which expect return some value but get null。

    @GetMapping("/get")
    @Transactional
    public String get(@RequestParam String key) {
        String value = stringRedisTemplate.opsForValue().get(key);
        System.out.println(value);
        return value;
    }

DefaultStringConnection hold LettuceRedisConnection with multi = true, result isFutureConversion() always return true

    @Nullable
    private <T> T convertAndReturn(@Nullable Object value, Converter converter) {

        if (isFutureConversion()) {

            addResultConverter(converter);
            return null;
        }

        if (!(converter instanceof ListConverter) && value instanceof List) {
            return (T) new ListConverter<>(converter).convert((List) value);
        }

        return value == null ? null
                : ObjectUtils.nullSafeEquals(converter, Converters.identityConverter()) ? (T) value
                        : (T) converter.convert(value);
    }
截屏2024-08-01 下午7 52 26
mp911de commented 3 months ago

The problem originates in DefaultStringConnection. The backend connection uses a proxy mechanism to determine whether the called method is a read method that should return a value. DefaultStringRedisConnection uses manual decoration without access to command metadata for roughly 530 commands.

As workaround, you can use RedisTemplate<String, String> with StringRedisSerializer.UTF_8.