最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot+MyBatis處理JSON字段的完整指南

 更新時間:2026年03月30日 09:23:27   作者:荒古前  
本文主要介紹了SpringBoot+MyBatis處理JSON字段的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

最近在開發(fā)一個活動發(fā)布功能時,遇到了一個讓人頭疼的問題:前端傳遞的聯(lián)系方式信息(contactInfo)是一個 JSON 對象,但后端始終無法正確接收和存儲到數(shù)據(jù)庫。經(jīng)過一番折騰,終于完美解決了。本文將詳細(xì)記錄這個問題和解決方案,希望對遇到類似問題的朋友有所幫助。

問題場景

我需要實(shí)現(xiàn)一個活動發(fā)布接口,其中聯(lián)系方式字段 contactInfo 需要存儲多個信息(如微信、QQ、手機(jī)號等),設(shè)計如下:

數(shù)據(jù)庫表結(jié)構(gòu):

CREATE TABLE activity (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    title VARCHAR(50),
    category VARCHAR(20),
    activity_type VARCHAR(50),
    activity_time DATETIME,
    city VARCHAR(50),
    people_limit INT,
    current_people INT,
    contact_info JSON,  -- JSON 類型字段
    contact_visibility VARCHAR(20),
    create_time DATETIME,
    status TINYINT
);

前端傳參格式:

{
  "title": "今晚王者三排",
  "category": "GAME",
  "activityType": "王者榮耀",
  "activityTime": "2026-03-23 20:00:00",
  "city": "南京",
  "peopleLimit": 3,
  "contactInfo": {
    "wechat": "test123",
    "qq": "123456789",
    "phone": "13800138000"
  },
  "contactVisibility": "PUBLIC"
}

遇到的坑

坑1:LocalDateTime 反序列化失敗

錯誤信息:

Cannot deserialize value of type `java.time.LocalDateTime` from String "2026-03-23 20:00:00"

原因: Jackson 默認(rèn)的日期格式是 yyyy-MM-ddTHH:mm:ss,但前端傳的是 yyyy-MM-dd HH:mm:ss(空格分隔)。

解決方案: 在 DTO 中添加 @JsonFormat 注解

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime activityTime;

坑2:contactInfo 類型不匹配

錯誤信息:

Cannot deserialize value of type `java.lang.String` from Object value

原因: 前端傳的是對象 {"wechat":"test123"},但后端 DTO 定義的是 String 類型。

坑3:MyBatis 無法處理 JSON 字段

錯誤信息:

Type handler was null on parameter mapping for property 'contactInfo'

原因: MyBatis 默認(rèn)不知道如何將 Java 對象轉(zhuǎn)換為數(shù)據(jù)庫的 JSON 字段。

坑4:自增 ID 返回 null

錯誤信息:

Column 'activity_id' cannot be null

原因: MyBatis insert 后沒有返回自增 ID,導(dǎo)致插入 activity_member 時 activity_id 為 null。

解決方案

經(jīng)過多次嘗試,我選擇了最簡單直接的方案:手動轉(zhuǎn)換 JSON

1. DTO 使用 Object 類型接收

package com.jade.partnermatch.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ActivityCreateDTO {
    private String title;
    private String category;
    private String activityType;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime activityTime;
    private String city;
    private Integer peopleLimit;
    private Object contactInfo;  // 使用 Object 接收,可以是字符串或?qū)ο?
    private String contactVisibility;
}

2. Entity 使用 String 存儲

package com.jade.partnermatch.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class Activity {
    private Long id;
    private Long userId;
    private String title;
    private String category;
    private String activityType;
    private LocalDateTime activityTime;
    private String city;
    private Integer peopleLimit;
    private Integer currentPeople;
    private String contactInfo;  // 存 JSON 字符串
    private String contactVisibility;
    private LocalDateTime createTime;
    private Integer status;
}

3. Service 手動轉(zhuǎn)換

