0基础学习Mybatis系列数据库操作框架——自定义类型处理器

大纲

  • Java模型类
  • 定义类型处理器
  • 配置文件
    • 和类型绑定
    • 和字段绑定
    • resultMap中绑定
  • Mapper代码
  • 测试
  • 类型对应关系表
  • 总结
  • 参考资料

我们有时候会在数据库中放入一个扩展字段,用于保存在表设计时尚未考虑到的、未来会加入的一些信息。这个字段我们一般使用字符串存储,格式是个Json。这样后续就可以很方便进行序列化和反序列化。
本文主要讲解如何自定义类型处理器,让Mybatis自动帮我们做序列化和反序列化。Json序列化工具我们采用fastjson库。
为了使用这个库,我们在Maven的pom.xml中加入如下片段

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.48</version>
        </dependency>

然后让Maven把依赖包下载到相应为止。

Java模型类

我们将Json字符串存储在《0基础学习Mybatis系列数据库操作框架——最小Demo》中创建的表的info_ltext字段。

info_ltext longtext comment ‘longtext’,

我们设计一个Java对象映射表结构,其中jsonElemList字段对应于表中info_ltext列,只是它不是String类型,而是我们自定义的JsonList 类型。

public class JsonType {
……
    private int intInfo;
    private JsonList jsonElemList;
}

我们将JsonList定义在JsonType内部,因为它只有在JsonType内中才有意义。JsonList中有一个成员变量jsonElemList 用于保存JsonElem数组。

    public static class JsonList {
    ……
        @JSONField()
        private List<JsonElem> jsonElemList = new ArrayList<>();
   }

JsonElem也定义在JsonType内部。它有两个成员变量,用于丰富Json结构。它实现了Cloneable接口,以方便后续对这个结构的深拷贝。

    public static class JsonElem implements Cloneable {
        @JSONField(name = "First")
        private int first;
        @JSONField(name = "Second")
        private String second;

        @Override
        public JsonElem clone() throws CloneNotSupportedException {
            JsonElem clonedJsonElem = null;
            try {
                clonedJsonElem = (JsonElem) super.clone();
                clonedJsonElem.setFirst(this.getFirst());
                clonedJsonElem.setSecond(this.getSecond());
            } finally {
            }

            return clonedJsonElem;
        }
    }

完整代码如下

package org.example.model;

import com.alibaba.fastjson.annotation.JSONField;

import java.util.ArrayList;
import java.util.List;

public class JsonType {

    public static class JsonList {
        public List<JsonElem> getJsonElemList() {
            return jsonElemList;
        }

        public void setJsonElemList(List<JsonElem> jsonElemList) {
            this.jsonElemList = jsonElemList;
        }
        @JSONField()
        private List<JsonElem> jsonElemList = new ArrayList<>();

        public JsonList(List<JsonElem> jsonElemList) {
            this.jsonElemList.addAll(jsonElemList);
        }
    }

    public static class JsonElem implements Cloneable {
        public int getFirst() {
            return first;
        }

        public void setFirst(int first) {
            this.first = first;
        }

        public String getSecond() {
            return second;
        }

        public void setSecond(String second) {
            this.second = second;
        }

        @JSONField(name = "First")
        private int first;
        @JSONField(name = "Second")
        private String second;

        public JsonElem(int first, String second) {
            this.first = first;
            this.second = second;
        }

        @Override
        public JsonElem clone() throws CloneNotSupportedException {
            JsonElem clonedJsonElem = null;
            try {
                clonedJsonElem = (JsonElem) super.clone();
                clonedJsonElem.setFirst(this.getFirst());
                clonedJsonElem.setSecond(this.getSecond());
            } finally {
            }

            return clonedJsonElem;
        }
    }

    public int getIntInfo() {
        return intInfo;
    }

    public void setIntInfo(int intInfo) {
        this.intInfo = intInfo;
    }

    public JsonList getJsonElemList() {
        return jsonElemList;
    }

    public void setJsonElemList(JsonList jsonElemList) {
        this.jsonElemList = jsonElemList;
    }

    private int intInfo;

    private JsonList jsonElemList;
}

定义类型处理器

我们的类型处理器继承于org.apache.ibatis.type.BaseTypeHandler,只要覆盖其几个NonNull方法即可

