mybatis-plus typeHandler list映射mysql的varchar

1. 場(chǎng)景舉例

sku表中存儲(chǔ)了一些規(guī)格屬性咨察,在sku表中的字段名字為specs蜓谋,用了一個(gè)json數(shù)組表示的担忧,數(shù)據(jù)格式如下所示

[{"key":"顏色","value":"金屬灰","keyId":1,"valueId":45},{"key":"圖案","value":"七龍珠","keyId":3,"valueId":9},{"key":"尺碼","value":"小號(hào) S","keyId":4,"valueId":14}]
  • 字段解釋
    keyId:規(guī)格id
    key:規(guī)格名字
    valueId:規(guī)格值Id
    value:規(guī)格值

2. 遇到問(wèn)題

我使用DO映射數(shù)據(jù)庫(kù)表sku馁启,使用list數(shù)據(jù)類型來(lái)表示sku表的specs字段。這樣就會(huì)報(bào)錯(cuò)秋度。

正常來(lái)說(shuō)都是使用String來(lái)表示varchar炸庞,mybatisplus代碼生成器生成的代碼亦是如此。

為了給前端展示和修改查詢這些規(guī)格值方便荚斯,使用list來(lái)表示最舒服埠居。這樣前端操作的specs為list查牌,就不用自己轉(zhuǎn)化String為list再操作數(shù)據(jù)那么麻煩了

3. 解決問(wèn)題思路分析

  • 我的需求:使用Java的list來(lái)對(duì)應(yīng)mysql數(shù)據(jù)庫(kù)的varchar類型
  • 解決:我的想法很簡(jiǎn)單,我需要有個(gè)東西滥壕,在查詢mysql以后轉(zhuǎn)化為javaBean之前會(huì)轉(zhuǎn)化一下數(shù)據(jù)纸颜,轉(zhuǎn)化成符合javaBean的樣子。在插入數(shù)據(jù)到mysql的時(shí)候也是這樣绎橘,也是在插入數(shù)據(jù)前面把javaBean的數(shù)據(jù)轉(zhuǎn)化為符合mysql表的樣子(簡(jiǎn)單說(shuō):插入數(shù)據(jù)的時(shí)候javaBean的specs屬性是個(gè)list胁孙,執(zhí)行插入的之前,會(huì)把這個(gè)specs轉(zhuǎn)為String金踪,這樣string就對(duì)應(yīng)mysql的varchar浊洞,這樣就可以牵敷。反之查詢的時(shí)候亦是如此)
  • 結(jié)果:mybatis-plus有個(gè)@TableField注解有個(gè)typeHandler屬性可以解決

4. 解決問(wèn)題步驟

  1. 自定義一個(gè)通用的轉(zhuǎn)換器(任意類型與json互相轉(zhuǎn)換)
package cn.wangningbo.mall.util;

import cn.wangningbo.mall.exception.server.ServerException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author wangningbo
 */
@Component
public class GenericAndJson {
    private static ObjectMapper mapper;

    @Autowired
    public void setMapper(ObjectMapper mapper) {
        GenericAndJson.mapper = mapper;
    }

    public static <T> String objectToJson(T o) {
        try {
            return GenericAndJson.mapper.writeValueAsString(o);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServerException(9999);
        }
    }

    public static <T> T jsonToObject(String s, TypeReference<T> typeReference) {
        if (s == null) {
            return null;
        }
        try {
            return GenericAndJson.mapper.readValue(s, typeReference);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new ServerException(9999);
        }
    }
}
  1. 自定義一個(gè)handler
package cn.wangningbo.mall.util;

import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * object和json字符串 互相轉(zhuǎn)化
 *
 * @author wangningbo
 */
