複雑なキーとSpringData Redisのリポジトリ

ダーム:

私たちは、春のデータを使用しようとするCrudRepository私たちのドメインオブジェクトの永続性を提供するために、私たちのプロジェクトに。
私は最初の実験で以来、バックエンドとしてのRedisを選んだの開始のためにCrudRepository<ExperimentDomainObject, String>、それが実行して取得し、seemd簡単です。

当社の生産コードでそれを置くしようとすると、リポジトリだったので、ここで私たちのドメインオブジェクトをキーとして、単純なタイプを使用してnecesseriliyなかったので、物事は、もっと複雑ですCrudRepository<TestObject, ObjectId>

今、私は例外が発生しました:

NOコンバータは、[...のObjectId]タイプに[バイト[]型から変換することができる見られなかっ

この例外の検索、この答えはで無学試しに私を導いているRedisTemplate設定。(私の実験のために私はemdedded-Redisのを使用しています)

私の考えでは提供する、だったRedisTemplate<Object, Object>の代わりにRedisTemplate<String, Object>使用できるようにJackson2JsonRedisSerializerもkeySerializerとして仕事をします。

それでも、呼び出しはtestRepository.save(testObject)失敗します。

私のコードを参照してください。

私は公共の場を持っており、この例の簡略化のために輸入を残しました。それらが必要な場合(このMVCE作るために)私は喜んでそれらを提供します。ちょうど私のコメントを残して。

依存関係:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    implementation group: 'redis.clients', name: "jedis", version: '2.9.0'
    implementation group: 'it.ozimov', name: 'embedded-redis', version: '0.7.2'
}

RedisConfiguration:

@Configuration
@EnableRedisRepositories
public class RedisConfiguration {
    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        return new JedisConnectionFactory();
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        final RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setEnableDefaultSerializer(true);

        return template;
    }
}

TestObject

@RedisHash("test")
public class TestObject
{
    @Id public ObjectId testId;
    public String value;

    public TestObject(ObjectId id, String value)
    {
        this.testId = id;
        this.value = value; // In experiment this is: "magic"
    }
}

ObjectId

@EqualsAndHashCode
public class ObjectId {
    public String creator; // In experiment, this is "me"
    public String name;    // In experiment, this is "fool"
}

TestRepository

@Repository
public interface TestRepository extends CrudRepository<TestObject, ObjectId>
{
}

EmbeddedRedisConfiguration

@Configuration
public class EmbeddedRedisConfiguration
{
    private final redis.embedded.RedisServer redisServer;

    EmbeddedRedisConfiguration(RedisProperties redisProperties)
    {
        this.redisServer = new redis.embedded.RedisServer(redisProperties.getPort());
    }

    @PostConstruct
    public void init()
    {
        redisServer.start();
    }

    @PreDestroy
    public void shutdown()
    {
        redisServer.stop();
    }
}

応用:

@SpringBootApplication
public class ExperimentApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(ExperimentApplication.class, args);
    }
}

ない希望回答:

もちろん、私はジャクソンズObjectMapperを使用して手動で構築し、使用し、単純なデータ型、例えばA JSON-Stringでいくつかの特別なIDをご紹介かもしれませんCrudRepository<TestObject, String>

私はまた、その間に試してみました:

  • RedisTemplate<String, String>
  • RedisTemplate<String, Object>
  • Autowireing RedisTemplateとそのデフォルト・シリアライザを設定します
  • 登録Converter<ObjectId, byte[]>します
    • autowired ConverterRegistry
    • アンはautowired GenericConversionService
      が、どうやら彼らは間違ったものとなっています
BBL:

基本的に、Redisのリポジトリは、使用RedisKeyValueTemplateキー(ID)と値のペアとしてデータを格納するためにボンネットの下。あなたの構成は、だからRedisTemplateあなたはそれを直接使用しない限り動作しません。

あなたのための一つの方法は、使用することになりますのでRedistTemplate、直接、このようなものはあなたのために動作します。

@Service
public class TestService {

    @Autowired
    private RedisTemplate redisTemplate;

    public void saveIt(TestObject testObject){
        ValueOperations<ObjectId, TestObject> values = redisTemplate.opsForValue();
        values.set(testObject.testId, testObject);
    }

}

上記のコードは、あなたの構成を使用して、キーと値の両方のためのマッパーとしてジャクソンを使用してRedisの中の文字列のペアを生成しますので。

しかし、あなたは経由Redisのリポジトリを使用したい場合はCrudRepository、あなたがのために読み書きのコンバータ作成する必要があるObjectIdからとまでStringとしbyte[]て、カスタムのRedisの変換として登録します。

それではためのコンバータを読み書き作成してみましょうObjectId< - >String

読者

@Component
@ReadingConverter
@Slf4j
public class RedisReadingStringConverter implements Converter<String, ObjectId> {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public ObjectId convert(String source) {
        try {
            return objectMapper.readValue(source, ObjectId.class);
        } catch (IOException e) {
            log.warn("Error while converting to ObjectId.", e);
            throw new IllegalArgumentException("Can not convert to ObjectId");
        }
    }
}

ライター

@Component
@WritingConverter
@Slf4j
public class RedisWritingStringConverter implements Converter<ObjectId, String> {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convert(ObjectId source) {
        try {
            return objectMapper.writeValueAsString(source);
        } catch (JsonProcessingException e) {
            log.warn("Error while converting ObjectId to String.", e);
            throw new IllegalArgumentException("Can not convert ObjectId to String");
        }
    }
}

そして、のObjectIdのための読み取りおよび書き込みコンバーター< - >バイト[]

ライター

@Component
@WritingConverter
public class RedisWritingByteConverter implements Converter<ObjectId, byte[]> {

    Jackson2JsonRedisSerializer<ObjectId> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(ObjectId.class);

    @Override
    public byte[] convert(ObjectId source) {
        return jackson2JsonRedisSerializer.serialize(source);
    }
}

読者

@Component
@ReadingConverter
public class RedisReadingByteConverter implements Converter<byte[], ObjectId> {

     Jackson2JsonRedisSerializer<ObjectId> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(ObjectId.class);

    @Override
    public ObjectId convert(byte[] source) {
        return jackson2JsonRedisSerializer.deserialize(source);
    }
}

そして最後Redisのカスタム会話を追加します。ちょうどにコードを置きますRedisConfiguration

@Bean
public RedisCustomConversions redisCustomConversions(RedisReadingByteConverter readingConverter,
                                                     RedisWritingByteConverter redisWritingConverter,
                                                     RedisWritingStringConverter redisWritingByteConverter,
                                                     RedisReadingStringConverter redisReadingByteConverter) {
    return new RedisCustomConversions(Arrays.asList(readingConverter, redisWritingConverter, redisWritingByteConverter, redisReadingByteConverter));
}

だから今のコンバータを作成し、カスタムRedisのコンバータとして登録された後にRedisKeyValueTemplateそれらを使用することができますし、期待どおりのコードは動作するはずです。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=330988&siteId=1