spring-data-redis icon indicating copy to clipboard operation
spring-data-redis copied to clipboard

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

Open CHYhave opened this issue 1 year ago • 3 comments

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

CHYhave avatar Aug 01 '24 11:08 CHYhave

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.

mp911de avatar Aug 01 '24 12:08 mp911de

Hi @mp911de. May I handle this issue?

LeeHyungGeol avatar Aug 20 '25 16:08 LeeHyungGeol

With #3193, we now no longer wrap a RedisConnection to StringRedisConnection when using StringRedisTemplate. As workaround, I suggesst overriding StringRedisTemplate.preProcessConnection(…) and returning the raw RedisConnection.

mp911de avatar Sep 08 '25 09:09 mp911de