package org.example.typehandlers;

import com.alibaba.fastjson.JSON;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.example.model.JsonType;

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

@MappedJdbcTypes(JdbcType.LONGVARCHAR)
public class JsonListHandler extends BaseTypeHandler<JsonType.JsonList> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JsonType.JsonList parameter, JdbcType jdbcType) throws SQLException {
        String jsonStr = JSON.toJSONString(parameter);
        ps.setString(i, jsonStr);
    }

    @Override
    public JsonType.JsonList getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String jsonStr = rs.getString(columnName);
        return JSON.parseObject(jsonStr, JsonType.JsonList.class);
    }


    @Override
    public JsonType.JsonList getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String jsonStr = rs.getString(columnIndex);
        return JSON.parseObject(jsonStr, JsonType.JsonList.class);
    }

    @Override
    public JsonType.JsonList getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String jsonStr = cs.getString(columnIndex);
        return JSON.parseObject(jsonStr, JsonType.JsonList.class);
    }
}

这儿有个概念,就是Java类型、JDBC类型和数据库字段类型的对应关系。我们选用的longtext是Mysql数据库字段类型,其对应的Java类型是java.lang.string,对应的jdbc类型是LONGVARCHAR。所以上述代码我们加了@MappedJdbcTypes(JdbcType.LONGVARCHAR)注解。
关于这些对应关系,可以见文后内容。
setNonNullParameter方法是将JsonType.JsonList对象序列化成String,这样就和数据库中longtext类型对应上了。

info_ltext longtext comment ‘longtext’,

getNullableResult方法则是将String内容反序列化成为JsonType.JsonList对象,这样就和Java模型类对应上了。

public class JsonType {
……
    private int intInfo;
    private JsonList jsonElemList;
}

配置文件

配置文件主要完成自定义类型处理器JsonListHandler绑定的问题。主要有两种方法

和类型绑定

和类型绑定,即让自定义类型处理器和JDBC或者Java类型绑定。
本例我们采用和JDBC类型绑定。下面代码放置于mybatis-config-json.xml中。

    <typeHandlers>
        <typeHandler handler="org.example.typehandlers.JsonListHandler" jdbcType="LONGVARCHAR"/>
    </typeHandlers>

然后在SQL Mapper XML中,指定jsonElemList字段类型是上述绑定的类型。这样Mybatis在处理info_ltext字段时,就会使用自定义类型处理器JsonListHandler来处理。

    <update id="updateJsonTypeElems">
        update all_type set info_ltext  = #{jsonElemList, jdbcType=LONGVARCHAR} where info_int = #{intInfo}
    </update>

和字段绑定

