当前位置: 首页 > news >正文

深入理解 MyBatis 代理机制

在 Java 开发领域,MyBatis 是一款优秀的持久层框架,它极大地简化了数据库操作,提高了开发效率。其中,代理机制作为 MyBatis 的核心特性之一,在连接 Java 代码与数据库操作中发挥着关键作用。本文将深入探讨 MyBatis 代理机制的原理、实现过程以及实际应用,帮助开发者更好地理解和使用这一强大功能。​

一、MyBatis 代理机制概述​

MyBatis 的代理机制,简单来说,就是通过创建接口的代理对象,让开发者能够以面向接口编程的方式操作数据库,而无需编写大量重复的 SQL 映射和数据库操作代码。当我们定义一个 Mapper 接口,并在 MyBatis 的配置文件中进行相应配置后,MyBatis 会自动为该接口生成代理对象。开发者只需调用代理对象的方法,MyBatis 就能根据方法名和参数,找到对应的 SQL 语句并执行,将结果返回给调用者。​

这种代理机制基于 Java 的动态代理技术,结合 MyBatis 自身的 SQL 映射和执行逻辑,实现了数据库操作的高度抽象和自动化。它使得代码更加简洁、易维护,同时也遵循了面向对象编程的设计原则,提高了代码的可扩展性。​

二、MyBatis 代理机制原理​

1. 动态代理基础​

在深入了解 MyBatis 代理机制之前,我们需要先掌握 Java 动态代理的基本概念。Java 提供了两种动态代理方式:JDK 动态代理和 CGLIB 动态代理。​

JDK 动态代理是 Java 自带的动态代理机制,它基于接口实现。通过java.lang.reflect.Proxy类和InvocationHandler接口,JDK 动态代理能够在运行时动态生成实现指定接口的代理类。代理类的方法调用会被转发到InvocationHandler的invoke方法中,在invoke方法里可以编写具体的业务逻辑,比如日志记录、权限验证等。​

CGLIB(Code Generation Library)动态代理则是通过继承的方式实现。它不需要接口,而是通过字节码技术在运行时动态生成被代理类的子类作为代理类。CGLIB 的代理类会重写被代理类的方法,在方法调用前后插入自定义的逻辑。​

2.MyBatis 代理机制实现原理​

MyBatis 默认使用 JDK 动态代理来生成 Mapper 接口的代理对象。其实现原理如下:​

  • 配置解析:MyBatis 在启动时,会解析配置文件(如mybatis-config.xml)和 Mapper 映射文件(如*.xml),将 SQL 语句和 Mapper 接口方法进行映射绑定。​
  • 代理对象创建:当开发者通过SqlSession获取 Mapper 接口的代理对象时,MyBatis 会调用MapperProxyFactory类的newInstance方法来创建代理对象。在这个过程中,MyBatis 使用java.lang.reflect.Proxy.newProxyInstance方法生成代理对象,该方法的参数包括类加载器、代理对象要实现的接口数组以及InvocationHandler实例。​
  • 方法调用:当调用代理对象的方法时,实际上会调用MapperProxy类(实现了InvocationHandler接口)的invoke方法。在invoke方法中,MyBatis 会根据方法名和参数,从之前解析绑定的 SQL 映射中找到对应的 SQL 语句,并通过SqlSession执行该 SQL 语句。最后,将执行结果进行处理和返回。​

三、MyBatis 代理机制实现流程​

1. 定义 Mapper 接口​

首先,我们需要定义一个 Mapper 接口,该接口中声明了与数据库操作相关的方法。例如,定义一个UserMapper接口,用于操作用户表:

public interface UserMapper {User selectUserById(int id);List<User> selectAllUsers();int insertUser(User user);int updateUser(User user);int deleteUser(int id);
}

2 编写 Mapper 映射文件​

接下来,编写对应的 Mapper 映射文件(如UserMapper.xml),在文件中定义 SQL 语句,并将其与 Mapper 接口方法进行绑定。例如:

