MyBatis 核心知识与实践
一、MyBatis 概述
1. 框架简介
MyBatis 是一款支持自定义 SQL、存储过程以及高级映射的持久层框架。它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作,使开发人员能够更专注于 SQL 语句的编写和业务逻辑的处理。
2. 核心组件
- SqlSessionFactoryBuilder:用于创建 SqlSessionFactory 实例。
- SqlSessionFactory:是 MyBatis 的核心对象,负责创建 SqlSession 实例。
- SqlSession:提供了执行 SQL 语句、管理事务等功能。
3. 工作原理
MyBatis 通过读取配置文件和映射文件,将 SQL 语句与 Java 方法进行映射。在运行时,根据方法调用生成相应的 SQL 语句,并执行数据库操作,最后将结果映射为 Java 对象返回。
二、MyBatis 基础操作
1. 环境搭建
- 引入 MyBatis 依赖(以 Maven 项目为例):
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>x.x.x</version>
</dependency>
- 配置
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><environments default="development"><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></dataSource></environment></environments><mappers><mapper resource="mapper/EmpMapper.xml" /><mapper resource="mapper/DeptMapper.xml" /></mappers>
</configuration>
2. 单表操作
- 实体类定义:
public class Emp {private Integer empid;private String empname;private String empjob;private BigDecimal empsalary;private Integer empdid;// 省略getter和setter方法
}
- Mapper 接口定义:
public interface EmpDao {List<Emp> findAll();Emp findById(Integer id);int insert(Emp emp);int update(Emp emp);int delete(Integer id);
}
- Mapper 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="org.example.Dao.EmpDao"><resultMap id="BaseResultMap" type="Emp"><id property="empid" column="emp_id" jdbcType="INTEGER" /><result property="empname" column="emp_name" jdbcType="VARCHAR" /><result property="empjob" column="emp_job" jdbcType="VARCHAR" /><result property="empsalary" column="emp_salary" jdbcType="DECIMAL" /><result property="empdid" column="did" jdbcType="INTEGER" /></resultMap><select id="findAll" resultMap="BaseResultMap">select * from tbl_emp</select><select id="findById" resultMap="BaseResultMap">select * from tbl_emp where emp_id = #{id}</select><insert id="insert" keyProperty="empid" useGeneratedKeys="true">insert into tbl_emp(emp_name, emp_job, emp_salary, did)values (#{empname}, #{empjob}, #{empsalary}, #{empdid})</insert><update id="update">update tbl_empset emp_name = #{empname}, emp_job = #{empjob}, emp_salary = #{empsalary}, did = #{empdid}where emp_id = #{empid}</update><delete id="delete">delete from tbl_emp where emp_id = #{id}</delete>
</mapper>
3. 测试类编写
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.Entity.Emp;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class EmpDaoTest {@Testpublic void testFindAll() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);List<Emp> emps = empDao.findAll();for (Emp emp : emps) {System.out.println(emp);}sqlSession.close();}@Testpublic void testFindById() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);Emp emp = empDao.findById(1);System.out.println(emp);sqlSession.close();}@Testpublic void testInsert() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);Emp emp = new Emp();emp.setEmpname("张三");emp.setEmpjob("开发工程师");emp.setEmpsalary(new BigDecimal("8000"));emp.setEmpdid(1);int result = empDao.insert(emp);System.out.println("插入成功,影响行数:" + result);sqlSession.commit();sqlSession.close();}@Testpublic void testUpdate() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);Emp emp = new Emp();emp.setEmpid(1);emp.setEmpname("李四");emp.setEmpjob("高级开发工程师");emp.setEmpsalary(new BigDecimal("10000"));emp.setEmpdid(2);int result = empDao.update(emp);System.out.println("更新成功,影响行数:" + result);sqlSession.commit();sqlSession.close();}@Testpublic void testDelete() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);int result = empDao.delete(1);System.out.println("删除成功,影响行数:" + result);sqlSession.commit();sqlSession.close();}
}
三、MyBatis 高级特性
1. 分页查询
- 引入 PageHelper 依赖:
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>6.0.0</version>
</dependency>
- 在 MyBatis 配置文件中添加插件配置:
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><!-- 可配置参数 --><property name="param1" value="value1" /></plugin>
</plugins>
- 代码示例:
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
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.Dao.EmpDao;
import org.example.Entity.Emp;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class PaginationTest {@Testpublic void testPagination() throws IOException {InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();EmpDao empDao = sqlSession.getMapper(EmpDao.class);// 开启分页,查询第一页,每页显示3条数据PageHelper.startPage(1, 3);List<Emp> emps = empDao.findAll();// 将查询结果封装到PageInfo中PageInfo<Emp> pageInfo = new PageInfo<>(emps);// 输出相关信息System.out.println("总条数:" + pageInfo.getTotal());System.out.println("总页数:" + pageInfo.getPages());System.out.println("当前页记录:");List<Emp> list = pageInfo.getList();for (Emp emp : list) {System.out.println(emp);}sqlSession.close();}
}
2. 联表查询
- 多对一关系查询(以员工和部门为例):
- 使用
association
标签:
<?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="org.example.Dao.EmpDao"><resultMap id="EmpWithDeptResultMap" type="Emp"><id property="empid" column="emp_id" jdbcType="INTEGER" /><result property="empname" column="emp_name" jdbcType="VARCHAR" /><result property="empjob" column="emp_job" jdbcType="VARCHAR" /><result property="empsalary" column="emp_salary" jdbcType="DECIMAL" /><result property="empdid" column="did" jdbcType="INTEGER" /><association property="dept" javaType="Dept"><id property="deptid" column="dept_id" jdbcType="INTEGER" /><result property="deptname" column="dept_name" jdbcType="VARCHAR" /><result property="deptloc" column="dept_loc" jdbcType="VARCHAR" /></association></resultMap><select id="findAllWithDept" resultMap="EmpWithDeptResultMap">select e.*, d.dept_id, d.dept_name, d.dept_locfrom tbl_emp ejoin tbl_dept d on e.did = d.dept_id</select>
</mapper>
- 一对多关系查询(以部门和员工为例):
- 使用
collection
标签:
<?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="org.example.Dao.DeptDao"><resultMap id="DeptWithEmpsResultMap" type="Dept"><id property="deptid" column="dept_id" jdbcType="INTEGER" /><result property="deptname" column="dept_name" jdbcType="VARCHAR" /><result property="deptloc" column="dept_loc" jdbcType="VARCHAR" /><collection property="emps" ofType="Emp"><id property="empid" column="emp_id" jdbcType="INTEGER" /><result property="empname" column="emp_name" jdbcType="VARCHAR" /><result property="empjob" column="emp_job" jdbcType="VARCHAR" /><result property="empsalary" column="emp_salary" jdbcType="DECIMAL" /><result property="empdid" column="did" jdbcType="INTEGER" /></collection></resultMap><select id="findAllWithEmps" resultMap="DeptWithEmpsResultMap">select d.*, e.*from tbl_dept dleft join tbl_emp e on d.dept_id = e.did</select>
</mapper>
3. 动态 SQL
<trim>:通过修剪 SQL 语句的开头和结尾来动态生成 SQL 片段。它可以用于去除不必要的 SQL 关键字或条件语句,并提供了一些属性来定义修剪规则。
<where>:用于在生成的 SQL 语句中添加 WHERE 子句。它可以自动处理条件语句的前缀,并在有条件语句存在时添加 WHERE 关键字。而且会去除sql的第一个and标签。
<set>:用于在生成的 SQL 语句中添加 SET 子句。它主要用于更新操作,可以根据条件来动态生成需要更新的列。
<foreach>:用于在生成的 SQL 语句中进行循环操作。它可以遍历集合或数组,并根据指定的模板将集合元素或数组元素插入到 SQL 语句中。
<if>:用于在生成的 SQL 语句中添加条件判断。可以根据指定的条件决定是否包含某个 SQL 语句片段。
<choose>:类似于 Java 中的 switch 语句,根据条件选择执行不同的 SQL 语句片段。它可以包含多个 <when> 和一个可选的 <otherwise> 标签。
<when>:用于在 <choose> 标签中定义条件分支。可以根据指定的条件判断是否执行特定的 SQL 语句片段。
<otherwise>:在 <choose> 标签中可选的标签,用于定义当没有任何 <when> 条件匹配时执行的 SQL 语句片段。
if
标签示例(根据条件查询员工):
<?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="org.example.Dao.EmpDao"><select id="selectByCondition" resultMap="BaseResultMap">select * from tbl_emp<where><if test="name!= null and name!= ''">and emp_name like concat('%', #{name}, '%')</if><if test="job!= null and job!= ''">and emp_job = #{job}</if><if test="salary!= null">and emp_salary = #{salary}</if></where></select>
</mapper>
choose
、when
、otherwise
标签示例(根据条件查询员工):
<?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="org.example.Dao.EmpDao"><select id="selectByCondition2" resultMap="BaseResultMap">select * from tbl_emp<where><choose><when test="name!= null and name!= ''">and emp_name like concat('%', #{name}, '%')</when><when test="job!= null and job!= ''">and emp_job = #{job}</when><when test="salary!= null">and emp_salary = #{salary}</when><otherwise>and 1 = 1</otherwise></choose></where></select>
</mapper>
foreach
标签示例(批量删除员工):
<?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="org.example.Dao.EmpDao"><delete id="batchDelete">delete from tbl_emp where emp_id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></delete>
</mapper>
相关文章:
MyBatis 核心知识与实践
一、MyBatis 概述 1. 框架简介 MyBatis 是一款支持自定义 SQL、存储过程以及高级映射的持久层框架。它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作,使开发人员能够更专注于 SQL 语句的编写和业务逻辑的处理。 2. 核心组件 SqlSessionFactoryB…...

机器学习期末速成
文章目录 一、机器学习分类二、逻辑回归三、决策树四、集成学习算法五、支持向量机六、聚类七、特征工程和指标 文章参考自B站机器学习期末速成课 本文仅作者个人复习使用 一、机器学习分类 聚类和分类的区别: 分类:一开始就知道有哪些类别 聚类&#…...

Linux中的线程
目录 线程的概念 进程与线程的关系 线程创建 线程终止 线程等待 线程分离 原生线程库 线程局部存储 自己实现线程封装 线程的优缺点 多线程共享与独占资源 线程互斥 互斥锁 自己实现锁的封装 加锁实现互斥的原理 死锁 线程同步 线程的概念 回顾进程相关概念 …...

AI大模型学习笔记|多目标算法梳理、举例
多目标算法学习内容推荐: 1.通俗易懂讲算法-多目标优化-NSGA-II(附代码讲解)_哔哩哔哩_bilibili 2.多目标优化 (python pyomo pareto 最优)_哔哩哔哩_bilibili 学习笔记: 通过网盘分享的文件:多目标算法学习笔记 链接: https://pan.baidu.com…...
蓝桥杯刷题——day3
蓝桥杯刷题——day3 题目一题干题目解析代码 题目二题干题目解析代码 题目一 题干 每张票据有唯一的 ID 号,全年所有票据的 ID 号是连续的,但 ID 的开始数码是随机选定的。因为工作人员疏忽,在录入 ID 号的时候发生了一处错误,造…...

企业级日志分析系统ELK之ELK概述
ELK 概述 ELK 介绍 什么是 ELK 早期IT架构中的系统和应用的日志分散在不同的主机和文件,如果应用出现问题,开发和运维人员想排 查原因,就要先找到相应的主机上的日志文件再进行查找和分析,所以非常不方便,而且还涉及…...

【开源项目】经典开源项目数字孪生体育馆—开源工程及源码
飞渡科技数字孪生体育馆管理平台,融合物联网IOT、BIM数据模型、三维GIS等技术,实现体育馆的全方位监控和实时全局掌握,同时,通过集成设备设施管理、人员管理等子系统,减少信息孤岛,让场馆“可视、可控、可管…...

C++多线程实战:掌握图像处理高级技巧
文章结尾有最新热度的文章,感兴趣的可以去看看。 本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身 导读 在当今的计算世界中,…...

解决MAC装win系统投屏失败问题(AMD显卡)
一、问题描述 电脑接上HDMI线后,电脑上能显示有外部显示器接入,但是外接显示器无投屏画面 二、已测试的方法 1 更改电脑分辨,结果无效 2 删除BootCamp,结果无效 3更新电脑系统,结果无效 4 在设备管理器中&#…...
网易游戏分享游戏场景中MongoDB运行和分析实践
在游戏行业中,数据库的稳定和性能直接影响了游戏质量和用户满意度。在竞争激烈的游戏市场中,一个优秀的数据库产品无疑能为游戏的开发和后期的运营奠定良好的基础。伴随着MongoDB在不同类型游戏场景中的应用越来越广泛,许多知名的游戏公司都在…...
Android14 AOSP 允许system分区和vendor分区应用进行AIDL通信
在Android14上,出于种种原因,system分区的应用无法和vendor分区的应用直接通过AIDL的方法进行通信,但是项目的某个功能又需要如此。 好在Binder底层其实是支持的,只是在上层进行了屏蔽。 修改 frameworks/native/libs/binder/Bp…...

R学习——因子
目录 1 定义因子(factor函数) 2因子的作用 一个数据集中的 只需要考虑可以用哪个数据来进行分类就可以了,可以用来分类就可以作为因子。 Cy1这个因子对应的水平level是4 6 8: 1 定义因子(factor函数) 要…...

pytest入门三:setup、teardown
https://zhuanlan.zhihu.com/p/623447031 function对应类外的函数,每个函数调用一次 import pytest def setup_module():print(开始 module)def teardown_module():print(结束 module)def setup_function():print(开始 function)def teardown_function():print(结…...
前端面试准备问题2
1.防抖和节流分别是什么,应用场景 防抖:在事件被触发后,只有在指定的延迟时间内没有再次触发,才执行事件处理函数。 在我的理解中,简单的说就是在一个指定的时间内,仅触发一次,如果有多次重复触…...
web前端sse封装
这是一个基于microsoft/fetch-event-source包封装的sse函数,包含开始、停止功能; 可传更多参数、使用非常简单。 使用前: 安装 microsoft/fetch-event-source 代码: // sse import { fetchEventSource } from microsoft/fetch-event-source import { …...

智能家居WTR096-16S录放音芯片方案,实现语音播报提示及录音留言功能
前言: 在当今社会的高速运转之下,夜幕低垂之时,许多辛勤工作的父母尚未归家。对于肩负家庭责任的他们而言,确保孩童按时用餐与居家安全成为心头大事。此时,家居留言录音提示功能应运而生,恰似家中的一位无形…...
【创建模式-蓝本模式(Prototype Pattern)】
目录 Overview应用场景代码演示JDK Prototype pattern 更优实践泛型克隆接口 https://doc.hutool.cn/pages/Cloneable/#%E6%B3%9B%E5%9E%8B%E5%85%8B%E9%9A%86%E7%B1%BB The prototype pattern is a creational design pattern in software development. It is used when the t…...
Spring Boot应用开发深度解析与实战案例
Spring Boot应用开发深度解析与实战案例 在当今快速发展的软件开发领域,Spring Boot凭借其“约定优于配置”的理念,极大地简化了Java应用的开发、配置和部署过程,成为了微服务架构下不可或缺的技术选型。本文将深入探讨Spring Boot的核心特性、最佳实践,并通过一个具体的…...

优化Go语言中的网络连接:设置代理超时参数
网络连接优化的重要性 在分布式系统和微服务架构中,网络请求的效率直接影响到整个系统的响应速度。合理的超时设置可以防止系统在等待网络响应时陷入无限期的阻塞,从而提高系统的吞吐量和用户体验。特别是在使用代理服务器时,由于增加了网络…...
《神经网络与深度学习》(邱锡鹏) 内容概要【不含数学推导】
第1章 绪论 基本概念:介绍了人工智能的发展历程及不同阶段的特点,如符号主义、连接主义、行为主义等。还阐述了深度学习在人工智能领域的重要地位和发展现状,以及其在图像、语音、自然语言处理等多个领域的成功应用。术语解释 人工智能&…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...

若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
JS设计模式(5): 发布订阅模式
解锁JavaScript发布订阅模式:让代码沟通更优雅 在JavaScript的世界里,我们常常会遇到这样的场景:多个模块之间需要相互通信,但是又不想让它们产生过于紧密的耦合。这时候,发布订阅模式就像一位优雅的信使,…...

信息收集:从图像元数据(隐藏信息收集)到用户身份的揭秘 --- 7000
目录 🌐 访问Web服务 💻 分析源代码 ⬇️ 下载图片并保留元数据 🔍 提取元数据(重点) 👤 生成用户名列表 🛠️ 技术原理 图片元数据(EXIF 数据) Username-Anarch…...