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

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

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

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

概述

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

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

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

文件路徑: db/schema.sql

-- 創(chuàng)建演示表結(jié)構(gòu)
drop table demo_entity;
-- 主表,使用TypeHandler方式存儲復(fù)雜對象
CREATE TABLE `demo_entity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(100) NOT NULL COMMENT '名稱',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
  `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='演示實體表';
select * from demo_entity;

實體類設(shè)計

文件路徑: 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ù)雜對象
    @TableField(value = "config_data", typeHandler = FastjsonTypeHandler.class)
    private ConfigData configData;
    // 方式二:關(guān)聯(lián)對象(通過其他字段映射)
    // @TableField(exist = false)是由于mybatis-plus的原因,
    // 當(dāng)實體類中存在該字段時,會默認(rèn)認(rèn)為該字段是關(guān)聯(lián)字段,會自動填充關(guān)聯(lián)對象。
    @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)對象
     */
    int insertWithAddress(@Param("entity") DemoEntity entity);
    /**
     * 自定義更新方法,處理關(guān)聯(lián)對象
     */
    int updateWithAddress(@Param("entity") DemoEntity entity);
    /**
     * 根據(jù)ID查詢包含關(guān)聯(lián)對象的完整實體
     */
    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)對象映射 -->
        <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 層接口與實現(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實體,同時處理兩種不同類型的復(fù)雜字段
     */
    DemoEntity saveDemoEntity(DemoEntity entity);
    /**
     * 獲取包含關(guān)聯(lián)地址信息的完整實體
     */
    DemoEntity getDemoEntityWithAddress(Long id);
}

Service 實現(xiàn)類

文件路徑: 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) {
        // 保存主實體(TypeHandler方式自動處理configData)
        if (entity.getId() == null) {
            entity.setCreateTime(LocalDateTime.now());
            // demoEntityMapper.insert(entity);此方法為mybatis-plus提供的方法,會自動處理configData,但不會處理addressInfo
            // 下面的方法會自動處理configData和addressInfo
            demoEntityMapper.insertWithAddress(entity);
        } else {
            // demoEntityMapper.updateById(entity);此方法為mybatis-plus提供的方法,會自動處理configData,但不會處理addressInfo
            // 下面的方法會自動處理configData和addressInfo
            demoEntityMapper.updateWithAddress(entity);
        }
        return entity;
    }
    @Override
    public DemoEntity getDemoEntityWithAddress(Long id) {
        // demoEntityMapper.selectById(id);此方法為mybatis-plus提供的方法,會自動處理configData,但不會處理addressInfo
        // 下面的方法會自動處理configData和addressInfo
        return demoEntityMapper.selectWithAddressById(id);
    }
}

測試用例

文件路徑: 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)建測試實體
        DemoEntity entity = new DemoEntity();
        entity.setName("Test Entity With TypeHandler");
        // 設(shè)置TypeHandler處理的復(fù)雜對象
        DemoEntity.ConfigData configData = new DemoEntity.ConfigData();
        configData.setTheme("dark");
        configData.setPermissions(Arrays.asList("read", "write", "delete"));
        configData.setEnabled(true);
        entity.setConfigData(configData);
        // 保存實體
        DemoEntity savedEntity = demoEntityService.saveDemoEntity(entity);
        // 驗證保存成功
        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());
        // 驗證從數(shù)據(jù)庫重新加載的數(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)建測試實體
        DemoEntity entity = new DemoEntity();
        entity.setName("Test Entity With Association");
        entity.setCreateTime(LocalDateTime.now());
        // 設(shè)置關(guān)聯(lián)對象
        DemoEntity.AddressInfo addressInfo = new DemoEntity.AddressInfo();
        addressInfo.setStreet("123 Main St");
        addressInfo.setCity("Beijing");
        addressInfo.setZipCode("100000");
        entity.setAddressInfo(addressInfo);
        // 保存實體
        DemoEntity savedEntity = demoEntityService.saveDemoEntity(entity);
        // 驗證保存成功
        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());
        // 驗證從數(shù)據(jù)庫重新加載的數(shù)據(jù)(包含關(guān)聯(lián)對象)
        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ù)要點說明

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

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

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

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

3. 自定義 Mapper 方法

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

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

4. 事務(wù)管理

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

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

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

相關(guān)文章

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

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

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

    MybatisPlus lambdaQueryWrapper中常用方法的使用

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

    Java中的泛型詳解

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

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

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

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

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

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

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

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

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

    spring boot中使用http請求的示例代碼

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

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

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

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

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

最新評論

黔西县| 朔州市| 溧水县| 怀宁县| 牙克石市| 天峻县| 三门县| 屏山县| 木兰县| 岑巩县| 遂平县| 唐海县| 营山县| 遂川县| 阿克陶县| 南京市| 常山县| 拜城县| 开封市| 兰西县| 灵台县| 岫岩| 壶关县| 同江市| 五大连池市| 上高县| 阜新市| 罗江县| 遂宁市| 轮台县| 惠安县| 博乐市| 柳江县| 东城区| 乡宁县| 梨树县| 屯门区| 荔浦县| 雷山县| 海安县| 咸宁市|