<mapper namespace="com.example.mapper.UserMapper"><select id="selectUserById" resultType="com.example.entity.User">SELECT * FROM user WHERE id = #{id}</select><select id="selectAllUsers" resultType="com.example.entity.User">SELECT * FROM user</select><insert id="insertUser" parameterType="com.example.entity.User">INSERT INTO user (name, age, email) VALUES (#{name}, #{age}, #{email})</insert><update id="updateUser" parameterType="com.example.entity.User">UPDATE user SET name = #{name}, age = #{age}, email = #{email} WHERE id = #{id}</update><delete id="deleteUser">DELETE FROM user WHERE id = #{id}</delete>
</mapper>

3.配置 MyBatis​

在 MyBatis 的主配置文件(如mybatis-config.xml)中,注册 Mapper 映射文件:

<configuration><mappers><mapper resource="com/example/mapper/UserMapper.xml"/></mappers>
</configuration>

4 获取代理对象并调用方法​

最后,在 Java 代码中通过SqlSession获取 Mapper 接口的代理对象,并调用其方法:

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.selectUserById(1);System.out.println(user);
}

四、MyBatis 代理机制源码剖析​

1.MapperProxyFactory 类​

MapperProxyFactory类负责创建 Mapper 接口的代理对象。其核心方法newInstance代码如下:

public T newInstance(SqlSession sqlSession) {final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);
}protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

可以看到,newInstance方法首先创建了一个MapperProxy实例,然后通过Proxy.newProxyInstance方法生成代理对象。​

2.MapperProxy 类​

MapperProxy类实现了InvocationHandler接口,其invoke方法是代理机制的核心逻辑所在:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else if (isDefaultMethod(method)) {return invokeDefaultMethod(proxy, method, args);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}final MapperMethod mapperMethod = cachedMapperMethod(method);return mapperMethod.execute(sqlSession, args);
}

在invoke方法中,首先判断方法是否是Object类的方法或默认方法,如果是则直接调用。否则,通过cachedMapperMethod方法获取对应的MapperMethod对象,然后调用MapperMethod的execute方法执行 SQL 语句并返回结果。​

3.MapperMethod 类​

MapperMethod类封装了 SQL 语句的执行逻辑。其execute方法根据方法类型(查询、插入、更新、删除)调用SqlSession的相应方法执行 SQL:

