Mysql使用Key/Value方式存儲動態擴展字段、對象與HashMap的相互轉化

1、背景

在項目剛剛進入開發階段設計表時,後期表的字段很可能會增加,可以設計出預留字段來應對。但是假如你的數據數據非常龐大且,那麼執行修改表語句時會長時間鎖表。而且假如一張表支持許多個客戶,每個客戶的需求不相同且多變時,使用一張表也無法滿足需求。這時可以使用Mysql存儲key/value數據滿足不同客戶需求。

2、Key/Value表設計

以Key/Value存儲數據肯定不是Mysql的存儲常態,但是可以應對一些靈活多變的場景。以下就是使用Key/Value的例子,先創建要給order訂單表,再創建訂單表的擴展字段。創建好Key/Value表之後可以爲不同的客戶配置不同的擴展字段屬性和值。

CREATE TABLE `order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `description` text,
  `quantity` bigint(20) unsigned DEFAULT NULL COMMENT '數量',
  `amount` decimal(22,2) DEFAULT NULL COMMENT '金額',
   PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=337411 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;


CREATE TABLE `order_extend` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_id` bigint unsigned NOT NULL COMMENT '訂單id',
  `extendfield_code` varchar(255) NOT NULL COMMENT '擴展字段屬性',
  `extendfield_value` text COMMENT '擴展字段值',
   PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

3、對象和HashMap相互轉化

在設計了Key/Value擴展字段表之後,在某些業務場景爲了方便處理擴展字段,可以將對象轉化爲Map進行操作,一個Map的所有key就是對象的所有字段,value就是對象字段所對應的值。以下是操作Key/Value數據案例操作:

    public void example(Long id) {
    	//查到id對應的訂單
        Order order = orderMapper.selectByPrimaryKey(id);
        //將對象屬性轉化爲map集合
        Map<String, Object> map = JSON.parseObject(JSONObject.toJSONString(order), HashMap.class);
        //查到對應的擴展字段list
        List<OrderExtend> orderExtends = orderExtendMapper.select(id);
        for (OrderExtend orderExtend : orderExtends) {
        	//將擴展字段放入map中
            map.put(orderExtend.getExtendFieldCode(),orderExtend.getExtendFieldValue());
        }
		 
		 //......
    	 //對map一頓操作
    	 //......

		//將map集合中的數據轉化爲指定對象的同名屬性中
        Order updateOrder = JSON.parseObject(JSONObject.toJSONString(map), EventOrder.class);
		//更新訂單信息
        eventOrderMapper.updateByPrimaryKey(updateOrder);
		//遍歷出map中的擴展字段進行更新
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getKey().startsWith("extendField_")) {
                OrderExtend  orderExtend  = new OrderExtend ();
                orderExtend.setOrderId(updateOrder.getId());
                orderExtend.setExtendFieldCode(entry.getKey());
                orderExtend.setExtendFieldValue(entry.getValue());
                update(orderExtend);
            }
        }
    }
  • HashMap和對象之間的轉化還可以通過使用org.springframework.cglib.beans.BeanMap類中的方法,轉化效率高。使用BeanMap進行對象和HashMap的轉化:

    //將map集合中的數據轉化爲指定對象的同名屬性中
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key+"", beanMap.get(key));
            }
        }
        return map;
    }
    
    //將對象屬性轉化爲map集合
    public static <T> T mapToBean(Map map,Class<T> clazz) throws Exception {
        T bean = clazz.newInstance();
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章