public class ObjectAndJsonHandler extends BaseTypeHandler<Object> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String json = GenericAndJson.objectToJson(parameter);
        ps.setString(i, json);
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String string = rs.getString(columnName);
        return GenericAndJson.jsonToObject(string, new TypeReference<>() {
        });
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String string = rs.getString(columnIndex);
        return GenericAndJson.jsonToObject(string, new TypeReference<>() {
        });
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String string = cs.getString(columnIndex);
        return GenericAndJson.jsonToObject(string, new TypeReference<>() {
        });
    }
}
  1. 配置自定義的handler到do上胡岔,配合mybatis-plus的注解
    這第三步的重點(diǎn)是
@TableName(value = "sku", autoResultMap = true)

@TableField(value = "specs", typeHandler = ObjectAndJsonHandler.class)
package cn.wangningbo.mall.pojo.model;

import lombok.Getter;
import lombok.Setter;

/**
 * @author wangningbo
 */
@Getter
@Setter
public class SpecDO {
    private Long keyId;
    private String key;
    private Long valueId;
    private String value;
}

package cn.wangningbo.mall.pojo.model;

import cn.wangningbo.mall.util.ObjectAndJsonHandler;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 *
 * </p>
 *
 * @author wangningbo
 * @since 2021-11-06
 */
@Getter
@Setter
@TableName(value = "sku", autoResultMap = true)
@ApiModel(value = "SkuDO對(duì)象", description = "")
public class SkuDO extends BaseDO {