和字段绑定就不用在mybatis-config-json.xml中做任何配置,只要在SQL Mapper XML中配置即可。
比如下例,定义item.jsonElemList类型处理器即可。

    <insert id="insertJsonTypeElems">
        insert into all_type(info_int, info_ltext) values
        <foreach item="item" collection="list" separator=",">
            (#{item.intInfo}, #{item.jsonElemList, typeHandler=org.example.typehandlers.JsonListHandler})
        </foreach>
    </insert>

resultMap中绑定

对于Select语句,我们可以使用《0基础学习Mybatis系列数据库操作框架——字段映射》中的方法,在映射表中定义。也不用在mybatis-config-json.xml中做任何配置。

    <resultMap id="jsonTypeResultMap" type="JsonType">
        <result property="intInfo" column="info_int"/>
        <result property="jsonElemList" column="info_char" jdbcType="LONGVARCHAR" typeHandler="org.example.typehandlers.JsonListHandler"/>
    </resultMap>

    <select id="selectJsonTypeElems" resultMap="jsonTypeResultMap">
        select * from all_type
    </select>

完整配置代码如下

<?xml version="1.0" encoding="UTF-8"?>
<!-- AllTypeMapper-1.xml -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.AllTypeMapper">
    <parameterMap id="jsonTypeParameterMap" type="JsonType">
        <parameter property="jsonElemList" jdbcType="LONGVARCHAR" typeHandler="org.example.typehandlers.JsonListHandler"/>
    </parameterMap>

    <resultMap id="jsonTypeResultMap" type="JsonType">
        <result property="intInfo" column="info_int"/>
        <result property="jsonElemList" column="info_char" jdbcType="LONGVARCHAR" typeHandler="org.example.typehandlers.JsonListHandler"/>
    </resultMap>

    <insert id="insertJsonTypeElems">
        insert into all_type(info_int, info_ltext) values
        <foreach item="item" collection="list" separator=",">
            (#{item.intInfo}, #{item.jsonElemList, typeHandler=org.example.typehandlers.JsonListHandler})
        </foreach>
    </insert>

    <update id="updateJsonTypeElems">
        update all_type set info_ltext  = #{jsonElemList, jdbcType=LONGVARCHAR} where info_int = #{intInfo}
    </update>

    <select id="selectJsonTypeElems" resultMap="jsonTypeResultMap">
        select * from all_type
    </select>
</mapper>

Mapper代码

在《0基础学习Mybatis系列数据库操作框架——增删改操作》引入的AllTypeMapper中新增如下三行方法以对应SQL Mapper XML中的三个方法id。

    long insertJsonTypeElems(List<JsonType> jsonTypeList);
    long updateJsonTypeElems(JsonType jsonType);
    List<JsonType> selectJsonTypeElems(int intInfo);

测试

package org.example;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.mapper.AllTypeMapper;
import org.example.model.AllType;
import org.example.model.JsonType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class JsonTest {
    private static SqlSessionFactory sqlSF;

    @BeforeAll
    static void CreateSessionFactory() throws IOException {
        InputStream in = Resources.getResourceAsStream("mybatis/config/mybatis-config-json.xml");
        sqlSF = new SqlSessionFactoryBuilder().build(in);
    }

    @Test
    void testUpdate() {
        try (SqlSession s = sqlSF.openSession(true)) {
            AllTypeMapper all_type_mapper = s.getMapper(AllTypeMapper.class);
            JsonType a = new JsonType();
            a.setIntInfo(1);

            List<JsonType.JsonElem> jsonElemList = Arrays.asList(
                    new JsonType.JsonElem(1,"1"),
                    new JsonType.JsonElem(2,"2")
            );
            JsonType.JsonList jsonList = new JsonType.JsonList(jsonElemList);

            a.setJsonElemList(jsonList);
            long count = all_type_mapper.updateJsonTypeElems(a);
            System.out.println(count);
        }
    }


    @Test
    void testSelect() {
        try (SqlSession s = sqlSF.openSession(true)) {
            AllTypeMapper all_type_mapper = s.getMapper(AllTypeMapper.class);
            List<JsonType> all = all_type_mapper.selectJsonTypeElems(1);
            for (JsonType a : Objects.requireNonNull(all)) {
                JsonType.JsonList jsonList = a.getJsonElemList();
                if (null == jsonList) {
                    continue;
                }
                for (JsonType.JsonElem b: jsonList.getJsonElemList()) {
                    System.out.printf("%d %s\n", b.getFirst(), b.getSecond());
                }
            }
        }
    }


    @Test
    void testinsertJsonTypeElems() {
        List<JsonType> jsonTypeList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            JsonType a = new JsonType();
            a.setIntInfo(i+100);

            List<JsonType.JsonElem> jsonElemList = Arrays.asList(
                    new JsonType.JsonElem(i+1100, "1"),
                    new JsonType.JsonElem(i+1200, "2")
            );
            JsonType.JsonList jsonList = new JsonType.JsonList(jsonElemList);
            a.setJsonElemList(jsonList);
            jsonTypeList.add(a);
        }


        try (SqlSession s = sqlSF.openSession(true)) {
            AllTypeMapper all_type_mapper = s.getMapper(AllTypeMapper.class);
            long count = all_type_mapper.insertJsonTypeElems(jsonTypeList);
            System.out.println(count);
        }
    }
}

在这里插入图片描述

类型对应关系表

类型处理器Java 类型JDBC 类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERIC 或 SMALLINT
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERIC 或 BIGINT
FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERIC 或 FLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERIC 或 DECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER 或未指定类型
EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHAR 或 LONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

总结

  • 自定义类型处理器类比较好写。只要定义好序列化和反序列化即可。
  • 主要容易混乱的点是在配置文件。
    • JDBC、Jave类型和自定义处理器绑定,需要在mybatis-config.xml中定义它们绑定关系;同时需要在SQL Mapper XML中的需要处理的字段上,用jdbcType或者javaType强调类型,才能让自定义类型处理器在这个字段上生效。
    • 直接在SQL Mapper XML中的需要处理的字段上指定类型处理器。这样就不用在mybatis-config.xml中做任何配置。
    • Select类型的SQL,除了直接在字段上标明类型处理器,还可以在resultMap上指定。

参考资料

  • https://mybatis.org/mybatis-3/zh_CN/configuration.html#typeHandlers

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/519689.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

短视频素材高清无水印购买要多少钱?

大家好&#xff01;在制作短视频时&#xff0c;找到短视频素材高清无水印是非常重要的。那么&#xff0c;短视频素材高清无水印在哪里找呢&#xff1f;今天&#xff0c;我要给大家推荐六个主流的视频素材分享网站&#xff0c;帮助你轻松获取高质量的短视频素材高清无水印&#…

C++读取.bin二进制文件

C读取.bin二进制文件 在C中&#xff0c;可以使用文件输入/输出流来进行二进制文件的读写操作&#xff0c;方便数据的保存和读写。 //C读取bin二进制文件 int read_bin() {std::ifstream file("data_100.bin", std::ios::in | std::ios::binary);if (file) {// 按照…

Hive初始化元数据库(默认是derby数据库)时候出现缺少方法的错误com.google.common.base.Preconditions

错误的出现&#xff1a; 下载好hive后&#xff0c;初始化元数据库&#xff08;使用内置derby数据测试&#xff09;&#xff0c;出现报错 初始化hive元数据&#xff1a;schematool -dbType derby -initSchema 这个原因是与 Hive 和 Hadoop 版本的 Guava 版本不一样导致的。 解决…

SpringBoot+ECharts+Html 字符云/词云案例详解

1. 技术点 SpringBoot、MyBatis、thymeleaf、MySQL、ECharts 等 2. 准备条件 在mysql中创建数据库echartsdb&#xff0c;数据库中创建表t_comment表&#xff0c;表中设置两个字段word与count&#xff0c;添加表中的数据。如&#xff1a;附件中的 echartsdb.sql 3. SpringBoot…

webrtcP2P通话流程

文章目录 webrtcP2P通话流程webrtc多对多 mesh方案webrtc多对多 mcu方案webrtc多对多 sfu方案webrtc案例测试getUserMediagetUserMedia基础示例-打开摄像头getUserMedia canvas - 截图 打开共享屏幕 webrtcP2P通话流程 在这里&#xff0c;stun服务器包括stun服务和turn转发服…

Aurora8b10b(1)IP核介绍并基于IP核进行设计

文章目录 前言一、IP核设置二、基于IP核进行设计2.1、设计框图2.2、aurora_8b10b_0模块2.3、aurora_8b10b_0_CLOCK_MODULE2.4、aurora_8b10b_0_SUPPORT_RESET_LOGIC2.5、aurora8b10b_channel模块2.6、IBUFDS_GTE2模块2.7、aurora_8b10b_0_gt_common_wrapper模块2.8、aurora8b10…

多路转接-epoll/Reactor(2)

epoll 上次说到了poll&#xff0c;它存在效率问题&#xff0c;因此出现了改进的poll----epoll。 目前epoll是公认的效率最高的多路转接的方案。 快速了解epoll接口 epoll_create&#xff1a; 这个参数其实已经被废弃了。 这个值只要大于0就可以了。 这是用来创建一个epoll模…

阿里云服务器资费:一年或1个月费用价格,2024年更新

阿里云服务器资费多少钱&#xff1f;一年或1个月费用价格&#xff1a;2核2G3M轻量服务器61元一年、ECS云服务器2核2G3M 99元一年&#xff0c;2核4G轻量165元一年&#xff0c;2核4G ECS 199元一年&#xff0c;阿里云服务器网aliyunfuwuqi.com整理如下&#xff1a; 1、ECS经济型e…

SpringBoot快速入门笔记(4)

文章目录 一、Vue框架1、前端环境准备2、简介3、快速开始4、事件绑定 二、Vue组件化开发1、NPM2、Vue Cli3、组件化开发4、SayHello自定义组件5、Movie自定义组件 一、Vue框架 1、前端环境准备 编码工具&#xff1a;VSCode 依赖管理&#xff1a;NPM 项目构建&#xff1a;VueCl…

Word·VBA文档合并

目录 1&#xff0c;复制法&#xff0c;不保留原文档格式2&#xff0c;复制法&#xff0c;保留原文档格式3&#xff0c;插入法&#xff0c;保留原文档格式 之前的文章《WordVBA实现邮件合并》虽然可以生成邮件合并文档结果&#xff0c;但是不能像《python实现word邮件合并》一样…

LeetCode-79. 单词搜索【数组 字符串 回溯 矩阵】

LeetCode-79. 单词搜索【数组 字符串 回溯 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;回溯 回溯三部曲。这里比较关键的是给board做标记&#xff0c;防止之后搜索时重复访问。解题思路二&#xff1a;回溯算法 dfs,直接看代码,很容易理解。visited哈希&#xff0c;防止…

Android面试题之Listview篇

秋招在即&#xff0c;计蒙准备在国庆假期结束前整理一套Android初级面试题籍&#xff0c;希望对大家有所帮助 提示&#xff1a;以下是本篇文章正文内容 ListView 1.当 ListView 数据集改变后&#xff0c;如何更新 ListView 使用该 ListView 的 adapter 的 notifyDataSetChange…

记录一下前端定时器清除失效的问题

目录 一、问题引入 二、错误代码&#xff1a; 三、错误原因 四、修正的代码 附 vue提供的线上运行代码网址以便证实可用性 一、问题引入 按理说&#xff0c;打开定时器 xxx setInterval(()>{ },100)&#xff0c;之后只要 clearInterval(xxx) 就可以顺利关闭定时器…

【浅尝C++】继承机制=>虚基表/菱形虚继承/继承的概念、定义/基类与派生类对象赋值转换/派生类的默认成员函数等详解

&#x1f3e0;专栏介绍&#xff1a;浅尝C专栏是用于记录C语法基础、STL及内存剖析等。 &#x1f3af;每日格言&#xff1a;每日努力一点点&#xff0c;技术变化看得见。 文章目录 继承的概念及定义继承的概念继承的定义定义格式继承关系与访问限定符 基类和派生类对象赋值转换继…

如果你正在投简历,一定要试试这款AI工具!

今天给大家分享一款AI简历神器 - BitBitFly AI 简历助手&#xff0c;这个工具可以帮助大家快速、精准投简历&#xff0c;并且提供职位匹配度分析报告&#xff0c;提供专业优化简历建议提高简历和职位匹配度&#xff0c;轻松拿下offer。 如果你在找工作的时候遇到以下问题&…

主流验证码对比及选型

目录 一、什么是验证码二、验证码的作用三、验证码的类型四、验证码厂商1、 [腾讯云验证码](https://cloud.tencent.com/document/product/1110)1.1 验证方式1.2 费用 2、[阿里云验证码](https://www.aliyun.com/activity/security/wafcaptcha)2.1 验证方式2.2 费用 3、[顶象验…

计算机网络——35什么是网络安全

什么是网络安全 机密性&#xff1a;只有发送方和预订的接收方能否理解传输的报文内容 发送方加密报文接收方解密报文 认证&#xff1a;发送方和接收方需要确认对方的身份报文完整性&#xff1a;发送方、接收方需要确认的报文在传输的过程中或者事后没有被改变访问控制和服务的…

android11 SystemUI入門之KeyguardPatternView解析

view层级树为&#xff1a; 被包含在 keyguard_host_view.xml中 。 <?xml version"1.0" encoding"utf-8"?> <!-- This is the host view that generally contains two sub views: the widget viewand the security view. --> <com.andro…

麻了,别再为难软件测试员了

前言 有不少技术友在测试群里讨论&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了,考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些测试工程师了。 这不&#xff0c;为了帮大家节约时…

RAG知识分享

文章目录 1.为什么要做RAG1.1. 解决幻觉问题1.1.1 直接输入问题1.1.2. 问题 相关知识 2. 什么是RAG2.1. 基本概念2.2. 基本RAG方法2.2.1. 知识预处理2.2.2. 知识检索2.2.3. 答案生成 3. RAG 与 Long Context3.1. Long Context3.2. RAG 与Long Context3.3 RAG对比Long Context的…