私たちは、春のデータを使用しようとする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
が、どうやら彼らは間違ったものとなっています。
- autowired
基本的に、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
それらを使用することができますし、期待どおりのコードは動作するはずです。