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

MyBatis復(fù)雜對(duì)象處理的兩種方式示例代碼文檔

 更新時(shí)間:2025年12月12日 17:17:09   作者:蛐蛐蜉蝣耶  
本文檔詳細(xì)介紹了如何在MyBatis中處理復(fù)雜對(duì)象的兩種方式:使用MyBatis-PlusTypeHandler處理嵌套對(duì)象(自動(dòng)序列化為JSON存儲(chǔ))和使用關(guān)聯(lián)對(duì)象映射處理多個(gè)字段,文中還涵蓋了自定義Mapper方法、事務(wù)管理和關(guān)聯(lián)數(shù)據(jù)操作的注意事項(xiàng),感興趣的朋友跟隨小編一起看看吧

MyBatis復(fù)雜對(duì)象處理示例代碼文檔

概述

本文檔詳細(xì)介紹了如何在 MyBatis中處理復(fù)雜對(duì)象的兩種方式:

  1. 使用 MyBatis-Plus TypeHandler 處理嵌套對(duì)象(自動(dòng)序列化為 JSON 存儲(chǔ))
  2. 使用關(guān)聯(lián)對(duì)象映射處理多個(gè)字段

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

文件路徑: db/schema.sql

-- 創(chuàng)建演示表結(jié)構(gòu)
drop table demo_entity;
-- 主表,使用TypeHandler方式存儲(chǔ)復(fù)雜對(duì)象
CREATE TABLE `demo_entity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(100) NOT NULL COMMENT '名稱(chēng)',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  `config_data` varchar(1000) DEFAULT NULL COMMENT '配置數(shù)據(jù)(JSON格式,由TypeHandler處理)',
  `street` varchar(200) DEFAULT NULL COMMENT '街道地址',
  `city` varchar(100) DEFAULT NULL COMMENT '城市',
  `zip_code` varchar(20) DEFAULT NULL COMMENT '郵政編碼',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='演示實(shí)體表';
select * from demo_entity;

實(shí)體類(lèi)設(shè)計(jì)

文件路徑: DemoEntity.java

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 com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@Data
@TableName(value = "demo_entity",autoResultMap = true)
public class DemoEntity implements Serializable {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @TableField("name")
    private String name;
    @TableField("create_time")
    private LocalDateTime createTime;
    // 方式一:使用TypeHandler處理復(fù)雜對(duì)象
    @TableField(value = "config_data", typeHandler = FastjsonTypeHandler.class)
    private ConfigData configData;
    // 方式二:關(guān)聯(lián)對(duì)象(通過(guò)其他字段映射)
    // @TableField(exist = false)是由于mybatis-plus的原因,
    // 當(dāng)實(shí)體類(lèi)中存在該字段時(shí),會(huì)默認(rèn)認(rèn)為該字段是關(guān)聯(lián)字段,會(huì)自動(dòng)填充關(guān)聯(lián)對(duì)象。
    @TableField(exist = false)
    private AddressInfo addressInfo;
    @Data
    public static class ConfigData implements Serializable {
        private String theme;
        private List<String> permissions;
        private Boolean enabled;
    }
    @Data
    public static class AddressInfo implements Serializable {
        private String street;
        private String city;
        private String zipCode;
    }
}

Mapper 接口

文件路徑: DemoEntityMapper.java

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.credithc.risk.entity.DemoEntity;
import org.apache.ibatis.annotations.Param;
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
    /**
     * 自定義插入方法,處理關(guān)聯(lián)對(duì)象
     */
    int insertWithAddress(@Param("entity") DemoEntity entity);
    /**
     * 自定義更新方法,處理關(guān)聯(lián)對(duì)象
     */
    int updateWithAddress(@Param("entity") DemoEntity entity);
    /**
     * 根據(jù)ID查詢(xún)包含關(guān)聯(lián)對(duì)象的完整實(shí)體
     */
    DemoEntity selectWithAddressById(@Param("id") Long id);
}

Mapper XML 映射文件

文件路徑: DemoEntityMapper.xml

<?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="DemoEntityMapper">
    <resultMap id="BaseResultMap" type="DemoEntity">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="createTime" column="create_time"/>
        <result property="configData" column="config_data"
                typeHandler="com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler"/>
        <!-- 關(guān)聯(lián)對(duì)象映射 -->
        <association property="addressInfo" javaType="DemoEntity$AddressInfo">
            <result property="street" column="street"/>
            <result property="city" column="city"/>
            <result property="zipCode" column="zip_code"/>
        </association>
    </resultMap>
    <insert id="insertWithAddress" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO demo_entity (name, create_time, config_data,street,city, zip_code)
        VALUES (#{entity.name}, #{entity.createTime},
                #{entity.configData, typeHandler=com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler},
                #{entity.addressInfo.street},#{entity.addressInfo.city},#{entity.addressInfo.zipCode})
    </insert>
    <insert id="updateWithAddress">
        UPDATE demo_entity
        SET name = #{entity.name},
            create_time = #{entity.createTime},
            config_data = #{entity.configData, typeHandler=com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler},
            street = #{entity.addressInfo.street},
            city = #{entity.addressInfo.city},
            zip_code = #{entity.addressInfo.zipCode}
        WHERE id = #{entity.id}
    </insert>
    <select id="selectWithAddressById" resultMap="BaseResultMap">
        SELECT
            id,name,create_time,config_data,
            street,
            city,
            zip_code
        FROM demo_entity
        WHERE id = #{id}
    </select>
</mapper>

Service 層接口與實(shí)現(xiàn)

Service 接口

文件路徑: DemoEntityService.java

import com.baomidou.mybatisplus.extension.service.IService;
import com.credithc.risk.entity.DemoEntity;
public interface DemoEntityService extends IService<DemoEntity> {
    /**
     * 保存Demo實(shí)體,同時(shí)處理兩種不同類(lèi)型的復(fù)雜字段
     */
    DemoEntity saveDemoEntity(DemoEntity entity);
    /**
     * 獲取包含關(guān)聯(lián)地址信息的完整實(shí)體
     */
    DemoEntity getDemoEntityWithAddress(Long id);
}

Service 實(shí)現(xiàn)類(lèi)

文件路徑: DemoEntityServiceImpl.java

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.credithc.risk.dao.DemoEntityMapper;
import com.credithc.risk.entity.DemoEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
@Service
public class DemoEntityServiceImpl extends ServiceImpl<DemoEntityMapper, DemoEntity> implements DemoEntityService {
    @Resource
    private DemoEntityMapper demoEntityMapper;
    @Override
    @Transactional
    public DemoEntity saveDemoEntity(DemoEntity entity) {
        // 保存主實(shí)體(TypeHandler方式自動(dòng)處理configData)
        if (entity.getId() == null) {
            entity.setCreateTime(LocalDateTime.now());
            // demoEntityMapper.insert(entity);此方法為mybatis-plus提供的方法,會(huì)自動(dòng)處理configData,但不會(huì)處理addressInfo
            // 下面的方法會(huì)自動(dòng)處理configData和addressInfo
            demoEntityMapper.insertWithAddress(entity);
        } else {
            // demoEntityMapper.updateById(entity);此方法為mybatis-plus提供的方法,會(huì)自動(dòng)處理configData,但不會(huì)處理addressInfo
            // 下面的方法會(huì)自動(dòng)處理configData和addressInfo
            demoEntityMapper.updateWithAddress(entity);
        }
        return entity;
    }
    @Override
    public DemoEntity getDemoEntityWithAddress(Long id) {
        // demoEntityMapper.selectById(id);此方法為mybatis-plus提供的方法,會(huì)自動(dòng)處理configData,但不會(huì)處理addressInfo
        // 下面的方法會(huì)自動(dòng)處理configData和addressInfo
        return demoEntityMapper.selectWithAddressById(id);
    }
}

測(cè)試用例

文件路徑: DemoEntityServiceTest.java

import com.credithc.risk.entity.DemoEntity;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
public class DemoEntityServiceTest {
    @Resource
    private DemoEntityService demoEntityService;
    @Test
    public void testSaveAndRetrieveEntityWithTypeHandler() {
        // 創(chuàng)建測(cè)試實(shí)體
        DemoEntity entity = new DemoEntity();
        entity.setName("Test Entity With TypeHandler");
        // 設(shè)置TypeHandler處理的復(fù)雜對(duì)象
        DemoEntity.ConfigData configData = new DemoEntity.ConfigData();
        configData.setTheme("dark");
        configData.setPermissions(Arrays.asList("read", "write", "delete"));
        configData.setEnabled(true);
        entity.setConfigData(configData);
        // 保存實(shí)體
        DemoEntity savedEntity = demoEntityService.saveDemoEntity(entity);
        // 驗(yàn)證保存成功
        assertNotNull(savedEntity.getId());
        assertEquals("Test Entity With TypeHandler", savedEntity.getName());
        assertNotNull(savedEntity.getConfigData());
        assertEquals("dark", savedEntity.getConfigData().getTheme());
        assertEquals(3, savedEntity.getConfigData().getPermissions().size());
        assertTrue(savedEntity.getConfigData().getEnabled());
        // 驗(yàn)證從數(shù)據(jù)庫(kù)重新加載的數(shù)據(jù)
        DemoEntity reloadedEntity = demoEntityService.getById(savedEntity.getId());
        assertNotNull(reloadedEntity);
        assertEquals("Test Entity With TypeHandler", reloadedEntity.getName());
        assertNotNull(reloadedEntity.getConfigData());
        assertEquals("dark", reloadedEntity.getConfigData().getTheme());
        assertEquals(3, reloadedEntity.getConfigData().getPermissions().size());
        assertTrue(reloadedEntity.getConfigData().getEnabled());
    }
    @Test
    public void testSaveAndRetrieveEntityWithAssociation() {
        // 創(chuàng)建測(cè)試實(shí)體
        DemoEntity entity = new DemoEntity();
        entity.setName("Test Entity With Association");
        entity.setCreateTime(LocalDateTime.now());
        // 設(shè)置關(guān)聯(lián)對(duì)象
        DemoEntity.AddressInfo addressInfo = new DemoEntity.AddressInfo();
        addressInfo.setStreet("123 Main St");
        addressInfo.setCity("Beijing");
        addressInfo.setZipCode("100000");
        entity.setAddressInfo(addressInfo);
        // 保存實(shí)體
        DemoEntity savedEntity = demoEntityService.saveDemoEntity(entity);
        // 驗(yàn)證保存成功
        assertNotNull(savedEntity.getId());
        assertEquals("Test Entity With Association", savedEntity.getName());
        assertNotNull(savedEntity.getAddressInfo());
        assertEquals("123 Main St", savedEntity.getAddressInfo().getStreet());
        assertEquals("Beijing", savedEntity.getAddressInfo().getCity());
        assertEquals("100000", savedEntity.getAddressInfo().getZipCode());
        // 驗(yàn)證從數(shù)據(jù)庫(kù)重新加載的數(shù)據(jù)(包含關(guān)聯(lián)對(duì)象)
        DemoEntity reloadedEntity = demoEntityService.getDemoEntityWithAddress(savedEntity.getId());
        assertNotNull(reloadedEntity);
        assertEquals("Test Entity With Association", reloadedEntity.getName());
        assertNotNull(reloadedEntity.getAddressInfo());
        assertEquals("123 Main St", reloadedEntity.getAddressInfo().getStreet());
        assertEquals("Beijing", reloadedEntity.getAddressInfo().getCity());
        assertEquals("100000", reloadedEntity.getAddressInfo().getZipCode());
    }
}

技術(shù)要點(diǎn)說(shuō)明

1. TypeHandler 方式處理復(fù)雜對(duì)象

  • 在實(shí)體類(lèi)中使用 @TableField 注解配合 typeHandler 參數(shù)指定處理器
  • MyBatis-Plus 提供了 FastjsonTypeHandler 來(lái)自動(dòng)將復(fù)雜對(duì)象序列化為 JSON 字符串存儲(chǔ)到數(shù)據(jù)庫(kù)
  • 適用于單個(gè)復(fù)雜對(duì)象字段的處理

2. 關(guān)聯(lián)對(duì)象映射方式

  • 使用 @TableField(exist = false) 標(biāo)記非數(shù)據(jù)庫(kù)字段
  • 在 XML 映射文件中使用 <association> 標(biāo)簽進(jìn)行關(guān)聯(lián)對(duì)象映射
  • 適用于需要將復(fù)雜對(duì)象的屬性拆分存儲(chǔ)到多個(gè)數(shù)據(jù)庫(kù)字段的情況

3. 自定義 Mapper 方法

為了處理關(guān)聯(lián)對(duì)象,我們自定義了以下方法:

  • insertWithAddress: 插入實(shí)體及關(guān)聯(lián)對(duì)象數(shù)據(jù)
  • updateWithAddress: 更新實(shí)體及關(guān)聯(lián)對(duì)象數(shù)據(jù)
  • selectWithAddressById: 查詢(xún)實(shí)體及關(guān)聯(lián)對(duì)象數(shù)據(jù)
  • 關(guān)聯(lián)數(shù)據(jù)的操作切勿使用mybatis-plus默認(rèn)方法可能會(huì)不生效

4. 事務(wù)管理

在 Service 實(shí)現(xiàn)類(lèi)中使用了 @Transactional 注解確保數(shù)據(jù)一致性。

在MyBatis生態(tài)中,當(dāng)處理數(shù)據(jù)庫(kù)中的關(guān)聯(lián)關(guān)系時(shí),Association和Collection是兩個(gè)非常重要的概念。它們能夠幫助我們高效地獲取和處理與主實(shí)體相關(guān)的其他實(shí)體信息。無(wú)論是一對(duì)一(Association)還是一對(duì)多(Collection)的關(guān)系,再加上MyBatis-Plus TypeHandler模式,可以根據(jù)具體業(yè)務(wù)需求選擇合適的方式,正確地使用它們可以讓我們的持久層代碼更加清晰和高效。

到此這篇關(guān)于MyBatis復(fù)雜對(duì)象處理示例代碼文檔的文章就介紹到這了,更多相關(guān)MyBatis復(fù)雜對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)之事件驅(qū)動(dòng)與CQRS

    詳解領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)之事件驅(qū)動(dòng)與CQRS

    這篇文章分析了如何應(yīng)用事件來(lái)分離軟件核心復(fù)雜度。探究CQRS為什么廣泛應(yīng)用于DDD項(xiàng)目中,以及如何落地實(shí)現(xiàn)CQRS框架。當(dāng)然我們也要警惕一些失敗的教訓(xùn),利弊分析以后再去抉擇正確的應(yīng)對(duì)之道
    2021-06-06
  • MybatisPlus lambdaQueryWrapper中常用方法的使用

    MybatisPlus lambdaQueryWrapper中常用方法的使用

    本文主要介紹了MybatisPlus lambdaQueryWrapper中常用方法的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java中的泛型詳解

    Java中的泛型詳解

    這篇文章主要介紹了Java中的泛型詳解,本文講解了泛型類(lèi)或接口、從泛型類(lèi)派生子類(lèi)、偽泛型、類(lèi)型通配符、通配符的上限、通配符的下限、擦除和轉(zhuǎn)換等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • SpringBoot?Java通過(guò)API的方式調(diào)用騰訊智能體(騰訊元寶)代碼示例

    SpringBoot?Java通過(guò)API的方式調(diào)用騰訊智能體(騰訊元寶)代碼示例

    這篇文章主要介紹了SpringBoot?Java通過(guò)API的方式調(diào)用騰訊智能體(騰訊元寶)的相關(guān)資料,詳細(xì)說(shuō)明參數(shù)獲取及動(dòng)態(tài)處理方法,提供結(jié)果字符串轉(zhuǎn)數(shù)組技巧,需要的朋友可以參考下
    2025-06-06
  • java 根據(jù)前端返回的字段名進(jìn)行查詢(xún)數(shù)據(jù)

    java 根據(jù)前端返回的字段名進(jìn)行查詢(xún)數(shù)據(jù)

    本文介紹了如何在Java中使用SpringDataJPA實(shí)現(xiàn)動(dòng)態(tài)查詢(xún)功能,以便根據(jù)前端傳遞的字段名動(dòng)態(tài)構(gòu)建查詢(xún)語(yǔ)句,通過(guò)創(chuàng)建實(shí)體類(lèi)、Repository接口、構(gòu)建動(dòng)態(tài)查詢(xún)、在Service層和Controller中使用動(dòng)態(tài)查詢(xún),實(shí)現(xiàn)了前后端分離架構(gòu)中的靈活查詢(xún)需求
    2024-11-11
  • 第三方包jintellitype實(shí)現(xiàn)Java設(shè)置全局熱鍵

    第三方包jintellitype實(shí)現(xiàn)Java設(shè)置全局熱鍵

    本文主要介紹了,在java中使用第三方插件包jintellitype來(lái)實(shí)現(xiàn)全局熱鍵,非常的簡(jiǎn)單,但是很實(shí)用,有需要的朋友可以參考下,歡迎一起來(lái)參與改進(jìn)此項(xiàng)目
    2014-09-09
  • 詳解JAVA使用Comparator接口實(shí)現(xiàn)自定義排序

    詳解JAVA使用Comparator接口實(shí)現(xiàn)自定義排序

    這篇文章主要介紹了JAVA使用Comparator接口實(shí)現(xiàn)自定義排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • spring boot中使用http請(qǐng)求的示例代碼

    spring boot中使用http請(qǐng)求的示例代碼

    本篇文章主要介紹了spring boot中 使用http請(qǐng)求的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java中進(jìn)程與線(xiàn)程的區(qū)別

    Java中進(jìn)程與線(xiàn)程的區(qū)別

    這篇文章主要介紹了Java進(jìn)程與線(xiàn)程的區(qū)別,進(jìn)程(Process)是操作系統(tǒng)分配資源的基本單位,線(xiàn)程(Thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的基本單位,下文更多兩者區(qū)別。需要的小伙伴可以參考一下
    2022-05-05
  • Feign實(shí)現(xiàn)多文件上傳,Open?Feign多文件上傳問(wèn)題及解決

    Feign實(shí)現(xiàn)多文件上傳,Open?Feign多文件上傳問(wèn)題及解決

    這篇文章主要介紹了Feign實(shí)現(xiàn)多文件上傳,Open?Feign多文件上傳問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論

文化| 丰台区| 嵊州市| 大宁县| 云林县| 古交市| 柞水县| 宜黄县| 社会| 孟村| 泗水县| 乃东县| 永昌县| 孟州市| 肇源县| 行唐县| 鹤岗市| 平安县| 郴州市| 涿鹿县| 东乌| 松桃| 淮滨县| 宝坻区| 湘阴县| 建阳市| 保康县| 布尔津县| 女性| 德化县| 嵊州市| 灵宝市| 阳西县| 来宾市| 连城县| 松溪县| 丽水市| 中超| 盖州市| 扎鲁特旗| 恩施市|