Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储

一.项目用redis-learn,文章参考

Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,而Hash则是:Key – [Field-Value] 的存储,也就是说其他数据结构的Value一般是确切的值,而Hash的Value是一系列的键值对。

通常我们是这样称呼Hash的存储的:大Key为实际的Key,小Key为Field,而具体的取值为Field对应的值value
实践:系统数据字典实时触发缓存存储

二. 系统数据字典实时触发缓存存储

2.1 在数据库建立 系统字典 表 sys_dict_config

CREATE TABLE `sys_dict_config` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '字典类型',
  `name` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '字典名称',
  `code` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '选项编码',
  `value` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '选项取值',
  `order_by` int(11) DEFAULT '1' COMMENT '排序',
  `is_active` int(11) DEFAULT '1' COMMENT '是否有效(1=是;0=否)',
  `create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `idx_type_code` (`type`,`code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.2 新建实体类 SysDictConfig,SysDictConfigMapper,SysDictConfigMapper.xml,代码如下:
SysDictConfig:

package com.example.redislearn.entity;

import org.hibernate.validator.constraints.NotBlank;

import java.io.Serializable;
import java.util.Date;

public class SysDictConfig implements Serializable {
    private Integer id;

    @NotBlank(message = "字典类型不能为空")
    private String type;

    @NotBlank(message = "字典名称不能为空")
    private String name;

    @NotBlank(message = "选项编码不能为空")
    private String code;

    @NotBlank(message = "选项取值不能为空")
    private String value;

    //排序
    private Integer orderBy;

    //是否有效(1=是;0=否)
    private Byte isActive=1;

    //创建时间
    private Date createTime;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Integer getOrderBy() {
        return orderBy;
    }

    public void setOrderBy(Integer orderBy) {
        this.orderBy = orderBy;
    }

    public Byte getIsActive() {
        return isActive;
    }

