此版本仍在开发中,尚未被视为稳定版本。如需使用最新稳定版本,请访问 Spring Data Redis 4.0.4spring-doc.cadn.net.cn

对象到哈希映射

Redis Repository 支持将对象持久化为哈希(Hashes)。 这需要进行对象到哈希的转换,该转换由 RedisConverter 完成。 默认实现使用 Converter 将属性值与 Redis 原生的 byte[] 进行相互映射。spring-doc.cadn.net.cn

鉴于前几节中提到的 Person 类型,默认映射如下所示:spring-doc.cadn.net.cn

_class = org.example.Person                 (1)
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand                            (2)
lastname = al’thor
address.city = emond's field                (3)
address.country = andor
1 _class 属性包含在根级别以及任何嵌套的接口或抽象类型上。
2 简单属性值通过路径进行映射。
3 复杂类型的属性通过其点路径(dot path)进行映射。

数据映射与类型转换

本节说明了类型如何与哈希(Hash)表示形式之间进行映射:spring-doc.cadn.net.cn

表1. 默认映射规则
类型 示例 映射值

简单类型
(例如,String)spring-doc.cadn.net.cn

String firstname = "rand";spring-doc.cadn.net.cn

firstname = "rand"spring-doc.cadn.net.cn

字节数组(byte[]spring-doc.cadn.net.cn

byte[] image = "rand".getBytes();spring-doc.cadn.net.cn

image = "rand"spring-doc.cadn.net.cn

复杂类型
(例如,地址)spring-doc.cadn.net.cn

Address address = new Address(\"艾蒙德菲尔德\");spring-doc.cadn.net.cn

address.city = "伊蒙德之野"spring-doc.cadn.net.cn

列表
简单类型spring-doc.cadn.net.cn

List<String> 尼克names = asList("龙重生", "莱斯·泰林");spring-doc.cadn.net.cn

nicknames.[0] = "龙傲天",
昵称.[1] = "lews therin"spring-doc.cadn.net.cn

映射
简单类型spring-doc.cadn.net.cn

Map<String, String> atts = asMap({\"eye-color\", \"grey\"}, {\"…​spring-doc.cadn.net.cn

atts.[eye-color] = "灰色",
属性.[发色] = "…​"spring-doc.cadn.net.cn

列表
复杂类型spring-doc.cadn.net.cn

List<Address> addresses = asList(new Address("em…​spring-doc.cadn.net.cn

addresses.[0].city = "伊蒙之野",
addresses.[1].city = "…​spring-doc.cadn.net.cn

映射
复杂类型spring-doc.cadn.net.cn

Map<String, Address> addresses = asMap({"home", new Address("em…​spring-doc.cadn.net.cn

addresses.[home].city = "埃蒙场",
addresses.[work].city = "…​spring-doc.cadn.net.cn

由于采用扁平化的表示结构,Map 的键需要是简单类型,例如 StringNumber

可以通过在 Converter 中注册相应的 RedisCustomConversions 来自定义映射行为。 这些转换器可以处理与单个 byte[] 以及 Map<String, byte[]> 之间的相互转换。 第一种方式适用于(例如)将复杂类型转换为(例如)二进制 JSON 表示形式,同时仍使用默认的映射哈希结构。 第二种方式则提供了对生成的哈希结构的完全控制。spring-doc.cadn.net.cn

将对象写入 Redis 哈希会删除该哈希中的原有内容并重新创建整个哈希,因此未被映射的数据将会丢失。

以下示例展示了两个字节数组转换器的样例:spring-doc.cadn.net.cn

示例 1. 示例 byte[] 转换器
@WritingConverter
public class AddressToBytesConverter implements Converter<Address, byte[]> {

  private final JacksonJsonRedisSerializer<Address> serializer;

  public AddressToBytesConverter() {

    serializer = new JacksonJsonRedisSerializer<Address>(Address.class);
    serializer.setObjectMapper(new ObjectMapper());
  }

  @Override
  public byte[] convert(Address value) {
    return serializer.serialize(value);
  }
}

@ReadingConverter
public class BytesToAddressConverter implements Converter<byte[], Address> {

  private final JacksonJsonRedisSerializer<Address> serializer;

  public BytesToAddressConverter() {

    serializer = new JacksonJsonRedisSerializer<Address>(Address.class);
    serializer.setObjectMapper(new ObjectMapper());
  }

  @Override
  public Address convert(byte[] value) {
    return serializer.deserialize(value);
  }
}

使用前面所述的字节数组Converter会产生类似如下的输出:spring-doc.cadn.net.cn

_class = org.example.Person
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand
lastname = al’thor
address = { city : "emond's field", country : "andor" }

以下示例展示了两个 Map 转换器的示例:spring-doc.cadn.net.cn

例 2. 样本 Map<String, byte[]> 转换器
@WritingConverter
public class AddressToMapConverter implements Converter<Address, Map<String, byte[]>> {

  @Override
  public Map<String, byte[]> convert(Address source) {
    return singletonMap("ciudad", source.getCity().getBytes());
  }
}

@ReadingConverter
public class MapToAddressConverter implements Converter<Map<String, byte[]>, Address> {

  @Override
  public Address convert(Map<String, byte[]> source) {
    return new Address(new String(source.get("ciudad")));
  }
}

使用前面的 Map Converter 会产生类似如下的输出:spring-doc.cadn.net.cn

_class = org.example.Person
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand
lastname = al’thor
ciudad = "emond's field"
自定义转换对索引解析没有影响。二级索引仍然会被创建,即使对于经过自定义转换的类型也是如此。

自定义类型映射

如果您希望避免将完整的 Java 类名作为类型信息写入,而更倾向于使用键,可以在被持久化的实体类上使用 @TypeAlias 注解。 如果需要进一步自定义映射,请查看 TypeInformationMapper 接口。 该接口的实例可以在 DefaultRedisTypeMapper 处进行配置,而 DefaultRedisTypeMapper 又可以在 MappingRedisConverter 上进行配置。spring-doc.cadn.net.cn

以下示例展示了如何为一个实体定义类型别名:spring-doc.cadn.net.cn

示例 3. 为实体定义 @TypeAlias
@TypeAlias("pers")
class Person {

}

生成的文档在 pers 字段中包含 _class 作为其值。spring-doc.cadn.net.cn

配置自定义类型映射

以下示例演示了如何在 RedisTypeMapper 中配置自定义的 MappingRedisConverterspring-doc.cadn.net.cn

示例 4. 通过 Spring Java 配置方式配置自定义的 RedisTypeMapper
class CustomRedisTypeMapper extends DefaultRedisTypeMapper {
  //implement custom type mapping here
}
@Configuration
class SampleRedisConfiguration {

  @Bean
  public MappingRedisConverter redisConverter(RedisMappingContext mappingContext,
        RedisCustomConversions customConversions, ReferenceResolver referenceResolver) {

    MappingRedisConverter mappingRedisConverter = new MappingRedisConverter(mappingContext, null, referenceResolver,
            customTypeMapper());

    mappingRedisConverter.setCustomConversions(customConversions);

    return mappingRedisConverter;
  }

  @Bean
  public RedisTypeMapper customTypeMapper() {
    return new CustomRedisTypeMapper();
  }
}