深入掌握MyBatis:核心解析

一、MyBatis核心架构解析

1. 什么是MyBatis?

MyBatis是一款半自动ORM框架,它通过XML或注解将SQL与Java对象映射,提供比Hibernate更灵活的SQL控制能力,同时消除了传统JDBC的样板代码。

2. 核心组件关系图

3. 核心组件职责

组件职责生命周期
SqlSessionFactory创建SqlSession应用级单例
SqlSession执行SQL操作请求/方法级
Mapper接口定义数据库操作应用级
SQL映射文件配置SQL语句应用级

二、环境搭建与配置

1. Maven依赖

<dependencies><!-- MyBatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- 连接池 --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>5.0.1</version></dependency>
</dependencies>

2. 核心配置文件(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><!-- 开启驼峰命名转换 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 开启二级缓存 --><setting name="cacheEnabled" value="true"/></settings><typeAliases><package name="com.example.model"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false"/><property name="username" value="root"/><property name="password" value="password"/><!-- HikariCP连接池配置 --><property name="maximumPoolSize" value="20"/><property name="connectionTimeout" value="30000"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>

三、CRUD操作详解

1. 实体类定义

public class User {private Long id;private String username;private String email;private LocalDateTime createTime;// 构造器、getter/setter省略
}

2. Mapper接口

public interface UserMapper {// 插入操作返回自增主键@Options(useGeneratedKeys = true, keyProperty = "id")int insertUser(User user);int updateUser(User user);int deleteUser(Long id);User selectUserById(Long id);List<User> selectAllUsers();
}

3. XML映射文件(UserMapper.xml)

<mapper namespace="com.example.mapper.UserMapper"><!-- 基础结果映射 --><resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><result property="email" column="email"/><result property="createTime" column="create_time"/></resultMap><!-- 插入用户 --><insert id="insertUser" parameterType="User">INSERT INTO users(username, email, create_time)VALUES(#{username}, #{email}, #{createTime})</insert><!-- 更新用户 --><update id="updateUser" parameterType="User">UPDATE users SETusername = #{username},email = #{email}WHERE id = #{id}</update><!-- 查询用户 --><select id="selectUserById" resultMap="userResultMap">SELECT * FROM users WHERE id = #{id}</select><!-- 分页查询 --><select id="selectAllUsers" resultMap="userResultMap">SELECT * FROM users LIMIT #{offset}, #{pageSize}</select>
</mapper>

四、参数处理与动态SQL

<select id="selectUsersByCondition" resultMap="userResultMap">SELECT * FROM usersWHERE 1=1<if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if><if test="email != null">AND email = #{email}</if><if test="startTime != null">AND create_time >= #{startTime}</if>
</select>

1. 多参数处理

// Mapper接口方法
List<User> selectUsersByCondition(@Param("username") String username,@Param("email") String email,@Param("startTime") LocalDateTime startTime);
<select id="selectUsersByCondition" resultMap="userResultMap">SELECT * FROM usersWHERE 1=1<if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if><if test="email != null">AND email = #{email}</if><if test="startTime != null">AND create_time >= #{startTime}</if>
</select>

2. 复杂动态SQL

<!-- 批量插入 -->
<insert id="batchInsertUsers" parameterType="list">INSERT INTO users(username, email) VALUES<foreach item="user" collection="list" separator=",">(#{user.username}, #{user.email})</foreach>
</insert><!-- 动态更新 -->
<update id="updateUserSelective" parameterType="User">UPDATE users<set><if test="username != null">username=#{username},</if><if test="email != null">email=#{email},</if></set>WHERE id=#{id}
</update><!-- 多条件选择 -->
<select id="findActiveUsers" resultMap="userResultMap">SELECT * FROM users<where><choose><when test="status == 'active'">AND status = 1</when><when test="status == 'inactive'">AND status = 0</when><otherwise>AND status IS NOT NULL</otherwise></choose></where>
</select>

五、高级结果映射

1. 一对一关联

public class Order {private Long id;private String orderNo;private User user; // 一对一关联
}
<resultMap id="orderResultMap" type="Order"><id property="id" column="id"/><result property="orderNo" column="order_no"/><!-- 一对一关联映射 --><association property="user" javaType="User"><id property="id" column="user_id"/><result property="username" column="username"/><result property="email" column="email"/></association>
</resultMap><select id="selectOrderWithUser" resultMap="orderResultMap">SELECT o.*, u.username, u.emailFROM orders oJOIN users u ON o.user_id = u.idWHERE o.id = #{id}
</select>

2. 一对多关联

public class Department {private Long id;private String name;private List<Employee> employees; // 一对多关联
}
<resultMap id="deptResultMap" type="Department"><id property="id" column="id"/><result property="name" column="name"/><!-- 一对多集合映射 --><collection property="employees" ofType="Employee"><id property="id" column="emp_id"/><result property="name" column="emp_name"/><result property="position" column="position"/></collection>
</resultMap><select id="selectDepartmentWithEmployees" resultMap="deptResultMap">SELECT d.*, e.id AS emp_id, e.name AS emp_name, e.positionFROM departments dLEFT JOIN employees e ON d.id = e.dept_idWHERE d.id = #{id}
</select>

六、缓存机制深度优化

1. 缓存层次结构

2. 缓存配置策略

<!-- 在Mapper.xml中配置二级缓存 -->
<cacheeviction="FIFO"  <!-- 回收策略:FIFO/LRU/SOFT/WEAK -->flushInterval="60000" <!-- 刷新间隔(毫秒) -->size="512"       <!-- 缓存对象数量 -->readOnly="true"/> <!-- 是否只读 --><!-- 使用自定义缓存实现 -->
<cache type="com.example.cache.RedisCache"/>

3. 缓存使用注意事项

// 手动清除缓存
sqlSession.clearCache(); // 清除一级缓存// 在Statement中控制缓存
<select id="selectUsers" useCache="false" flushCache="true">SELECT * FROM users
</select>

七、Spring Boot整合实践

1. 快速整合配置

# application.yml
mybatis:mapper-locations: classpath:mapper/**/*.xmltype-aliases-package: com.example.modelconfiguration:map-underscore-to-camel-case: truecache-enabled: truelazy-loading-enabled: true

2. 自动注入Mapper

@Mapper
public interface UserMapper {// 方法定义
}// 在Service中使用
@Service
public class UserService {private final UserMapper userMapper;public UserService(UserMapper userMapper) {this.userMapper = userMapper;}public User getUserById(Long id) {return userMapper.selectUserById(id);}
}

3. 分页插件集成

// 配置分页插件
@Configuration
public class MyBatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}
}// 使用分页
public Page<User> getUsersByPage(int pageNum, int pageSize) {Page<User> page = new Page<>(pageNum, pageSize);return userMapper.selectPage(page, null);
}

八、性能优化与最佳实践

1. SQL优化技巧

/* 避免SELECT * */
SELECT id, username, email FROM users/* 使用覆盖索引 */
CREATE INDEX idx_username ON users(username);/* 批量操作替代循环 */
<foreach item="item" collection="list" separator=",">(#{item.value})
</foreach>

2. 事务管理

@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {// 减少转出账户余额userMapper.deductBalance(fromId, amount);// 增加转入账户余额userMapper.addBalance(toId, amount);// 记录交易日志logMapper.insertTransferLog(fromId, toId, amount);
}

3. 监控与诊断

# 开启SQL日志
logging:level:com.example.mapper: debug
-- 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM users WHERE username = 'john';

九、高级特性应用

1. 存储过程调用

<select id="callUserProcedure" statementType="CALLABLE">{call get_user_by_id(#{id, mode=IN}, #{username, mode=OUT, jdbcType=VARCHAR})}
</select>

2. 类型处理器

// 自定义枚举处理器
public class StatusTypeHandler extends BaseTypeHandler<Status> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) {ps.setInt(i, parameter.getCode());}// 其他方法实现...
}// 注册处理器
<typeHandlers><typeHandler handler="com.example.handler.StatusTypeHandler"/>
</typeHandlers>

3. 插件开发(拦截器)

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class SqlCostInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {long start = System.currentTimeMillis();Object result = invocation.proceed();long end = System.currentTimeMillis();System.out.println("SQL执行耗时: " + (end - start) + "ms");return result;}
}// 注册插件
<plugins><plugin interceptor="com.example.plugin.SqlCostInterceptor"/>
</plugins>

十、实战案例:电商订单系统

1. 复杂查询示例

<select id="selectOrderDetails" resultMap="orderDetailMap">SELECT o.id, o.order_no, o.total_amount,u.id AS user_id, u.username, u.email,p.id AS product_id, p.name AS product_name, p.price,oi.quantityFROM orders oJOIN users u ON o.user_id = u.idJOIN order_items oi ON o.id = oi.order_idJOIN products p ON oi.product_id = p.idWHERE o.status = 'COMPLETED'<if test="startDate != null">AND o.create_time >= #{startDate}</if><if test="minAmount != null">AND o.total_amount >= #{minAmount}</if>ORDER BY o.create_time DESC
</select>

2. 事务边界设计

@Service
public class OrderService {private final OrderMapper orderMapper;private final InventoryService inventoryService;private final PaymentService paymentService;@Transactional(rollbackFor = Exception.class)public void placeOrder(Order order) {// 1. 创建订单orderMapper.insertOrder(order);// 2. 扣减库存inventoryService.deductStock(order.getItems());// 3. 支付处理paymentService.processPayment(order);// 4. 更新订单状态orderMapper.updateOrderStatus(order.getId(), "PAID");}
}
  

结语:MyBatis在企业级应用中的定位

MyBatis作为持久层框架的选择标准:

  1. 适用场景

    • 需要精细控制SQL的场景

    • 复杂报表查询

    • 遗留数据库系统改造

  2. 性能考量

    • 与Hibernate相比,在复杂查询上通常有更好表现

    • 对数据库特性利用更充分

  3. 学习建议

    • 掌握动态SQL编写技巧

    • 深入理解结果集映射机制

    • 合理应用缓存策略

    • 结合Spring事务管理

"不要试图用ORM解决所有问题,MyBatis的价值在于平衡SQL控制力和开发效率"
—— MyBatis创始人 Clinton Begin

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通达信 超级趋势强悍 幅图指标公式

指标用法说明 核心逻辑 该指标通过结合价格趋势、波动率和支撑阻力分析来识别潜在的买入机会和趋势转折点。 主要组成部分 趋势判断: 使用19日和7日EMA的交叉判断趋势方向 股道_Q_3:19日EMA上穿7日EMA(看涨信号) 股道_Q_4:7日EMA上穿19日EMA(看跌信号) 支撑阻力线: …

knowledge-vue2项目(Electron)打包为PC桌面应用程序

1.使用nvm管理node版本 不同的项目开发需要的node版本环境不一样,所以需要使用nvm进行版本管理。 关键命令: &#xff08;1&#xff09;检查nvm版本号是否安装成功 nvm -v &#xff08;2&#xff09;检查所有node版本号 nvm ls &#xff08;3&#xff09;安装指定node版…

k8s集群1.18.20更换节点ip地址段需求操作

前期已经部署好一套k8s集群1.18.20版本&#xff0c;1个master&#xff0c;2个node节点&#xff0c;使用节点地址段为192.168.66.0/24&#xff0c;现在因测试任务需要临时调整到192.168.40.0/24&#xff0c;以下记录一下相关操作步骤&#xff0c;请供参考学习。 一、环境准备 …

1-BaoStock股票数据下载

一、程序功能 程序基于 baostock 接口实现 A 股股票数据的获取与存储&#xff0c;主要功能包括股票列表更新、数据下载与处理。程序通过三个核心函数协同工作&#xff1a; update_stk_list(dateNone)&#xff1a;获取指定日期的 A 股股票列表&#xff0c;默认使用当日。自动处…

【C/C++】无锁队列实现与内存回收机制:Hazard Pointer 深度解析

无锁队列实现与内存回收机制&#xff1a;Hazard Pointer 深度解析 在并发系统中&#xff0c;为了提升性能和避免锁竞争&#xff0c;我们常常追求 lock-free 数据结构。但当你实现完一个无锁队列后&#xff0c;会发现一个严重问题&#xff1a; 内存什么时候释放&#xff1f;怎样…

Scrapy进阶封装(第三阶段:多管道封装,多文件存储)

1.yield返回数据的原理? 为什么要用yield返回数据给管道&#xff1f; 遍历这个函数的返回值的时候&#xff0c;挨个把数据读到内存&#xff0c;不会造成内存的瞬间占用过高&#xff0c;Python3中的range和python2中的xrange同理。scrapy是异步爬取&#xff0c;所以通过yield…

证照大师 MAX 4.0安装与基础功能体验(附流程演示)

软件介绍 证照大师 MAX 4.0是一款功能强大的证件照制作软件&#xff0c;专为满足用户不同场景下的证件照需求而设计。它整合了专业的照片处理技术和智能化的操作系统&#xff0c;提供了自动抠图、尺寸调整、美颜处理、批量处理以及格式转换等多种功能。该软件用户界面简洁明快…

RK3568-适配mipi屏幕触摸和显示

1.1 适配mipi屏幕触摸 gt9xx_lvds: gt9xx-lvds5d {compatible "goodix,gt9xx";reg <0x5d>;pinctrl-names "default";pinctrl-0 <&touch_gpio>;touch-gpio <&gpio1 RK_PA4 IRQ_TYPE_LEVEL_LOW>;reset-gpio <&gpio1…

ICME 2025音频编码器能力挑战赛Workshop即将举办!

IEEE International Conference on Multimedia and Expo 2025&#xff08;ICME 2025&#xff09; 将于 6月30日至7月4日在法国南特举行。作为全球多媒体领域的顶级会议之一&#xff0c;ICME 2025 汇聚全球顶尖学者与产业专家&#xff0c;聚焦人工智能驱动的多媒体技术&#xff…

物奇微WQ5007A上手指南

一、获取SDK 需要与物奇微电子股份有限公司签订NDA协议才会提供SDK。 二、搭建开发环境 SDK里包含了编译工具、开发文档、源码。在windows系统下搭建开发环境&#xff1a; 1、安装交叉编译工具 将\wuqi_sdk\tools\riscv64-unknown-elf-gcc-10.2.0-windows.zip文件解压到任…

[论文阅读] 人工智能 + 软件工程 | LLM在单元测试中的应用:系统性综述与未来展望

LLM在单元测试中的应用&#xff1a;系统性综述与未来展望 论文信息 arXiv:2506.15227 Large Language Models for Unit Testing: A Systematic Literature Review Quanjun Zhang, Chunrong Fang, Siqi Gu, Ye Shang, Zhenyu Chen, Liang Xiao Subjects: Software Engineering …

数据重叠对CLIP零样本能力影响CLIP论文图17笔记

这两张图表&#xff08;图17左、右图&#xff09;是CLIP论文中验证“数据重叠是否影响CLIP零样本能力”的关键证据&#xff0c;核心是通过**“数据重叠分析”排除CLIP“作弊”嫌疑**&#xff08;即CLIP的高零样本准确率是否因为“见过测试集图像”&#xff09;。下面用“先看懂…

996引擎-假人系统

996引擎-假人系统 lua 假人问题添加假人名字列表打开M2设置假人参考资料 lua 假人问题 添加假人名字列表 假人名字列表 Mir200\Envir\DummyNameList.txt 打开M2设置假人 【选项】>【假人设置】 参考资料 假人系统

Rk3568驱动开发_Key驱动_13

设备树配置 key{compatible "alientek,key";pinctrl-0 <&key_gpio>;pinctrl-names "alientek,key";key-gpio <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;status "okay";};配置信息方便后面直接引用&#xff1a; // Narnat 2025…

参展回顾 | AI应用创新场景:数据分析助手ChatBI、璞公英教学平台亮相2025四川国际职教大会暨产教融合博览会

2025年6月11日-13日&#xff0c;以“数字赋能产教融合&#xff0c;创新驱动技能未来”为主题的2025四川国际职业教育大会暨产教融合博览会在成都盛大开幕。璞华联合百度共同参展&#xff0c;并携旗下创新产品ChatBI数据分析助手、璞公英教学平台重磅亮相&#xff0c;凭借前沿的…

动态规划之01背包问题

动态规划算法 动态规划算法介绍 动态规划(Dynamic Programming)算法的核心思想是&#xff1a;将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法动态规划算法与分治法类似&#xff0c;其基本思想也是将待解决问题分解成若干个子问题&#xff0c;先求解…

人大金仓新建用户,并且赋值查询权限

-- 1. 创建用户 visitor&#xff0c;并且设置密码 CREATE USER visitor WITH PASSWORD 1234qwer; -- 2. 授予该用户连接到数据库 "yonbip_db" 的权限 GRANT CONNECT ON DATABASE yonbip_db TO visitor; -- 3. 假设你要让 visitor 查询的模式是 public&#xff08;或…

学习笔记丨信号处理新趋势:量子计算将如何颠覆传统DSP?

在算力需求爆炸式增长的今天&#xff0c;传统数字信号处理&#xff08;DSP&#xff09;芯片正面临物理极限的严峻挑战。当经典计算机架构在摩尔定律的黄昏中挣扎时&#xff0c;量子计算正以颠覆性姿态崛起&#xff0c;准备重新定义信号处理的未来图景。 目录 传统DSP的瓶颈&am…

react day.js使用及经典场景

简介 Day.js 是一个轻量级的 JavaScript 日期库&#xff0c;它提供了简单易用的 API 来处理日期和时间。以及更加轻量级&#xff0c;并且具有更快的性能。 安装 npm install dayjs 使用 import dayjs from "dayjs";dayjs().format("YYYY-MM-DD HH:mm:ss&qu…

【机器学习深度学习】线性回归

目录 一、定义 二、举例说明 三、 数学形式 四、 训练过程&#xff08;机器怎么学会这条线&#xff1f;&#xff09; 五、在 PyTorch 中怎么实现线性回归&#xff1f; 六、如果你学懂了线性回归&#xff0c;你也能理解这些 七、综合应用&#xff1a;线性回归示例 7.1 执…