package com.jade.partnermatch.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jade.partnermatch.dto.ActivityCreateDTO;
import com.jade.partnermatch.entity.Activity;
import com.jade.partnermatch.mapper.ActivityMapper;
import com.jade.partnermatch.mapper.ActivityMemberMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
@Service
public class ActivityService {
    @Autowired
    private ActivityMapper activityMapper;
    @Autowired
    private ActivityMemberMapper activityMemberMapper;
    @Autowired
    private ObjectMapper objectMapper;  // 注入 Jackson
    @Transactional
    public void create(ActivityCreateDTO dto) {
        Activity activity = new Activity();
        activity.setUserId(1L);
        activity.setTitle(dto.getTitle());
        activity.setCategory(dto.getCategory());
        activity.setActivityType(dto.getActivityType());
        activity.setActivityTime(dto.getActivityTime());
        activity.setCity(dto.getCity());
        activity.setPeopleLimit(dto.getPeopleLimit());
        activity.setCurrentPeople(1);
        // 關(guān)鍵:將 Object 轉(zhuǎn)換為 JSON 字符串
        String contactInfoJson = convertToJson(dto.getContactInfo());
        activity.setContactInfo(contactInfoJson);
        activity.setContactVisibility(dto.getContactVisibility());
        activity.setCreateTime(LocalDateTime.now());
        activity.setStatus(0);
        // 先插入活動,獲取自增 ID
        activityMapper.insert(activity);
        // 再插入活動成員
        activityMemberMapper.insert(activity.getId(), activity.getUserId());
    }
    private String convertToJson(Object obj) {
        if (obj == null) {
            return null;
        }
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }
}

