Spring Data Redis 教程

Hash映射:Jackson2HashMapper

上一章节介绍了怎样使用 HashMapper 映射 Java 对象,本章将介绍怎样通过 Jackson2HashMapper 实现 Java 对象映射。

Jackson2HashMapper 通过使用 FasterXML Jackson 为 Java 对象提供 Redis Hash 映射。Jackson2HashMapper 可以将顶级属性映射为 Hash 字段名,还可以选择将结构扁平化。

什么是结构扁平化?

扁平化指为所有嵌套属性创建单独的 Hash 项,并尽可能将复杂类型解析为简单类型。

考虑以下类及其包含的数据结构:

public class Person {
	private String firstname;
	private String lastname;
	private Address address;
	private Date date;
	private LocalDateTime localDateTime;
	//...
}
public class Address {
  	private String city;
  	private String country;
	//...
}

下表显示了前面类中的数据在非扁平化映射中的显示方式:

Hash字段
firstnameJon
lastnameSnow
address{ "city" : "Castle Black", "country" : "The North" }        
date1561543964015
localDateTime                  2018-01-02T12:13:14

下表显示了前面类中的数据在扁平化映射中的显示方式:

Hash字段
firstnameJon
lastnameSnow
address.cityCastle Black  
address.country               The North
date1561543964015
localDateTime2018-01-02T12:13:14                                                   

示例

使用订单示例来学习怎样通过 Jackson2HashMapper 将对象映射为 Map,并且保存到 Redis。

配置 RedisTemplate

使用 Jackson2JsonRedisSerializer 作为 RedisTemplate 的序列化器。如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;

@Configuration
public class RedisConfigJackson2JsonRedisSerializer {

    @Bean
    public RedisTemplate<String,Object> jsonSerialRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        redisTemplate.setHashKeySerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}

定义实体对象

// Order.java
import java.util.ArrayList;
import java.util.List;

/**
 * 订单实体
 * @author hxstrive.com 2022/10/9
 */
public class Order {
    /** 订单编号 */
    private String orderNumber;
    /** 订单总金额 */
    private double amount;
    /** 订单所属用户 */
    private User user;
    /** 订单商品列表 */
    private List<Goods> goodsList;

    public Order() {
        this.orderNumber = "";
        this.amount = 0.0D;
        this.user = null;
        this.goodsList = new ArrayList<>();
    }

    /**
     * 添加商品到订单
     * @param goods
     */
    public void addGoods(Goods goods) {
        this.goodsList.add(goods);
        this.amount += goods.getPrice();
    }
	//...
}
// User.java
/**
 * 用户实体
 * @author hxstrive.com 2022/7/5
 */
public class User {
    /** 用户ID */
    private int id;
    /** 用户名 */
    private String name;

    public User() {}
    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }
	//...
}
// Goods.java
/**
 * 商品实体
 * @author hxstrive.com 2022/10/9
 */
public class Goods {
    /** 商品编号 */
    private String number;
    /** 商品名称 */
    private String name;
    /** 商品价格 */
    private double price;
    /** 商品数量 */
    private int quantity;
	//...
}

创建测试用例

使用 @RunWith(SpringRunner.class) 和 @SpringBootTest 注解创建一个测试类,代码如下:

import com.alibaba.fastjson.JSONObject;
import com.hxstrive.redis.entity.Goods;
import com.hxstrive.redis.entity.Order;
import com.hxstrive.redis.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.hash.HashMapper;
import org.springframework.data.redis.hash.Jackson2HashMapper;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;

/**
 * 测试验证 Jackson2HashMapper 的用法
 * @author hxstrive.com 2022/10/9
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Jackson2HashMapperTest {

    @Autowired
    @Qualifier("jsonSerialRedisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    private Order getOrder() {
        Order order = new Order();
        order.setOrderNumber("BH20221009125434");

        User user = new User();
        user.setId(100);
        user.setName("张三");
        order.setUser(user);

        Goods goodsJava = new Goods();
        goodsJava.setNumber("9787111213826");
        goodsJava.setName("《Java编程思想》");
        goodsJava.setQuantity(2);
        goodsJava.setPrice(54.0D);
        order.addGoods(goodsJava);

        Goods goodsPhp = new Goods();
        goodsPhp.setNumber("9787302596462");
        goodsPhp.setName("《PHP从入门到精通》(第6版)");
        goodsPhp.setQuantity(1);
        goodsPhp.setPrice(90.70D);
        order.addGoods(goodsPhp);

        return order;
    }

    @Test
    public void toHash() {
        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(true);

        Order order = getOrder();
        Map<String,Object> map = hashMapper.toHash(order);
        for(Map.Entry<String,Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }

    @Test
    public void toHashFlatten() {
        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(false);

        Order order = getOrder();
        Map<String,Object> map = hashMapper.toHash(order);
        for(Map.Entry<String,Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }

    @Test
    public void save() {
        Order order = getOrder();

        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(false);
        Map<String,Object> map = hashMapper.toHash(order);
        for(Map.Entry<String,Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + "=" + value);
        }

        HashOperations<String,String,Object> ops = redisTemplate.opsForHash();
        ops.putAll("jackson", map);
    }

    @Test
    public void find() {
        HashOperations<String,String,Object> ops = redisTemplate.opsForHash();
        Map<String,Object> map = ops.entries("jackson");

        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(false);
        Order order = (Order)hashMapper.fromHash(map);
        if(null != order) {
            System.out.println(JSONObject.toJSONString(order, true));
        }
    }

    @Test
    public void saveFlatten() {
        Order order = getOrder();

        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(true);
        Map<String,Object> map = hashMapper.toHash(order);
        for(Map.Entry<String,Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key + "=" + value);
        }

        HashOperations<String,String,Object> ops = redisTemplate.opsForHash();
        ops.putAll("jackson", map);
    }

    @Test
    public void findFlatten() {
        HashOperations<String,String,Object> ops = redisTemplate.opsForHash();
        Map<String,Object> map = ops.entries("jackson");

        HashMapper<Object, String, Object> hashMapper = new Jackson2HashMapper(true);
        Order order = (Order)hashMapper.fromHash(map);
        if(null != order) {
            System.out.println(JSONObject.toJSONString(order, true));
        }
    }

}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号