public Object execute(SqlSession sqlSession, Object[] args) {Object result;switch (command.getType()) {case INSERT: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT:if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else if (method.returnsCursor()) {result = executeForCursor(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);if (method.returnsOptional()&& (result == null ||!method.getReturnType().equals(result.getClass()))) {result = Optional.ofNullable(result);}}break;default:throw new BindingException("Unknown execution method for: " + command.getName());}if (result == null && method.getReturnType().isPrimitive() &&!method.returnsVoid()) {throw new BindingException("Mapper method '" + command.getName()+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");}return result;
}

五、MyBatis 代理机制的优势与应用场景​

1. 优势​

  • 简化代码:通过代理机制,开发者只需关注 Mapper 接口的定义和方法调用,无需编写繁琐的数据库连接、SQL 执行和结果处理代码,大大提高了开发效率。​
  • 解耦:将数据库操作与业务逻辑分离,使得代码结构更加清晰,便于维护和扩展。​
  • 提高可维护性:当 SQL 语句发生变化时,只需修改 Mapper 映射文件,而无需修改 Java 代码,降低了代码的维护成本。​
  • 遵循设计原则:采用面向接口编程,符合依赖倒置原则,提高了代码的可测试性和可扩展性。​

2.应用场景​

  • CRUD 操作:在日常的数据库增删改查操作中,MyBatis 代理机制能够快速实现功能,减少重复代码的编写。​
  • 复杂查询:对于复杂的 SQL 查询,通过 Mapper 映射文件可以灵活编写 SQL 语句,并通过代理对象调用方法获取结果。​
  • 分库分表:在分布式系统中,当涉及到分库分表时,MyBatis 代理机制可以结合动态数据源等技术,实现对不同数据库的操作。​

六、注意点

1.MyBatis 代理机制原理

MyBatis 采用代理模式,在内存中动态生成 DAO 接口的代理类及其实例。这一机制能够让开发者仅定义 DAO 接口,而无需手动编写实现类,MyBatis 会依据映射文件(如 SqlMapper.xml)中的配置自动生成对应的 SQL 语句并执行。

2.使用 MyBatis 代理机制的前提条件

  • SqlMapper.xml 文件的 namespacenamespace 必须是 DAO 接口的全限定名称。这是为了让 MyBatis 能够明确该映射文件对应的是哪个 DAO 接口。
  • SqlMapper.xml 文件的 idid 必须是 DAO 接口中的方法名。这样 MyBatis 就能把接口方法和映射文件里的 SQL 语句关联起来。

3.代码示例与解释

定义 DAO 接口

// AccountDao.java
package com.example.dao;import com.example.entity.Account;
import java.util.List;public interface AccountDao {// 查询所有账户信息List<Account> findAll();// 根据 ID 查询账户信息Account findById(int id);
}

这里定义了一个 AccountDao 接口,包含两个方法:findAll() 用于查询所有账户信息,findById(int id) 用于根据 ID 查询账户信息。

 编写 SqlMapper.xml 文件

<!-- SqlMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.AccountDao"><!-- 查询所有账户信息 --><select id="findAll" resultType="com.example.entity.Account">SELECT * FROM account</select><!-- 根据 ID 查询账户信息 --><select id="findById" parameterType="int" resultType="com.example.entity.Account">SELECT * FROM account WHERE id = #{id}</select>
</mapper>

在这个映射文件中,namespace 是 com.example.dao.AccountDao,和 AccountDao 接口的全限定名称一致。每个 select 标签的 id 分别对应 AccountDao 接口中的方法名。

获取 DAO 接口的代理实例

import com.example.dao.AccountDao;
import com.example.entity.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;public class Main {public static void main(String[] args) {// 加载 MyBatis 配置文件String resource = "mybatis-config.xml";InputStream inputStream = Main.class.getClassLoader().getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 获取 SqlSession 实例try (SqlSession sqlSession = sqlSessionFactory.openSession()) {// 获取 AccountDao 接口的代理实例AccountDao accountDao = sqlSession.getMapper(AccountDao.class);// 调用代理实例的方法List<Account> accounts = accountDao.findAll();for (Account account : accounts) {System.out.println(account);}Account account = accountDao.findById(1);System.out.println(account);}}
}

七、总结​

MyBatis 代理机制是其强大功能的重要组成部分,它基于 Java 动态代理技术,通过简洁的接口定义和配置,实现了数据库操作的自动化和抽象化。深入理解 MyBatis 代理机制的原理、实现流程和源码,有助于开发者更好地运用这一技术,提高开发效率和代码质量。在实际项目中,合理使用 MyBatis 代理机制,能够让我们的持久层代码更加简洁、高效、易维护。​

希望本文对大家理解和使用 MyBatis 代理机制有所帮助。如果在使用过程中遇到任何问题,欢迎在评论区留言讨论。​

上述内容详细介绍了 MyBatis 代理机制。若你还想了解更多关于 MyBatis 的优化技巧、与其他框架整合等内容,欢迎和我说说。

相关文章:

深入理解 MyBatis 代理机制

在 Java 开发领域&#xff0c;MyBatis 是一款优秀的持久层框架&#xff0c;它极大地简化了数据库操作&#xff0c;提高了开发效率。其中&#xff0c;代理机制作为 MyBatis 的核心特性之一&#xff0c;在连接 Java 代码与数据库操作中发挥着关键作用。本文将深入探讨 MyBatis 代…...

游戏引擎学习第254天:重新启用性能分析

运行游戏并尝试让性能分析系统恢复部分功能 我们现在的调试系统这几天基本整理得差不多了&#xff0c;因此我们打算开始清理一些功能&#xff0c;比如目前虽然已经在收集性能分析数据&#xff0c;但我们没有办法查看或有效利用这些信息。今天的计划可能会围绕这方面展开&#…...

性能测试工具篇

文章目录 目录1. JMeter介绍1.1 安装JMeter1.2 打开JMeter1.3 JMeter基础配置1.4 JMeter基本使用流程1.5 JMeter元件作用域和执行顺序 2. 重点组件2.1 线程组2.2 HTTP取样器2.3 查看结果树2.4 HTTP请求默认值2.5 JSON提取器2.6 用户定义的变量2.7 JSON断言2.8 同步定时器&#…...

【Hive入门】Hive性能调优之Join优化:深入解析MapJoin与Sort-Merge Join策略

目录 前言 1 Hive Join操作基础 1.1 Join操作的类型与挑战 1.2 Hive Join执行机制 2 MapJoin优化策略 2.1 MapJoin原理 2.2 MapJoin适用场景 2.3 MapJoin关键参数 3 Sort-Merge Join优化策略 3.1 Sort-Merge Join原理 3.2 Sort-Merge Join优势 3.3 关键配置参数 3…...

【Unity】使用XLua实现C#访问Lua文件

先引入XLua文件中的Plugins和XLua文件夹于Unity项目的Asset文件中 XLua_github链接 建立Lua虚拟机&#xff1a;LuaEnv luaEnv new LuaEnv(); 关闭虚拟机&#xff0c;及时释放资源&#xff1a;luaEnv.Dispose(); Resources文件夹下加载lua文件&#xff08;假设文件路径为Resour…...

AXI中的out of order和interleaving的定义和两者的差别?

AXI中的out of order和interleaving的定义和两者的差别 摘要&#xff1a;在 AXI (Advanced eXtensible Interface) 协议中&#xff0c;Out-of-Order 和 Interleaving 是两个与事务处理顺序和数据传输相关的概念&#xff0c;它们都与 AXI 协议支持的多事务并发处理能力有关&…...

生产级RAG系统一些经验总结

本文将探讨如何使用最新技术构建生产级检索增强生成(RAG)系统&#xff0c;包括健壮的架构、向量数据库(Faiss、Pinecone、Weaviate)、框架(LangChain、LlamaIndex)、混合搜索、重排序器、流式数据接入、评估策略以及实际部署技巧。 引言&#xff1a;检索增强生成的力量 大型语…...

sftp连接报错Received message too long 168449893

sftp连接报错Received message too long 168449893 一、openEuler传文件报错二、分析问题三、解决问题endl 一、openEuler传文件报错 [rootRocky9-12 ~]# scp apache-tomcat-10.1.33.tar.gz root10.0.0.14:Authorized users only. All activities may be monitored and report…...

Java中修饰类的关键字

Java中修饰类的关键字 在web编程课上&#xff0c;老师提问了Java中各种修饰类的关键字的用途和区别&#xff0c;一时间我头脑空白&#xff0c;现在课后重新梳理一遍Java中修饰类的各种关键字的区别和用法。在Java编程中&#xff0c;修饰类的关键字起着至关重要的作用&#xff…...

2025年人工智能火爆技术总结

2025年人工智能火爆技术总结&#xff1a; 生成式人工智能 生成式人工智能可生成高质量的图像、视频、音频和文本等多种内容。如昆仑万维的SkyReels-V2能生成无限时长电影&#xff0c;其基于扩散强迫框架&#xff0c;结合多模态大语言模型和强化学习等技术&#xff0c;在运动动…...

脑机接口技术:开启人类与机器的全新交互时代

在科技飞速发展的今天&#xff0c;人类与机器的交互方式正经历着前所未有的变革。从最初的键盘鼠标&#xff0c;到触摸屏&#xff0c;再到语音控制&#xff0c;每一次交互方式的升级都极大地提升了用户体验和效率。如今&#xff0c;脑机接口&#xff08;Brain-Computer Interfa…...

Arduino程序函数详解与实际案例

一、Arduino程序的核心架构与函数解析 Arduino程序的核心由两个函数构成:setup() 和 loop()。这两个函数是所有Arduino代码的骨架,它们的合理使用决定了程序的结构和功能。 1.1 setup() 函数:初始化阶段 setup() 函数在程序启动时仅执行一次,用于完成初始化配置,例如设置…...

2025年RAG技术发展现状分析

2025年&#xff0c;大模型RAG&#xff08;检索增强生成&#xff09;技术经历了快速迭代与深度应用&#xff0c;逐渐从技术探索走向行业落地&#xff0c;同时也面临安全性和实用性的新挑战。以下是其发展现状的综合分析&#xff1a; 一、技术架构的持续演进 从单一到模块化架构 …...

C++11新特性_范围-based for 循环

based for 循环介绍 范围 - based for 循环&#xff08;Range-based for loop&#xff09;是 C11 引入的一种新的 for 循环语法&#xff0c;它可以更简洁地遍历容器和数组。 遍历数组&#xff1a;定义了一个整数数组 arr&#xff0c;使用范围 - based for 循环 for (int num :…...

小牛电动:荣登央视舞台,引领智能出行新潮流

在这个科技飞速发展的时代&#xff0c;出行方式也在不断地变革与创新。而在两轮电动车领域&#xff0c;有一个品牌凭借其卓越的技术、独特的设计和优质的服务脱颖而出&#xff0c;那就是小牛电动。近日&#xff0c;小牛电动荣登央视舞台&#xff0c;成为备受瞩目的焦点&#xf…...

Three.js在vue中的使用(一)-基础

Three.js 是一个基于 WebGL 的 JavaScript 3D 图形库,它简化了在网页中创建和渲染 3D 场景的复杂性。Three.js 提供了丰富的功能,如光照、材质、几何体、动画、控制器等,使得开发者可以快速构建交互式的 3D 应用。 🧠 Three.js 原理概述 1. WebGL 基础 Three.js 底层使用…...

开发板型号 ESP32-DevKitC-32模块型号 ESP32-WROOM-32 和主控芯片 ESP32-D0WDQ6-V3

以下是关于开发板型号 ESP32-DevKitC-32、模块型号 ESP32-WROOM-32 和主控芯片 ESP32-D0WDQ6-V3 的详细介绍&#xff1a; 开发板型号&#xff1a;ESP32-DevKitC-32 概述&#xff1a;ESP32-DevKitC 是乐鑫推出的一款基于 ESP32 模组的小型开发板&#xff0c;板上模组的绝大部…...

【C语言练习】015. 声明和初始化指针

015. 声明和初始化指针 015. 声明和初始化指针1. 声明指针示例1:声明一个指向整数的指针2. 初始化指针示例2:将指针初始化为`NULL`示例3:将指针初始化为某个变量的地址示例4:将指针初始化为动态分配的内存地址3. 使用指针访问和修改变量的值示例5:使用指针访问和修改变量的…...

手撕哈希表

引入&#xff1a;unordered_set /map是什么&#xff1f; 库里面除开set和map&#xff0c;还有unordered_set 和 unordered_map&#xff0c;区别在于&#xff1a; ①&#xff1a;set和map的底层结构是红黑树&#xff0c;而unordered_set和unordered_map的底层是哈希表 ②&…...

编程题python常用技巧-持续

1.字典 1.1排序 在Python中&#xff0c;要按照字典的值进行排序&#xff0c;可以按照以下步骤操作&#xff1a; 方法说明 ‌获取键值对列表‌&#xff1a;使用 dict.items() 获取字典的键值对视图。‌排序键值对‌&#xff1a;使用 sorted() 函数&#xff0c;并通过 key 参…...

大模型蒸馏技术

提问&#xff1a;请写一篇关于蒸馏大模型的详细解说&#xff08;论文&#xff09;&#xff0c;要求配有图并不少于8000字。 Deepseek&#xff1a; 大模型蒸馏技术&#xff1a;原理、方法与产业实践 ——基于知识压缩与效率优化的深度解析 目录 引言&#xff1a;大模型时代的…...

深入理解C语言中的整形提升与算术转换

深入理解C语言中的整形提升与算术转换 一.整形提升&#xff1a;概念与原理 在C语言中&#xff0c;整形提升&#xff08;Integer Promotion&#xff09;是一个重要但容易被忽视的概念。它指的是在表达式中&#xff0c;任何小于int类型的整型&#xff08;如char、short&#xf…...

企业经营系统分类及功能详解

近年来互联网行业下行&#xff0c;招聘少&#xff0c;要求离谱&#xff0c;年龄学历背景已经卡的死死的&#xff0c;技术再突出也没用。 但对于软件开发来说&#xff0c;互联网只是一小部分&#xff0c;企业级系统软件开发&#xff0c;虽然不如互联网大起大落&#xff0c;但重…...

IRF2.0IRF3.1

1、IRF3定义 IRF3是一种能够提高网络接入层的接入能力和管理效率的纵向网络整合虚拟化技术&#xff0c;采用IEEE 802.1BR标准协议实现。IRF3将多台PEX设备&#xff08;Bridge Port Extender&#xff09;连接到父设备&#xff08;Parent device&#xff09;上&#xff0c;将每台…...

【C++】类和对象【中下】

目录 一、类与对象1、运算符重载1.2 赋值运算符重载1.3 <<运算符和>>运算符1.4 前置与后置 2、 const成员函数3、取地址运算符重载 个人主页<—请点击 C专栏<—请点击 一、类与对象 本期的主题是一步步完善日期类的编写&#xff0c;将要讲解的知识融入在代…...

ThreadLocal详解

什么是 ThreadLocal&#xff1f;​ ThreadLocal 是 Java 中的一个工具类&#xff0c;用于为每个线程提供独立的变量副本&#xff0c;使得每个线程可以独立操作自己的变量&#xff0c;避免多线程环境下的数据竞争问题。它的核心思想是​​线程封闭​​&#xff08;Thread Confi…...

Vue3 + OpenLayers 企业级应用进阶

1. 企业级架构设计 1.1 微前端架构集成 // src/micro-frontend/map-container.ts import { Map } from ol; import { registerMicroApps, start } from qiankun;export class MapMicroFrontend {private map: Map;private apps: any[];constructor(map: Map) {this.map map;…...

如何提升自我执行力?

提升个人执行力是一个系统性工程&#xff0c;需要从目标管理、习惯养成、心理调节等多方面入手。 以下是具体方法&#xff0c;结合心理学和行为科学原理&#xff0c;帮助你有效提升执行力&#xff1a; 一、明确目标&#xff1a;解决「方向模糊」问题 1. 用SMART原则设定目标 …...

L3-041 影响力

下面给出基于“切比雪夫距离”&#xff08;Chebyshev 距离&#xff09;之和的高效 O(nm) 解法。核心思想是把 ∑ u 1 n ∑ v 1 m max ⁡ ( ∣ u − i ∣ , ∣ v − j ∣ ) \sum_{u1}^n\sum_{v1}^m\max\bigl(|u-i|,|v-j|\bigr) u1∑n​v1∑m​max(∣u−i∣,∣v−j∣) 拆成两个…...

【ESP32】st7735s + LVGL使用-------图片显示

【ESP32】st7735s + LVGL使用-------图片显示 1、文件准备2、工程搭建3、代码编写4、应用部分5、函数调用6、显示效果移植部分参考这个博客: 【ESP32】st7735s + LVGL移植 1、文件准备 本次图片放在内部存储,先使用转换工具将要显示的图片转换好。 文件名保存为xx.c,xx这…...

MERGE存储引擎(介绍,操作),FEDERATED存储引擎(介绍,操作),不同存储引擎的特性图

目录 MERGE存储引擎(合并) 介绍 创建表 语法 示例 查看.mrg文件 操作 查询结果 示例 重建逻辑表 FEDERATED存储引擎 结盟 介绍 ​编辑 应用场景 操作 开启 创建表 对本地表进行数据插入 EXAMPLE存储引擎 不同存储引擎的特性​编辑 MERGE存储引擎(合并) 介绍…...

初学者如何学习AI问答应用开发范式

本文是根据本人2年大模型应用开发5年小模型开发经验&#xff0c;对AI问答应用的开发过程进行总结。 技术范式 现在超过80%的AI问答是 提示词 大模型&#xff0c; 然后就是RAG 方案&#xff0c;这两种无疑是主流方案。 1、提示词大模型 适合于本身业务不超过大模型的知识范围…...

GESP2024年6月认证C++八级( 第二部分判断题(1-5))

判断题2&#xff1a; #include <iostream> #include <iomanip> using namespace std;int main() {double a 1e308;double b 1e-10;double orig_a a, orig_b b;a a b;b a - b;a a - b;cout << fixed << setprecision(20);cout << "…...

npm命令介绍(Node Package Manager)(Node包管理器)

文章目录 npm命令全解析简介基础命令安装npm&#xff08;npm -v检插版本&#xff09;初始化项目&#xff08;npm init&#xff09;安装依赖包&#xff08;npm install xxx、npm i xxx&#xff09;卸载依赖包&#xff08;npm uninstall xxx 或 npm uni xxx、npm remove xxx&…...

小刚说C语言刷题—1602总分和平均分

1.题目描述 期末考试成绩出来了&#xff0c;小明同学语文、数学、英语分别考了 x、y、z 分&#xff0c;请编程帮助小明计算一下&#xff0c;他的总分和平均分分别考了多少分&#xff1f; 输入 三个整数 x、y、z 分别代表小明三科考试的成绩。 输出 第 11行有一个整数&…...

python类私有变量

在Python中&#xff0c;要将一个属性定义为类的内部属性&#xff08;也就是私有属性&#xff09;&#xff0c;通常会在属性名称前加一个下划线&#xff08;_&#xff09;或两个下划线&#xff08;__&#xff09;。这两种方式有不同的效果&#xff1a; 单下划线&#xff08;_&a…...

前端如何转后端

前端转后端是完全可行的&#xff0c;特别是你已经掌握了 JavaScript / TypeScript&#xff0c;有一定工程化经验&#xff0c;这对你学习如 Node.js / NestJS 等后端技术非常有利。下面是一条 系统化、实践导向 的路线&#xff0c;帮助你高效完成从前端到后端的转型。 ✅ 一、评…...

数字智慧方案5976丨智慧农业顶层设计建设与运营方案(59页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;智慧农业顶层设计建设与运营方案 在现代农业发展进程中&#xff0c;智慧农业成为推动农业转型升级、提升竞争力的关键力量。这份《智慧农业顶层设计建设与运营方案》全面且深入地探讨了智慧农业的建设现状、需求分析、…...

软件工程国考

软件工程-同等学力计算机综合真题及答案 &#xff08;2004-2014、2017-2024&#xff09; 2004 年软工 第三部分 软件工程 &#xff08;共 30 分&#xff09; 一、单项选择题&#xff08;每小题 1 分&#xff0c;共 5 分&#xff09; 软件可用性是指&#xff08; &#xff09…...

linux python3安装

1 安装依赖环境 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel 2 mkdir -p /usr/python3 3 cd usr/python3; tar -zxvf Python-3.8.3.tgz;cd Python-3.8.3 4 ./confi…...

软件测评中心如何保障软件质量与性能?评测范围和标准有哪些?

软件测评中心对保障软件质量与性能有关键作用&#xff0c;它像软件世界里的质量卫士&#xff0c;会评测各类软件&#xff0c;能为用户选出真正优质好用的软件&#xff0c;我将从多个方面向大家介绍软件测评中心。 评测范围 软件测评中心的评测范围很广&#xff0c;它涵盖了常…...

从MCP基础到FastMCP实战应用

MCP(https://github.com/modelcontextprotocol) MCP&#xff08;模型上下文协议&#xff09; 是一种专为 基于LLM的工具调用外部工具而设计的协议 &#xff0c; 本质上是 LLM ↔ 工具之间的RPC&#xff08;远程过程调用&#xff09; 的一种安全且一致的处理方式&#xff0c; 是…...

【云备份】服务端工具类实现

1.文件实用工具类设计 不管是客户端还是服务端&#xff0c;文件的传输备份都涉及到文件的读写&#xff0c;包括数据管理信息的持久化也是如此&#xff0c;因此首先设 计封装文件操作类&#xff0c;这个类封装完毕之后&#xff0c;则在任意模块中对文件进行操作时都将变的简单化…...

如何在Cursor中使用MCP服务

前言 随着AI编程助手的普及&#xff0c;越来越多开发者选择在Cursor等智能IDE中进行高效开发。Cursor不仅支持代码补全、智能搜索&#xff0c;还能通过MCP&#xff08;Multi-Cloud Platform&#xff09;服务&#xff0c;轻松调用如高德地图API、数据库等多种外部服务&#xff…...

PB的框架advgui反编译后控件无法绘制的处理(即导入pbx的操作步骤)

advguiobjects.pbl反编译后&#xff0c;涉及到里面一个用pbni开发的一个绘制对象需要重新导入才可以。否则是黑色的无法绘制控件&#xff1a; 对象的位置在&#xff1a; 操作&#xff1a; 导入pbx文件中的对象。 恢复正常&#xff1a; 文章来源&#xff1a;PB的框架advgui反编译…...

第 11 届蓝桥杯 C++ 青少组中 / 高级组省赛 2020 年真题,选择题详细解释

一、选择题 第 2 题 在二维数组按行优先存储的情况下&#xff0c;元素 a[i][j] 前的元素个数计算如下&#xff1a; 1. **前面的完整行**&#xff1a;共有 i 行&#xff0c;每行 n 个元素&#xff0c;总计 i * n 个元素。 2. **当前行的前面元素**&#xff1a;在行内&#x…...

Python 装饰器基础知识科普

装饰器定义与基本原理 装饰器本质上是一个可调用的对象&#xff0c;它接收另一个函数&#xff08;即被装饰的函数&#xff09;作为参数。装饰器可以对被装饰的函数进行处理&#xff0c;之后返回该函数&#xff0c;也可以将其替换为另一个函数或可调用对象。 代码示例理解 有…...

数字基带信号和频带信号的区别解析

数字基带信号和数字频带信号是通信系统中两种不同的信号形式&#xff0c;它们的核心区别在于是否经过调制以及适用的传输场景。以下是两者的主要区别和分析&#xff1a; 1. 定义与核心区别 数字基带信号&#xff08;Digital Baseband Signal&#xff09; 未经调制的原始数字信号…...

Nginx Proxy Manager 中文版安装部署

目录 Nginx Proxy Manager 中文版安装部署教程一、项目简介1.1 主要功能特点1.2 项目地址1.3 系统架构与工作原理1.4 适用场景 二、系统要求2.1 硬件要求2.2 软件要求 三、Docker环境部署3.1 CentOS系统安装Docker3.2 Ubuntu系统安装Docker3.3 安装Docker Compose 四、安装Ngin…...

类和对象(拷贝构造和运算符重载)下

类和对象(拷贝构造和运算符重载)下 这一集的主要目标先是接着上一集讲完日期类。然后再讲一些别的运算符的重载&#xff0c;和一些语法点。 这里我把这一集要用的代码先放出来:(大家拷一份代码放在编译器上先) Date.h #include <iostream> #include <cassert> …...