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

`opsForHash()` should reuse cached instances #2970

Closed HK-hub closed 2 months ago

HK-hub commented 3 months ago

Curious question

Why in the series of OpsFor* methods of RedisTemplate, opsForHash() always returns a new instance object, valueOps, listOps, setOps, zSetOps and other data structures return final modified instantiated property objects. Is there a particular reason for this

dependency

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>3.2.2</version>
      </dependency>

opsForHash() Method

this is opsForHash() method body for 3.2.2 version

    public <HK, HV> HashOperations<K, HK, HV> opsForHash() {
        return new DefaultHashOperations(this);
    }

and the next code is some opsFor* that return the singleton object

    private final ValueOperations<K, V> valueOps = new DefaultValueOperations(this);
    private final ListOperations<K, V> listOps = new DefaultListOperations(this);
    private final SetOperations<K, V> setOps = new DefaultSetOperations(this);
    private final StreamOperations<K, ?, ?> streamOps = new DefaultStreamOperations(this, ObjectHashMapper.getSharedInstance());
    private final ZSetOperations<K, V> zSetOps = new DefaultZSetOperations(this);
    private final GeoOperations<K, V> geoOps = new DefaultGeoOperations(this);
    private final HyperLogLogOperations<K, V> hllOps = new DefaultHyperLogLogOperations(this);
    private final ClusterOperations<K, V> clusterOps = new DefaultClusterOperations(this);

I would like to know why the design is like this, I searched for related questions but found no discussion about it

mp911de commented 2 months ago

This behavior has existed since the earliest days of hash operations (Early 2010). I cannot tell why this is, though I assume that the code didn't want to mess with generic assignability. Its reactive variant, ReactiveRedisTemplate.opsForHash() uses a cached variant. Tests pass when we change the object to a cached variant so there's no reason why it needs to remain this way.