    public void setIsActive(Byte isActive) {
        this.isActive = isActive;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

SysDictConfigMapper:

package com.example.redislearn.dao;

import com.example.redislearn.entity.SysDictConfig;

import java.util.List;

public interface SysDictConfigMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(SysDictConfig sysDictConfig);

    int insertSelective(SysDictConfig sysDictConfig);

    SysDictConfig selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(SysDictConfig sysDictConfig);

    int updateByPrimaryKey(SysDictConfig sysDictConfig);

    List selectActiveConfigs();
}

SysDictConfigMapper.xml:





  
    
    
    
    
    
    
    
    
  

  
    id, type, name, code, value, order_by, is_active, create_time
  

  

  
    delete from sys_dict_config
    where id = #{id,jdbcType=INTEGER}
  

  
    insert into sys_dict_config (id, type, name,
      code, value, order_by, 
      is_active, create_time)
    values (#{id,jdbcType=INTEGER}, #{type,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, 
      #{code,jdbcType=VARCHAR}, #{value,jdbcType=VARCHAR}, #{orderBy,jdbcType=INTEGER}, 
      #{isActive,jdbcType=TINYINT}, #{createTime,jdbcType=TIMESTAMP})
  

  
    insert into sys_dict_config
    
      
        id,
      
      
        type,
      
      
        name,
      
      
        code,
      
      
        value,
      
      
        order_by,
      
      
        is_active,
      
      
        create_time,
      
    
    
      
        #{id,jdbcType=INTEGER},
      
      
        #{type,jdbcType=VARCHAR},
      
      
        #{name,jdbcType=VARCHAR},
      
      
        #{code,jdbcType=VARCHAR},
      
      
        #{value,jdbcType=VARCHAR},
      
      
        #{orderBy,jdbcType=INTEGER},
      
      
        #{isActive,jdbcType=TINYINT},
      
      
        #{createTime,jdbcType=TIMESTAMP},
      
    
  

  
    update sys_dict_config
    
      
        type = #{type,jdbcType=VARCHAR},
      
      
        name = #{name,jdbcType=VARCHAR},
      
      
        code = #{code,jdbcType=VARCHAR},
      
      
        value = #{value,jdbcType=VARCHAR},
      
      
        order_by = #{orderBy,jdbcType=INTEGER},
      
      
        is_active = #{isActive,jdbcType=TINYINT},
      
      
        create_time = #{createTime,jdbcType=TIMESTAMP},
      
    
    where id = #{id,jdbcType=INTEGER}
  

  
    update sys_dict_config
    set type = #{type,jdbcType=VARCHAR},
      name = #{name,jdbcType=VARCHAR},
      code = #{code,jdbcType=VARCHAR},
      value = #{value,jdbcType=VARCHAR},
      order_by = #{orderBy,jdbcType=INTEGER},
      is_active = #{isActive,jdbcType=TINYINT},
      create_time = #{createTime,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=INTEGER}
  


  



2.3 RedisHashController类 ,代码如下:

package com.example.redislearn.controller;

import com.example.redislearn.entity.SysDictConfig;
import com.example.redislearn.response.BaseResponse;
import com.example.redislearn.response.StatusCode;
import com.example.redislearn.service.RedisHashService;
import com.example.redislearn.util.ValidatorUtil;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

/**
 * 数据类型Hash字典
 * Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,
 * 而Hash则是:Key – [Field-Value] 的存储,也就是说其他数据结构的Value一般是确切的值,而Hash的Value是一系列的键值对,
 * 通常我们是这样称呼Hash的存储的:大Key为实际的Key,小Key为Field,而具体的取值为Field对应的值value。
 * 实践:系统数据字典实时触发缓存存储
 */

/**
 * 常用的方法:
 * 1. put(H key, HK hashKey, HV value);   新增hashMap值。
 * 2. putAll(H key, Map m);以map集合的形式添加键值对。
 * 3. entries(H key); 获取key的列表元素。
 * 4. get(H key, Object hashKey); 获取变key中的指定field键是否有值,如果存在返回value,没有则返回null。
 * 5. keys(H key); 获取key中的所有field列表。
 * 6. hasKey(H key, Object hashKey);判断key是否有指定的field。
 * 7. delete(H key, Object... hashKeys); 删除key中的field-value对,可以传入多个参数,删除多个field-value对。
 * 8. size(H key);获取key的长度。
 */
@RestController
@RequestMapping("RedisHashController")
public class RedisHashController {

    private static final Logger log = LoggerFactory.getLogger(RedisHashController.class);

    @Autowired
    private RedisHashService redisHashService;

    @Autowired
    private RedisTemplate redisTemplate;


    @RequestMapping(value = "/hashSet", method = RequestMethod.POST)
    public void hashSet() {
        log.info("----开始哈希Hash测试");
        final String key = "SpringBootRedis:Hash:Key:英雄联盟";
        redisTemplate.delete(key);

        HashOperations hashOperations = redisTemplate.opsForHash();
        hashOperations.put(key, "德玛西亚", "盖伦");
        hashOperations.put(key, "诺克萨斯", "德莱厄斯");

        Map dataMap = Maps.newHashMap();
        dataMap.put("祖安", "蒙多");
        dataMap.put("艾欧尼亚", "艾瑞莉娅");
        hashOperations.putAll(key, dataMap);

        log.info("---哈希hash-获取列表元素: {} ", hashOperations.entries(key));
        log.info("---哈希hash-获取诺克萨斯的元素: {} ", hashOperations.get(key, "诺克萨斯"));
        log.info("---哈希hash-获取所有元素的field列表: {} ", hashOperations.keys(key));

        log.info("---哈希hash-祖安成员是否存在: {} ", hashOperations.hasKey(key, "祖安"));
        log.info("---哈希hash-艾欧尼亚成员是否存在: {} ", hashOperations.hasKey(key, "艾欧尼亚"));

        hashOperations.putIfAbsent(key, "暗影", "卡尔萨斯");
        log.info("---哈希hash-获取列表元素: {} ", hashOperations.entries(key));

        log.info("---哈希hash-删除元素德玛西亚、 诺克萨斯: {} ", hashOperations.delete(key, "德玛西亚", "诺克萨斯"));
        log.info("---哈希hash-获取列表元素: {} ", hashOperations.entries(key));

        log.info("---哈希hash-获取列表元素个数: {} ", hashOperations.size(key));
    }


    //==============================================系统数据字典实时触发缓存存储=================================================//


    /**
     * 添加数据字典及其对应的选项(field-value)
     * @param config
     * @param result
     * @return
     */
    @RequestMapping(value = "/addSysDictConfig",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse addSysDictConfig(@RequestBody @Validated SysDictConfig config, BindingResult result){
        String checkRes= ValidatorUtil.checkResult(result);
        /*if (StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.Fail.getCode(),checkRes);
        }*/
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            redisHashService.addSysDictConfig(config);
        }catch (Exception e){
            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }


    /**
     *获取缓存中所有的数据字典
     * @return
     */
    @RequestMapping(value = "getSysDictConfig",method = RequestMethod.GET)
    public BaseResponse getSysDictConfig(){
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            response.setData(redisHashService.getSysDictConfig());
        }catch (Exception e){
            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }


    /**
     * 获取缓存中某个特定编码下数据字典的取值列表
     * @param type
     * @return
     */
    @RequestMapping(value = "get/type",method = RequestMethod.GET)
    public BaseResponse getType(@RequestParam String type){
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            response.setData(redisHashService.getByType(type));
        }catch (Exception e){
            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }

}

2.4 业务类:RedisHashService,代码如下:

package com.example.redislearn.service;

import com.example.redislearn.dao.SysDictConfigMapper;
import com.example.redislearn.entity.SysDictConfig;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;

@Service
public class RedisHashService {

    private static final Logger log = LoggerFactory.getLogger(RedisHashService.class);

    private static final String RedisHashKey = "Redis:Hash";

    @Autowired
    private SysDictConfigMapper sysDictConfigMapper;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 添加数据字典及其对应的选项(code-value)
     *
     * @param config
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer addSysDictConfig(SysDictConfig config) throws Exception {
        int res = sysDictConfigMapper.insertSelective(config);
        if (res > 0) {
            //实时触发数据字典的hash存储
            cacheConfigMap();
        }
        return config.getId();
    }


    /**
     * 取出缓存中所有的数据字典列表
     */
    public Map> getSysDictConfig() throws Exception {
        return getAllCacheConfig();
    }


    /**
     * 取出缓存中特定的数据字典列表
     *
     * @param type
     * @return
     * @throws Exception
     */
    public List getByType(final String type) throws Exception {
        return getCacheConfigByType(type);
    }


    /**
     * 实时获取所有有效的数据字典列表-转化为map-存入hash缓存中
     */
    @Async
    public void cacheConfigMap() {
        try {
            List sysDictConfigList = sysDictConfigMapper.selectActiveConfigs();
            if (sysDictConfigList != null && !sysDictConfigList.isEmpty()) {
                Map> dataMap = Maps.newHashMap();
                //所有的数据字典列表遍历 -> 转化为 hash存储的map
                sysDictConfigList.forEach(sysDictConfig -> {
                    List list = dataMap.get(sysDictConfig.getType());
                    if (CollectionUtils.isEmpty(list)) {
                        list = Lists.newLinkedList();
                    }
                    list.add(sysDictConfig);
                    dataMap.put(sysDictConfig.getType(), list);
                });

                //存储到缓存hash中
                HashOperations> hashOperations = redisTemplate.opsForHash();
                hashOperations.putAll(RedisHashKey, dataMap);
            }
        } catch (Exception e) {
            log.error("实时获取所有有效的数据字典列表-转化为map-存入hash缓存中-发生异常:", e.fillInStackTrace());
        }
    }


    /**
     * 从缓存hash中获取所有的数据字典配置map
     *
     * @return
     */
    public Map> getAllCacheConfig() {
        Map> map = Maps.newHashMap();
        try {
            HashOperations> hashOperations = redisTemplate.opsForHash();
            map = hashOperations.entries(RedisHashKey);
        } catch (Exception e) {
            log.error("从缓存hash中获取所有的数据字典配置map-发生异常:", e.fillInStackTrace());
        }
        return map;
    }


    /**
     * 从缓存hash中获取特定的数据字典列表
     *
     * @param type
     * @return
     */
    public List getCacheConfigByType(final String type) {
        List list = Lists.newArrayList();
        try {
            HashOperations> hashOperations = redisTemplate.opsForHash();
            list = hashOperations.get(RedisHashKey, type);
        } catch (Exception e) {
            log.error("从缓存hash中获取特定的数据字典列表-发生异常:", e.fillInStackTrace());
        }
        return list;
    }

}

三.测试

启动项目
测试 添加数据字典及其对应的选项(field-value)
在浏览器或postman 上输入:http://127.0.0.1:8782/RedisHashController/addSysDictConfig
post请求
Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储_第1张图片
Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储_第2张图片
Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储_第3张图片
测试 获取缓存中所有的数据字典 功能:
在浏览器或postman 上输入:http://127.0.0.1:8782/RedisHashController/getSysDictConfig
get请求
Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储_第4张图片
测试 获取缓存中某个特定编码下数据字典的取值列表 功能:
在浏览器或postman 上输入:http://127.0.0.1:8782/RedisHashController/get/type?type=sex
get请求
Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储_第5张图片

你可能感兴趣的:(Redis)