Object-to-Hash Mapping

Redis 存储库支持将对象持久化到哈希。这需要对象到哈希的转换,这是由 RedisConverter 完成的。默认实现使用 Converter 来将属性值映射到和从 Redis 本机 byte[]。 给定前一部分内容中的 Person 类型,默认映射如下所示:

_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 按点路径映射复杂类型属性。

Data Mapping and Type Conversion

此部分解释了类型与哈希表示之间的映射方式:

Table 1. Default Mapping Rules
Type Sample Mapped Value

Simple Type (for example, String)

String firstname = "rand";

firstname = "rand"

Byte array (byte[])

byte[] image = "rand".getBytes();

image = "rand"

Complex Type (for example, Address)

地址 address = new Address("emond’s field");

address.city = "emond’s field"

List of Simple Type

列表<String> 昵称 = asList("dragon reborn", "lews therin");

nicknames.[0] = "dragon reborn",nicknames.[1] = "lews therin"

Map of Simple Type

地图<String, String> atts = asMap({"eye-color", "grey"}, {"…​

atts.[eye-color] = "grey",atts.[hair-color] = "…​

List of Complex Type

列表<地址> 地址 = asList(new 地址("em…​

addresses.[0].city = "emond’s field",addresses.[1].city = "…​

Map of Complex Type

地图<String, 地址> 地址 = asMap({"home", new 地址("em …​

addresses.[home].city = "emond’s field",addresses.[work].city = "…​

由于扁平表示结构,映射键需要是简单类型,例如 StringNumber

映射行为可以通过在 RedisCustomConversions 中注册相应的 Converter 来自定义。这些转换器可以负责从和到单个 byte[] 以及 Map<String, byte[]> 的转换。第一个选项适用于(例如)将复杂类型转换为(例如)二进制 JSON 表示,该表示仍然使用默认映射哈希结构。第二个选项对结果哈希提供完全控制。

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

下例展示了两个示例字节数组转换器:

Example 1. Sample byte[] Converters
@WritingConverter
public class AddressToBytesConverter implements Converter<Address, byte[]> {

  private final Jackson2JsonRedisSerializer<Address> serializer;

  public AddressToBytesConverter() {

    serializer = new Jackson2JsonRedisSerializer<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 Jackson2JsonRedisSerializer<Address> serializer;

  public BytesToAddressConverter() {

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

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

使用前面的字节数组 Converter 产生的输出类似于以下内容:

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

下例展示了 Map 转换器的两个示例:

Example 2. Sample Map<String, byte[]> Converters
@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 产生的输出类似于以下内容:

_class = org.example.Person
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand
lastname = al’thor
ciudad = "emond's field"

自定义转换对索引解析没有任何影响。即使对于自定义转换的类型,“ Secondary Indexes”仍然会被创建。

Customizing Type Mapping

如果要避免将整个 Java 类名作为类型信息来编写,而更愿意使用键,则可以使用 @TypeAlias 注释在要持久化的实体类中。如果您需要更多地自定义映射,请查看 link:https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/convert/TypeInformationMapper.html[TypeInformationMapper 接口。可以在 DefaultRedisTypeMapper 中配置该接口的实例,而 MappingRedisConverter 中又可以对其进行配置。

下例展示了如何为实体定义类型别名:

Example 3. Defining @TypeAlias for an entity
@TypeAlias("pers")
class Person {

}

生成的 _class 字段中包含 pers 作为值。

Configuring Custom Type Mapping

以下示例演示如何在 MappingRedisConverter 中配置自定义 RedisTypeMapper

Example 4. Configuring a custom RedisTypeMapper via Spring Java Config
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();
  }
}