【精选】框架初探篇之——MyBatis的CRUD及配置文件
MyBatis增删改查

MyBatis新增

新增用户
-
持久层接口添加方法
void add(User user); -
映射文件添加标签
<insert id="add" parameterType="com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) </insert> -
编写测试方法
@Test public void testAdd() throws Exception {InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession session = factory.openSession();UserMapper userMapper = session.getMapper(UserMapper.class);User user = new User("程序员", "男", "上海");userMapper.add(user);// 提交事务session.commit();session.close();is.close(); }
注意:
- 当接口方法的参数类型为POJO类型时,SQL语句中绑定参数时使用
# {POJO的属性名}即可。- MyBatis事务默认手动提交,所以在执行完增删改方法后,需要手动调用SqlSession对象的事务提交方法,否则数据库将不发生改变。
MyBatis修改
优化测试类
我们发现MyBatis的测试方法在操作数据库前都需要获取代理对象,操作数据库后都需要释放资源,可以利用Junit的前置后置方法,优化测试类代码。
InputStream is = null;
SqlSession session = null;
UserMapper userMapper = null;@Before
public void before() throws IOException {// (1)读取核心配置文件is = Resources.getResourceAsStream("SqlMapConfig.xml");// (2)创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();// (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象SqlSessionFactory factory = builder.build(is);// (4)SqlSessionFactory对象获取SqlSession对象session = factory.openSession();// (5)获取代理对象userMapper = session.getMapper(UserMapper.class);
}@After
public void after() throws IOException {// 释放资源session.close();is.close();
}
这样Junit就会自动执行获取代理对象和释放资源的方法。
修改用户
-
持久层接口添加方法
void update(User user); -
映射文件添加标签
<update id="update" parameterType="com.mybatis.pojo.User">update userset username = #{username},sex = #{sex},address=#{address}where id = #{id} </update> -
编写测试方法
@Test public void testUpdate(){User user = new User(8,"程序员1","女","深圳");userMapper.update(user);session.commit(); }
MyBatis删除、根据Id查询
删除用户
-
持久层接口添加方法
void delete(int userId); -
映射文件添加标签
<delete id="delete" parameterType="int">delete from user where id = #{id} </delete>注:当方法的参数类型是简单数据类型时,#{}中可以写任意名称
- 简单数据类型:基本数据类型、字符串等
-
编写测试方法
@Test public void testDelete(){userMapper.delete(8);session.commit(); }
根据ID查询用户
-
持久层接口添加方法
User findById(int userId); -
映射文件添加标签
<select id="findById" parameterType="int" resultType="com.mybatis.pojo.User">select * from user where id = #{userId} </select> -
编写测试方法
@Test public void testFindById(){User user = userMapper.findById(1);System.out.println(user); }
MyBatis模糊查询
使用#定义参数
-
持久层接口添加方法
List<User> findByNameLike(String username); -
映射文件添加标签
<select id="findByNameLike" parameterType="string" resultType="com.mybatis.user.User">select * from user where username like #{name} </select> -
编写测试方法
@Test public void testFindByNameLike(){List<User> users = userMapper.findByNameLike("%王%");for (User user:users){System.out.println(user);} }
我们看到在映射文件中,parameterType的值为
string而没有写java.lang.String,这是为什么呢?
- 参数/返回值类型为基本数据类型/包装类/String等类型时,我们可以写全类名,也可以写别名。
| 数据类型 | 别名 |
|---|---|
| byte | _byte |
| long | _long |
| short | _short |
| int | _int |
| int | _integer |
| double | _double |
| float | _float |
| boolean | _boolean |
| String | string |
| Byte | byte |
| Long | long |
| Short | short |
| Integer | int/integer |
| Double | double |
| Float | float |
| Boolean | boolean |
| Date | date |
| BigDecimal | decimal/bigdecimal |
| Object | object |
| Map | map |
| HashMap | hashmap |
| List | list |
| ArrayList | arraylist |
| Collection | collection |
| Iterator | iterator |
使用$定义参数
模糊查询如果不想在调用方法时参数加%,可以使用拼接参数的方式设置Sql:
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User">select * from user where username like '%${value}%'
</select>
测试方法写法如下:
@Test
public void testFindByNameLike(){List<User> users = userMapper.findByUsernameLike("张三");users.forEach(System.out::println);
}
#和$的区别:
- #表示sql模板的占位符,$表示将字符串拼接到sql模板中。
- #可以防止sql注入,一般能用#就不用$。
- ${}内部的参数名必须写value。
使用< bind>定义参数
如果使用#还不想在调用方法的参数中添加%,可以使用<bind>标签,<bind>标签允许我们在 Sql语句以外创建一个变量,并可以将其绑定到当前的Sql语句中。用法如下:
<select id="findByUsernameLike" parameterType="string" resultType="com.mybatis.pojo.User"><bind name="likeName" value="'%'+username+'%'"/>select * from user where username like #{likeName}
</select>
测试方法写法如下:
@Test
public void testFindByNameLike(){List<User> users = userMapper.findByUsernameLike("张三");users.forEach(System.out::println);
}
MyBatis分页查询
分页查询时,Sql语句使用limit关键字,需要传入开始索引和每页条数两个参数。MyBatis的多参数处理有以下方式:
顺序传参
Sql中的参数使用arg0,arg1…或param1,param2…表示参数的顺序。此方法可读性较低,在开发中不建议使用。
-
持久层接口方法
/*** 分页查询* @param startIndex 开始索引* @param pageSize 每页条数* @return*/ List<User> findPage(int startIndex,int pageSize); -
映射文件
<select id="findPage" resultType="com.mybatis.mapper.User">select * from user limit #{arg0},#{arg1} </select><select id="findPage" resultType="com.mybatis.mapper.User">select * from user limit #{param1},#{param2} </select> -
测试类
@Test public void testFindPage(){List<User> users = userMapper.findPage(0,3);users.forEach(System.out::println); }
@Param传参
在接口方法的参数列表中通过@Param定义参数名称,在Sql语句中通过注解中所定义的参数名称指定参数位置。此方式参数比较直观的,推荐使用。
-
持久层接口方法
List<User> findPage1(@Param("startIndex") int startIndex, @Param("pageSize")int pageSize); -
映射文件
<select id="findPage1" resultType="com.mybatis.mapper.User">select * from user limit #{startIndex},#{pageSize} </select> -
测试类
@Test public void testFindPage1(){List<User> users = userMapper.findPage1(3,3);users.forEach(System.out::println); }
POJO传参
自定义POJO类,该类的属性就是要传递的参数,在SQL语句中绑定参数时使用POJO的属性名作为参数名即可。此方式推荐使用。
-
自定义POJO
public class PageQuery {private int startIndex;private int pageSize;// 省略getter/setter/构造方法 } -
持久层接口方法
List<User> findPage2(PageQuery pageQuery); -
映射文件
<select id="findPage2" resultType="com.mybatis.pojo.User" parameterType="com.mybatis.pojo.PageQuery">select * from user limit #{startIndex},#{pageSize} </select> -
测试类
@Test public void testFindPage2(){PageQuery pageQuery = new PageQuery(3, 3);List<User> users = userMapper.findPage2(pageQuery);users.forEach(System.out::println); }
Map传参
如果不想自定义POJO,可以使用Map作为传递参数的载体,在SQL语句中绑定参数时使用Map的Key作为参数名即可。此方法推荐使用。
-
持久层接口方法
List<User> findPage3(Map<String,Object> params); -
映射文件
<select id="findPage3" resultType="com.mybatis.pojo.User" parameterType="map">select * from user limit #{startIndex},#{pageSize} </select> -
测试类
@Test public void testFindPage3(){Map<String,Object> params = new HashMap();params.put("startIndex",0);params.put("pageSize",4);List<User> users = userMapper.findPage3(params);users.forEach(System.out::println); }
MyBatis聚合查询、主键回填
查询用户总数
-
持久层接口方法
int findCount(); -
映射文件
<select id="findCount" resultType="int">select count(id) from user </select> -
测试类
@Test public void testFindCount(){System.out.println(userMapper.findCount()); }
主键回填
有时我们需要获取新插入数据的主键值。如果数据库中主键是自增的,这时我们就需要使用MyBatis的主键回填功能。
-
持久层接口方法
void add(User user); -
映射文件
<insert id="add" parameterType="com.mybatis.user.User"><!-- keyProperty:主键属性名,keyColumn:主键列名,resultType:主键类型,order:执行时机 --><selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">SELECT LAST_INSERT_ID();</selectKey>insert into user(username,sex,address) values(#{username},#{sex},#{address}) </insert>SELECT LAST_INSERT_ID():查询刚刚插入的记录的主键值,只适用于自增主键,且必须和insert语句一起执行。
-
测试类
@Test public void testAdd(){User user = new User("×××", "男", "北京");userMapper.add(user);session.commit();System.out.println(user.getId()); }
MyBatis配置文件

< properties>标签
MyBatis配置文件结构:
-configuration-properties(属性)-property-settings(全局配置参数)-setting-plugins(插件)-plugin-typeAliases(别名)-typeAliase-package-environments(环境)-environment-transactionManager(事务管理)-dataSource(数据源)-mappers(映射器)-mapper-package
properties
属性值定义。properties标签中可以定义属性值,也可以引入外部配置文件。无论是内部定义还是外部引入,都可以使用 ${name} 获取值。
例如:我们可以将数据源配置写到外部的db.properties中,再使用properties标签引入外部配置文件,这样可以做到动态配置数据源。
-
编写db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=root -
在配置文件中引入db.properties
<properties resource="db.properties"></properties><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><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>
当然我们也可以将数据源数据通过<properties>配置到MyBatis配置文件内,但这样做没什么意义。
<properties><property name="jdbc.driver" value="com.mysql.jdbc.Driver"></property><property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis"></property><property name="jdbc.username" value="root"></property><property name="jdbc.password" value="root"></property>
</properties><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><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>
< settings>标签
<settings>是配置MyBatis运行时的一些行为的,例如缓存、延迟加载、命名规则等一系列控制性参数。后期我们会使用该标签配置缓存和延迟加载等。
< plugins>标签
<plugins>是配置MyBatis插件的。插件可以增强MyBatis功能,比如进行sql增强,打印日志,异常处理等。后期我们会使用该标签配置分页插件。
< typeAliases>标签
MyBatis对常用类有默认别名支持,比如java.lang.Stirng的别名为string。除此之外,我们也可以使用<typeAliases>设置自定义别名。
为一个类配置别名
<typeAliases><typeAlias type="全类名" alias="别名"></typeAlias>
</typeAliases>
此时我们即可在映射文件中使用自定义别名,如:
-
配置文件:
<typeAliases><typeAlias type="com.mybatis.pojo.User" alias="User"> </typeAlias> </typeAliases> -
映射文件:
<select id="findAll" resultType="User">select * from user </select>
为一个所有包下的所有类配置别名
<typeAliases><package name="包名"></package>
</typeAliases>
此时该包下的所有类都有了别名,别名省略包名,和类名相同。如:
-
配置文件:
<typeAliases><package name="com.mybatis.pojo"></package> </typeAliases> -
映射文件:
<select id="findPage2" resultType="User" parameterType="PageQuery">select * from user limit #{startIndex},#{pageSize} </select>
< environments>标签
<environments>可以为MyBatis配置数据环境。
事务管理
<environments default="mysql"><environment id="mysql"><!-- JDBC:使用JDBC的提交和回滚 MANAGED:不做事务处理--><transactionManager type="JDBC"></transactionManager></environment>
</environments>
连接池
<environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><!-- 连接池设置 --><dataSource type="POOLED"><!-- 数据源设置... --></dataSource></environment>
</environments>
dataSource的type属性:
- POOLED:使用连接池管理连接,使用MyBatis自带的连接池。
- UNPOOLED:不使用连接池,直接由JDBC连接。
- JNDI:由JAVAEE服务器管理连接,如果使用Tomcat作为服务器则使用Tomcat自带的连接池管理。
< mappers>标签
<mappers>用于注册映射文件或持久层接口,只有注册的映射文件才能使用,共有四种方式都可以完成注册:
-
使用相对路径注册映射文件
<mappers><mapper resource="com/mybatis/mapper/UserMapper.xml"/> </mappers> -
使用绝对路径注册映射文件
<mappers> <mapper url="file:///C:\Users\a\IdeaProjects\mybatiscase\mybatisDemo1\src\main\resources\com\mybatis\mapper\UserMapper.xml"/> </mappers> -
注册持久层接口
<mappers> <mapper class="com.mybatis.mapper.UserMapper"/> </mappers> -
注册一个包下的所有持久层接口
<mappers><package name="com.mybatis.mapper"/> </mappers>
相关文章:
【精选】框架初探篇之——MyBatis的CRUD及配置文件
MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…...
ES8语法async与await
async和await两种语法结合可以让异步代码像同步代码一样。 一、async函数 async函数的返回值为Promise对象promise对象的结果由async函数执行的返回值决定 async function fn() {// 返回一个字符串return 字符串;// 返回的结果不是一个Promise类型的对象…...
c#处理SQLSERVER 中image数量类型为空
项目场景: DataRow dataRow dataTable.Rows[i]; var pxpicture dataRow ["pxImage"];if (pxpicture!null){byte[] pic (byte[])pxpicture;acs.Add("pxpicture", Convert.ToBase64String(pic));}问题描述 代码执行出现错误: 无…...
五子棋游戏
import pygame #导入pygame模块 pygame.init()#初始化 screen pygame.display.set_mode((750,750))#设置游戏屏幕大小 running True#建立一个事件 while running:#事件运行for event in pygame.event.get():if event.type pygame.QUIT:#当点击事件后退出running False #事…...
vue+SpringBoot的图片上传
前端VUE的代码实现 直接粘贴过来element-UI的组件实现 <el-uploadclass"avatar-uploader"action"/uploadAvatar" //这个action的值是服务端的路径,其他不用改:show-file-list"false":on-success"handleAvatarSuccess"…...
FFmepg 核心开发库及重要数据结构与API
文章目录 前言一、FFmpeg 核心开发库二、FFmpeg 重要数据结构与 API1、简介2、FFmpeg 解码流程①、FFmpeg2.x 解码流程②、FFmpeg4.x 解码流程 3、FFMpeg 中比较重要的函数以及数据结构①、数据结构②、初始化函数③、音视频解码函数④、文件操作⑤、其他函数 三、FFmpeg 流程1…...
训练 CNN 对 CIFAR-10 数据中的图像进行分类
1. 加载 CIFAR-10 数据库 import keras from keras.datasets import cifar10# 加载预先处理的训练数据和测试数据 (x_train, y_train), (x_test, y_test) cifar10.load_data() 2. 可视化前 24 个训练图像 import numpy as np import matplotlib.pyplot as plt %matplotlib …...
香港科技大学广州|智能制造学域博士招生宣讲会—天津大学专场
时间:2023年12月07日(星期四)15:30 地点:天津大学卫津路校区26楼B112 报名链接:https://www.wjx.top/vm/mmukLPC.aspx# 宣讲嘉宾: 汤凯教授 学域主任 https://facultyprofiles.hkust-gz.edu.cn/faculty-p…...
滑动窗口练习(二)— 子数组中满足max -min <= sum的个数
题目 给定一个整型数组arr,和一个整数num 某个arr中的子数组sub,如果想达标,必须满足: sub中最大值 – sub中最小值 < num, 返回arr中达标子数组的数量 暴力对数器 暴力对数器方法主要是用来和另一个方法互相校验正…...
用xlwings新建一个excel并同时生成多个sheet
新建一个excel并同时生成多个sheet,要实现如下效果: 一般要使用数据透视表来快速实现。 今天记录用xlwings新建一个excel并同时生成多个sheet。 import xlwings as xw # 打开excel,参数visible表示处理过程是否可视,add_book表示是否打开新的Excel程序…...
诺威信,浪潮云,微众区块链
目录 诺威信B隐私计算平台 浪潮云=星火连-澳优码 HyperChain 产品介绍 CA认证即电子认证服务...
Redux在React中的使用
Redux在React中的使用 1.构建方式 采用reduxjs/toolkitreact-redux的方式 安装方式 npm install reduxjs/toolkit react-redux2.使用 ①创建目录 创建store文件夹,然后创建index和对应的模块,如上图所示 ②编写counterStore.js 文章以counterStore…...
Go 数字类型
一、数字类型 1、Golang 数据类型介绍 Go 语言中数据类型分为:基本数据类型和复合数据类型基本数据类型有: 整型、浮点型、布尔型、字符串复合数据类型有: 数组、切片、结构体、函数、map、通道(channel)、接口 2、…...
时间序列预测 — Informer实现多变量负荷预测(PyTorch)
目录 1 实验数据集 2 如何运行自己的数据集 3 报错分析 1 实验数据集 实验数据集采用数据集4:2016年电工数学建模竞赛负荷预测数据集(下载链接),数据集包含日期、最高温度℃ 、最低温度℃、平均温度℃ 、相对湿度(平均) 、降雨…...
2023年金融信创行业研究报告
第一章 行业概况 1.1 定义 金融信创是指在金融行业中应用的信息技术,特别是那些涉及到金融IT基础设施、基础软件、应用软件和信息安全等方面的技术和产品。这一概念源于更广泛的“信创 (信息技术应用创新)”,即通过中国国产信息技术替换海外信息技术&a…...
51单片机按键控制LED灯亮灭的N个玩法
51单片机按键控制LED灯亮灭的N个玩法 1.概述 这篇文章介绍按键的使用,以及通过控制LED灯的小实验,发现按键中存在的问题,然后思考并解决这些问题。达到熟练使用按键控制元器件。 2.搭建硬件环境 1.硬件准备 名称型号数量单片机STC12C205…...
推荐6款本周 yyds 的开源项目
🔥🔥🔥本周GitHub项目圈选: 主要包含 链接管理、视频总结、有道音色情感合成、中文文本格式校正、GPT爬虫、深度学习推理 等热点项目。 1、Dub 一个开源的链接管理工具,可自定义域名将繁杂的长链接生成短链接,便于保…...
【Git】git 更换远程仓库地址三种方法总结分享
因为公司更改了 gitlab 的网段地址,发现全部项目都需要重新更改远程仓库的地址了,所以做了个记录,说不定以后还会用到呢。 一、不删除远程仓库修改(最方便) # 查看远端地址 git remote -v # 查看远端仓库名 git rem…...
springboot 返回problem+json
spring所有配置都在WebMvcAutoConfiguration中 其中有 ProblemDetailsExceptionHandler 容器中的一个组件 -ControllerAdvice用来集中处理异常的 -点进ResponseEntityExceptionHandler 包含这些异常,如果出现以下异常,会被springboot支持以RFC 7807规…...
AI动画制作 StableDiffusion
1.brew -v 2.安装爬虫项目包所必需的python和git等系列系统支持部件 brew install cmake protobuf rust python@3.10 git wget pod --version brew link --overwrite cocoapods 3.从github网站克隆stable-diffusion-webui爬虫项目包至本地 ssh-add /Users/haijunyan/.ssh/id_r…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