    @ApiModelProperty("主鍵id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty("價(jià)格")
    @TableField("price")
    private BigDecimal price;

    @ApiModelProperty("上線:0-否;1->是;")
    @TableField("is_online")
    private Boolean online;

    @ApiModelProperty("標(biāo)題")
    @TableField("title")
    private String title;

    @ApiModelProperty("spu_id")
    @TableField("spu_id")
    private Long spuId;

    @ApiModelProperty("規(guī)格")
    @TableField(value = "specs", typeHandler = ObjectAndJsonHandler.class)
    private List<SpecDO> specs;
  1. 該實(shí)體類的xml中的specs字段配置使用的handler
<result column="specs" property="specs" typeHandler="cn.wangningbo.mall.util.ObjectAndJsonHandler"/>

5. 最終效果

插入數(shù)據(jù)時(shí)參數(shù)格式

{
  "online": true,
  "price": 66.00,
  "specs": [
    {
      "key": "顏色",
      "keyId": 1,
      "value": "青芒色",
      "valueId": 42
    },
    {
      "key": "圖案",
      "keyId": 3,
      "value": "灌籃高手",
      "valueId": 10
    },
    {
      "key": "尺碼",
      "keyId": 4,
      "value": "中號(hào) M",
      "valueId": 15
    }
  ],
  "spuId": 1,
  "stock": 0,
  "title": "青芒色·灌籃高手"
}

插入到mysql后的樣式


image.png

查詢后的結(jié)果

{
    "id": 1,
    "title": "針織衫",
    "subtitle": "秋日冬款,浪漫滿屋",
    "categoryId": 1,
    "rootCategoryId": 2,
    "price": "77.00",
    "sketchSpecId": 1,
    "defaultSkuId": 1,
    "img": null,
    "discountPrice": "62.00",
    "description": null,
    "tags": "秋日冬款;浪漫滿屋",
    "forThemeImg": null,
    "skuVOList": [{
            "id": 1,
            "price": 13.80,
            "discountPrice": null,
            "online": true,
            "img": null,
            "title": "青峰·7英寸",
            "spuId": 1,
            "categoryId": null,
            "rootCategoryId": null,
            "specs": [{
                    "keyId": 1,
                    "key": "顏色",
                    "valueId": 1,
                    "value": "青藍(lán)色"
                },
                {
                    "keyId": 2,
                    "key": "尺寸",
                    "valueId": 5,
                    "value": "7英寸"
                }
            ],
            "code": null,
            "stock": 0
        },
        {
            "id": 2,
            "price": 77.76,
            "discountPrice": null,
            "online": true,
            "img": null,
            "title": "金屬灰·七龍珠",
            "spuId": 1,
            "categoryId": null,
            "rootCategoryId": null,
            "specs": [{
                    "keyId": 1,
                    "key": "顏色",
                    "valueId": 45,
                    "value": "金屬灰"
                },
                {
                    "keyId": 3,
                    "key": "圖案",
                    "valueId": 9,
                    "value": "七龍珠"
                },
                {
                    "keyId": 4,
                    "key": "尺碼",
                    "valueId": 14,
                    "value": "小號(hào) S"
                }
            ],
            "code": null,
            "stock": 0
        },
        {
            "id": 3,
            "price": 66.00,
            "discountPrice": null,
            "online": true,
            "img": null,
            "title": "青芒色·灌籃高手",
            "spuId": 1,
            "categoryId": null,
            "rootCategoryId": null,
            "specs": [{
                    "keyId": 1,
                    "key": "顏色",
                    "valueId": 42,
                    "value": "青芒色"
                },
                {
                    "keyId": 3,
                    "key": "圖案",
                    "valueId": 10,
                    "value": "灌籃高手"
                },
                {
                    "keyId": 4,
                    "key": "尺碼",
                    "valueId": 15,
                    "value": "中號(hào) M"
                }
            ],
            "code": null,
            "stock": 0
        }
    ]
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枷餐,一起剝皮案震驚了整個(gè)濱河市靶瘸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毛肋,老刑警劉巖怨咪,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異润匙,居然都是意外死亡诗眨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門孕讳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匠楚,“玉大人,你說(shuō)我怎么就攤上這事厂财∮蟛荆” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵璃饱,是天一觀的道長(zhǎng)与斤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荚恶,這世上最難降的妖魔是什么撩穿? 我笑而不...
    開(kāi)封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮谒撼,結(jié)果婚禮上食寡,老公的妹妹穿的比我還像新娘。我一直安慰自己嗤栓,他們只是感情好冻河,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布箍邮。 她就那樣靜靜地躺著,像睡著了一般叨叙。 火紅的嫁衣襯著肌膚如雪锭弊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天擂错,我揣著相機(jī)與錄音味滞,去河邊找鬼。 笑死钮呀,一個(gè)胖子當(dāng)著我的面吹牛剑鞍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爽醋,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蚁署,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蚂四?” 一聲冷哼從身側(cè)響起光戈,我...
    開(kāi)封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遂赠,沒(méi)想到半個(gè)月后久妆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跷睦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年筷弦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抑诸。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烂琴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哼鬓,到底是詐尸還是另有隱情监右,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布异希,位于F島的核電站健盒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏称簿。R本人自食惡果不足惜扣癣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憨降。 院中可真熱鬧父虑,春花似錦、人聲如沸授药。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至莱衩,卻和暖如春爵嗅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笨蚁。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工睹晒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人括细。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓伪很,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奋单。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锉试,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一、準(zhǔn)備工作 1.1 數(shù)據(jù)庫(kù)MySQL 下載安裝過(guò)程略辱匿。 1.2 數(shù)據(jù)庫(kù)可視化工具DBeaver 下載安裝過(guò)程略键痛。...
    文景大大閱讀 1,539評(píng)論 0 1
  • 三、試一試 既然是來(lái)操作數(shù)據(jù)的江兢,那得準(zhǔn)備好數(shù)據(jù)的環(huán)境昨忆。 1.建庫(kù)、建表杉允、建數(shù)據(jù) # 創(chuàng)建數(shù)據(jù)庫(kù) CREATE DA...
    聯(lián)旺閱讀 409評(píng)論 0 0
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射...
    有_味閱讀 2,908評(píng)論 0 26
  • 之前學(xué)習(xí)MyBatis整理了一些筆記叔磷,筆記分為四個(gè)部分:1.MyBatis應(yīng)用分析與實(shí)踐[https://www....
    javacoo閱讀 979評(píng)論 0 2
  • 基礎(chǔ)查詢 select 查詢列表 from 表名; USE myemployees; //最好寫上 1.查詢表中的...
    曖莓悠閱讀 593評(píng)論 0 1