4. Mapper XML 配置自增 ID

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jade.partnermatch.mapper.ActivityMapper">
    <!-- 關(guān)鍵:添加 useGeneratedKeys 和 keyProperty -->
    <insert id="insert" parameterType="Activity" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO activity
        (user_id, title, category, activity_type, activity_time, city,
         people_limit, current_people, contact_info, contact_visibility,
         create_time, status)
        VALUES
        (#{userId}, #{title}, #{category}, #{activityType}, #{activityTime}, #{city},
         #{peopleLimit}, #{currentPeople}, #{contactInfo}, #{contactVisibility},
         #{createTime}, #{status})
    </insert>
    <select id="list" resultType="Activity">
        SELECT * FROM activity
        WHERE status = 0
        ORDER BY create_time DESC
    </select>
</mapper>

5. 如果需要查詢時解析 JSON

// 在查詢后解析 JSON 字符串為 Map
public List<Activity> list() {
    List<Activity> activities = activityMapper.list();
    for (Activity activity : activities) {
        if (activity.getContactInfo() != null) {
            try {
                Map<String, Object> contactInfoMap = objectMapper.readValue(
                    activity.getContactInfo(), 
                    Map.class
                );
                // 使用 contactInfoMap...
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    return activities;
}

最終效果

數(shù)據(jù)庫成功存儲 JSON 數(shù)據(jù):

mysql> select * from activity;
+----+---------+--------------+----------+---------------+---------------------+------+--------------+----------------+-----------------------+--------------------+---------------------+--------+
| id | user_id | title        | category | activity_type | activity_time       | city | people_limit | current_people | contact_info          | contact_visibility | create_time         | status |
+----+---------+--------------+----------+---------------+---------------------+------+--------------+----------------+-----------------------+--------------------+---------------------+--------+
|  1 |       1 | 今晚王者三排 | GAME     | 王者榮耀      | 2026-03-23 20:00:00 | 南京 |            3 |              2 | {"wechat": "test123"} | PUBLIC             | 2026-03-24 20:22:59 |      0 |
|  2 |       1 | 今晚王者三排 | GAME     | 王者榮耀      | 2026-03-23 20:00:00 | 南京 |            3 |              1 | {"wechat": "test123"} | PUBLIC             | 2026-03-26 13:50:05 |      0 |
|  3 |       1 | 今晚王者三排 | GAME     | 王者榮耀      | 2026-03-23 20:00:00 | 南京 |            3 |              1 | {"wechat": "test123"} | PUBLIC             | 2026-03-26 13:51:45 |      0 |
|  4 |       1 | 今晚王者三排 | GAME     | 王者榮耀      | 2026-03-23 20:00:00 | 南京 |            3 |              1 | {"wechat": "test123"} | PUBLIC             | 2026-03-26 13:53:44 |      0 |
+----+---------+--------------+----------+---------------+---------------------+------+--------------+----------------+-----------------------+--------------------+---------------------+--------+
4 rows in set (0.00 sec)

方案優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 簡單直接:不需要學(xué)習(xí)復(fù)雜的 TypeHandler
  • 完全可控:自己決定如何轉(zhuǎn)換,易于調(diào)試
  • 兼容性好:前端傳字符串或?qū)ο蠖寄芴幚?/li>
  • 代碼清晰:邏輯一目了然

缺點(diǎn)

  • 查詢時需要手動解析 JSON
  • 如果需要頻繁操作 JSON 內(nèi)的字段,性能稍差

其他可選方案

方案2:使用 MyBatis 的 JacksonTypeHandler

在 Mapper XML 中配置:

<result column="contact_info" property="contactInfo" 
        typeHandler="org.apache.ibatis.type.JacksonTypeHandler"/>

方案3:自定義 TypeHandler

實(shí)現(xiàn) BaseTypeHandler 接口,自己處理 JSON 轉(zhuǎn)換。

總結(jié)

  • JSON 字段接收:DTO 使用 Object 或 Map 類型
  • JSON 字段存儲:Entity 使用 String 類型
  • 轉(zhuǎn)換工具:使用 Jackson 的 ObjectMapper
  • 自增 ID:MyBatis insert 添加 useGeneratedKeys 和 keyProperty

遇到類似問題不要慌,一步步排查,總能找到解決方案。

到此這篇關(guān)于SpringBoot+MyBatis處理JSON字段的完整指南的文章就介紹到這了,更多相關(guān)SpringBoot+MyBatis處理JSON字段內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jenkins服務(wù)器配置SSH實(shí)踐

    Jenkins服務(wù)器配置SSH實(shí)踐

    文章指導(dǎo)如何配置Jenkins用戶的SSH免密登錄:需獲取Jenkins公鑰并添加至目標(biāo)服務(wù)器authorized_keys文件,測試時若無需輸入密碼則表示配置成功,否則需檢查公鑰配置步驟
    2025-09-09
  • Java獲取隨機(jī)數(shù)的n種方法

    Java獲取隨機(jī)數(shù)的n種方法

    項目中,我們常常會用到隨機(jī)數(shù),本文主要介紹了Java獲取隨機(jī)數(shù)的n種方法,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • Lombok同時使?@Data和@Builder踩坑總結(jié)

    Lombok同時使?@Data和@Builder踩坑總結(jié)

    這篇文章主要介紹了Lombok同時使?@Data和@Builder踩坑總結(jié),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值需要的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助
    2022-05-05
  • 在springboot中如何給mybatis加攔截器

    在springboot中如何給mybatis加攔截器

    這篇文章主要介紹了在springboot中如何給mybatis加攔截器,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 從零實(shí)現(xiàn)一個簡單的Spring Bean容器的代碼案例

    從零實(shí)現(xiàn)一個簡單的Spring Bean容器的代碼案例

    Spring是一個非常流行的Java?Web開發(fā)框架,它提供了強(qiáng)大的依賴注入、面向切面編程、聲明式事務(wù)管理等功能,為開發(fā)者提供了高效、快速地構(gòu)建Web應(yīng)用程序的工具,在這篇文章中,咱們將一步一步地構(gòu)建一個簡單的SpringBean容器,需要的朋友可以參考下
    2023-06-06
  • JAVA對象中使用?static?和?String?基礎(chǔ)探究

    JAVA對象中使用?static?和?String?基礎(chǔ)探究

    這篇文章主要介紹了JAVA對象中使用static和String基礎(chǔ)探究,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 淺析SpringBoot中使用thymeleaf找不到.HTML文件的原因

    淺析SpringBoot中使用thymeleaf找不到.HTML文件的原因

    這篇文章主要介紹了SpringBoot中使用thymeleaf找不到.HTML文件的原因分析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Intellij IDEA十大快捷鍵

    Intellij IDEA十大快捷鍵

    Intellij IDEA中有很多快捷鍵讓人愛不釋手,stackoverflow上也有一些有趣的討論.這篇文章主要介紹了Intellij IDEA十大快捷鍵,需要的朋友可以參考下
    2018-03-03
  • mybatis的insert語句插入數(shù)據(jù)時的返回值的實(shí)現(xiàn)

    mybatis的insert語句插入數(shù)據(jù)時的返回值的實(shí)現(xiàn)

    這篇文章主要介紹了mybatis的insert語句插入數(shù)據(jù)時的返回值的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • RocketMQ源碼本地搭建調(diào)試方法

    RocketMQ源碼本地搭建調(diào)試方法

    這篇文章主要介紹了RocketMQ源碼本地搭建調(diào)試,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01

最新評論

同江市| 元阳县| 大埔区| 汉川市| 教育| 浮梁县| 峨边| 芜湖市| 江永县| 平果县| 裕民县| 玉树县| 静乐县| 陈巴尔虎旗| 多伦县| 凤台县| 上虞市| 天水市| 漳平市| 从江县| 吴忠市| 江达县| 庆阳市| 河北区| 方山县| 远安县| 鹤壁市| 屏山县| 浦北县| 广元市| 台湾省| 胶南市| 崇阳县| 新干县| 桐乡市| 乌拉特后旗| 贺州市| 南平市| 南宫市| 武邑县| 彭山县|