MyBatis 框架基本的增删改查
提示:写代码要严谨
文章目录
- 前言
- 前期准备
- MyBatis CRUD操作流程
- 增加功能
- 删除功能
- 修改功能
- 查询功能
- #{} 占位符
- ${} 占位符
- 两种占位符的区别❗
- 映射文件总结❗
- mapper 代理方式实现CRUD
- mapper代理开发规范
- 增加功能
- 删除功能
- 修改功能
- 查询功能
前言
提示:mybatis官网
MyBatis 代码最主要的是简化 dao 层代码
ORM思想
O:po类
R:关系,数据库
M:mapper,映射
前期准备
第一步:新建项目Maven项目

在下一步中勾选第一个选项,创建一个简单的项目,最后填写相关信息后完成

如果有需要导入的配置文件:

这样做的好处是:即便原有的配置文件被删掉也没事
第二步:
项目建成后在 pom.xml 文件中导入相关代码,比如:
缺什么加什么
<dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version><!-- <version>5.1.6</version> --></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- 使用log4j输出更多的日志信息 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies><build><resources><resource><!--表示需要编译的源文件路径--><directory>src/main/java</directory><includes><!--表示以.properties和*.xml结尾的文件将进行编译--><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><!--表示需要编译的源文件路径--><directory>src/main/resources</directory><includes><!--表示以.properties和*.xml和.yml结尾的文件将进行编译--><include>**/*.properties</include><include>**/*.xml</include><include>**/*.yml</include></includes><filtering>false</filtering></resource></resources></build>
第三步:
在 main/resources 文件夹中创建 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><typeAliases><package name=""/></typeAliases><!-- 配置数据源相关属性 --><environments default="development"><!-- 可以配置多个数据源环境,默认使用default中的值 --><environment id="development"><!-- 使用jdbc的事务管理 --><transactionManager type="MANAGED" /><!-- 配置数据源,并使用自带数据库连接池 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&serverTimezone=Asia/Shanghai" /><property name="username" value="root" /><property name="password" value="123456" /></dataSource></environment></environments><!-- 配置映射文件,可配置多个 --><mappers><!-- 指定映射文件路径,复制一下 --><mapper resource="" /><mapper resource="" /></mappers>
</configuration>
第四步:
在 main/resources 文件夹中还有个 log4j.properties 配置文件,可以显示 log 输出
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
log4j.rootLogger=debug,stdout
第五步:
在main/resources文件夹中新建映射文件 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=""></mapper>
第六步:在 test/java 文件夹下创建 test 测试类
import java.io.InputStream;
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.junit.After;
import org.junit.Before;
import org.junit.Test;public class AppTest {private SqlSession session=null;@Beforepublic void before() throws Exception {InputStream input = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(input);session= ssf.openSession();}@Afterpublic void after() {session.close();} @Test public void test() {}}
第七步:
MySQL建表语句:
drop table if exists emp;create table EMP
(EMPNO int primary key,ENAME varchar(20),JOB varchar(9),MGR int,HIREDATE date,SAL double,COMM double,DEPTNO int,foreign key (DEPTNO) references DEPT (DEPTNO)
);
提示:以下是本篇文章正文内容,下面案例可供参考
MyBatis CRUD操作流程
增加功能
在main/java文件夹中新建 po 包及类
public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer Deptno;// 自动生成 Getter、Setter、toString()、有参无参方法
}
在main.resources文件夹中新建映射文件 mapper.xml
这里面写的就是SQL语句
parameterType里面的参数是:在 po 类中双击类的名字,右键复制限定名

SQL语句中的具体数据要写成#{}占位符的写法
大括号中的属性名要与 po 类中的名字一致(注意大小写),而 po 类中的名字要与数据库中的名字一致
<mapper namespace="emp"><!-- 方法名, 参数 返回值(只有查询有) --><insert id="insertEmp" parameterType="com.mybatis.po.Emp">insert into emp values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{Deptno})</insert>
</mapper>
接下来在 config.xml 文件中增加配置文件
<!-- 配置映射文件,可配置多个 --><mappers><!-- 指定映射文件路径,复制一下 --><mapper resource="EmpMapper.xml" /></mappers>
接下来就可以测试了,测试代码:
@Test// insertEmp()起个名public void insertEmp() {Emp emp = new Emp(8988, "张三", "Java", 7790, new Date(2023, 10, 23), 10000.0, 99.0, 20);// "emp.insertEmp" → "namespace的值.insertEmp方法名是映射文件中的id"int i = session.insert("emp.insertEmp", emp);System.out.println(i);}

接下来右键该 test 类测试,点击运行方式 → JUnit测试

他会运行前面带@Test的方法

删除功能
#{} 占位符中的名字 如果参数是 po 类型,那么名字必须是属性名,如果参数是基本类型或String,那么参数名字自定义
映射文件代码:
<delete id="deleteEmp" parameterType="int">delete from empwhere empno = #{随便起名}</delete>
测试类代码:
@Testpublic void deleteEmp() { int i = session.delete("emp.deleteEmp",8966);System.out.println(i); }
修改功能
映射文件代码:
<update id="updateEmp" parameterType="com.neuedu.mybatis.po.Emp">update emp set ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},Deptno=#{Deptno}where empno = #{empno}</update>
测试类代码:
@Testpublic void updateEmp() { Emp emp = new Emp(8988,"enen","java全栈",7790,new Date(2003, 10, 13), 11000.0, 999.0, 20);int i = session.update("emp.updateEmp",emp);System.out.println(i);}
查询功能
#{} 占位符
映射文件代码:
<select id="queryEmps" parameterType="String" resultType="com.neuedu.mybatis.po.Emp">select * from emp where ename like concat('%',#{名字模糊查询},'%')</select>
测试类代码:
@Testpublic void queryEmp() {List<Emp> list = session.selectList("emp.queryEmps","T");for (Emp emp : list) {System.out.println(emp);}}
除了#{}外还有种占位符叫${},现在用的比较少
${} 占位符
映射文件代码:
<select id="queryEmps" parameterType="String" resultType="com.neuedu.mybatis.po.Emp">select * from emp where empno like concat('%','${value}','%')</select>
测试类代码:
@Test public void queryDept() {List<Dept> list = session.selectList("dept.queryDepts","O");for (Dept dept : list) {System.out.println(dept);}}
两种占位符的区别❗
${} 使用的是普通的 Statement 语句运行,运行效率低,采用的是SQL语句拼接的方式,可能发生SQL注入安全问题
#{} 使用的是 PreparedStatement 预编译语句,运行效率高,能够防止SQL注入,安全性高
映射文件总结❗
- 映射文件可以理解为dao类,里面写的就是SQL语句
- 映射文件中的
insert update delete select标记,理解为dao类中的方法 id属性理解为方法名,parameterType属性理解为参数,resultType属性理解为方法返回值(增删改不需要配置,因为只能是 int 类型)- SQL语句中的具体数据要写成
#{}占位符的写法,#{属性名1},#{属性名2} #{}占位符中的名字 如果参数是 po 类型,那么名字必须是属性名,如果参数是基本类型或字符串,那么参数名字自定义alt + /是提示
mapper 代理方式实现CRUD
mapper代理开发规范
1.在同一个包中新建一个接口和与之同名的映射文件
2.映射文件的namespace必须是接口的限定名
3.映射文件中语句id必须和接口中方法名一致
4.映射文件中语句parameterType必须和接口中方法参数一致
5.映射文件中语句resultType必须和接口中方法返回值类型一致
一个 mapper.xml 对应一个 mapper.java 接口,接口的实现类由MyBatis 自动生成
在数据库中新建客户表
drop table if exists cust;CREATE TABLE cust (id INT PRIMARY KEY auto_increment, # id自增name VARCHAR(50) NOT NULL, # 姓名phone VARCHAR(20), # 电话birthday DATE, # 出生日期balance DOUBLE # 余额
);
INSERT INTO cust (id, name, phone, birthday, balance) VALUES (1, '张三', '13611111111', '1990-01-01', 1000.00);INSERT INTO cust (id, name, phone, birthday, balance) VALUES (2, '李四', '13722222222', '1995-02-02', 2000.00);INSERT INTO cust (id, name, phone, birthday, balance) VALUES (3, '王五', '13833333333', '1985-03-03', 3000.00);
main/java内新建 po 包及其Java类
public class Cust {private Integer id;private String name;private String phone;private Date birthday;private double balance;// 自动生成 Getter、Setter、toString()、有参无参方法
}
接着在main/java内新建Cust 接口及 .xml 文件
在CustMapper.xml 文件中,namespace是接口的限定名
<mapper namespace="com.mybatis.mapper.CustMapper">
在mybatis-config.xml文件中的配置:
<!-- 1.package name是po包的限定名 --><typeAliases><package name="com.mybatis.po"/></typeAliases><!-- 中间代码省略 --><!-- 2.配置映射文件,可配置多个 --><mappers><!-- 指定映射文件包(mapper包) 的限定名,复制一下 --><package name="com.mybatis.mapper"/></mappers>
增加功能
首先在接口中定义方法:
int insertCust(Cust cust);
Customers.xml 文件代码:
<insert id="insertCust" parameterType="Cust"> insert into cust(id,name,phone,birthday,balance)values (#{id},#{name},#{phone},#{birthday},#{balance})</insert>
测试代码:
@Testpublic void insertCust() {// 得到mapper接口实现类对象CustMapper mapper = session.getMapper(CustMapper.class);// 主键是自增的,所以id可以为空Cust cust = new Cust(null,"张三", "15794612345", new Date(2003-8-03),20.5);// 调用接口中定义的方法int i = mapper.insertCust(cust);System.out.println(i);}

增加后怎么拿到主键呢?
在映射文件中:加上查询主键值
<insert id="insertCust" parameterType="Cust"><!-- 获得自动递增的主键值 --><selectKey keyProperty="id" resultType="int" order="AFTER"><!-- 查一个虚表,最后一次插入的值 先执行增加的sql语句,再执行查询,获取插入的主键值,然后赋值给keyProperty的id -->select last_insert_id() from dual</selectKey> insert into cust(id,name,phone,birthday,balance)values (#{id},#{name},#{phone},#{birthday},#{balance})</insert>
测试代码加上:
System.out.println("增加的主键值是:"+cust.getId());

删除功能
首先在接口中定义方法:
int deleteCust(int id);
映射文件 CustMapper.xml 中:
<delete id="deleteCust" parameterType="int">delete from custwhere id = #{int类型随便起名}</delete>
测试代码:
@Testpublic void deleteCustomers() {CustMapper mapper = session.getMapper(CustMapper.class);int i = mapper.deleteCust(3);System.out.println(i);}

修改功能
首先在接口中定义方法:
int updateCust(Cust cust);
映射文件 CustMapper.xml 中:
<update id="updateCust" parameterType="Cust">update custset name = #{name}, phone = #{phone}, birthday = #{birthday}, balance = #{balance}where id = #{id}</update>
测试代码:
@Testpublic void updateCust() {CustMapper mapper = session.getMapper(CustMapper.class);Cust cust = new Cust(5,"李四", "15846012345", new Date(2013-8-03),1320.5);int i = mapper.updateCust(cust);System.out.println(i);}

查询功能
首先在接口中定义方法:
// id查询Cust queryCustById(int id);// 名字和电话的模糊查询List<Cust> queryCusts(Cust cust);
映射文件 CustMapper.xml 中:
<select id="queryCustById" parameterType="int" resultType="Cust">select * from custwhere id = #{随便起名}</select><select id="queryCusts" parameterType="Cust" resultType="Cust">select * from custwhere name like concat('%',#{name},'%')and phone like concat('%',#{phone},'%')</select>
测试代码:
@Testpublic void query() {CustMapper mapper = session.getMapper(CustMapper.class); mapper.queryCustById(6);Cust cust = new Cust(null,"四", "2345", null,130020.5);mapper.queryCusts(cust);}
重点看控制台输出语句是否正确

相关文章:
MyBatis 框架基本的增删改查
提示:写代码要严谨 文章目录 前言前期准备MyBatis CRUD操作流程增加功能删除功能修改功能查询功能#{} 占位符${} 占位符两种占位符的区别❗ 映射文件总结❗ mapper 代理方式实现CRUDmapper代理开发规范增加功能删除功能修改功能查询功能 前言 提示:myba…...
Javascript--JSON
什么是 JSON? JavaScript中的JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于存储和表示结构化的数据。JSON使用键值对的方式组织数据,并支持基本数据类型(字符串、数字、布尔值、数组和对象&…...
Rust: error: failed to run custom build command for `openssl-sys v0.9.71`
error: failed to run custom build command for openssl-sys v0.9.71 解决 windows : openssl 不要选Light版 设置环境变量 cmd: set OPENSSL_DIR“C:\Program Files\OpenSSL-Win64” OPENSSL_DIR:C:\Program Files\OpenSSL-Win64 linux:…...
Excel修改日期格式,改变日期的筛选方式
我们有两列日期数据: 左边这一列筛选会显示: 右边这一列筛选会显示: 修改格式,将【日期1】改为【日期2】 将【日期1】的格式修改为文本格式即可 修改格式,将【日期2】改为【日期1】 选中日期2,点击【数据…...
【RabbitMQ(day2)】默认(直连)交换机的应用
文章目录 一、第一种模型(Hello World)二、第二种模型(work queue)自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结: 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…...
谷粒商城第八天-商品服务之品牌管理的整体实现(直接使用逆向生成的代码;含oss文件上传)
目录 一、总述 二、前端部分 2.1 创建好品牌管理菜单 2.2 复制组件 编辑2.3 复制api 编辑 2.4 查看效果 编辑2.5 需要优化的地方 2.6 具体优化实现 2.6.1 优化一:将表格的状态列(这里是是否显示列)修改为开关ÿ…...
阿里云率先荣获容器集群稳定性先进级认证
7 月 25 日,由中国信通院发起的“2023 稳保体系”评估结果在可信云大会现场公布,阿里云容器服务 ACK 成为首批通过“云服务稳定运行能力-容器集群稳定性”评估的产品,并荣获“先进级”认证。 云原生技术正在激活应用构建新范式,构…...
【SpringBoot笔记37】SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket
这篇文章,主要介绍SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket。 目录 一、基于注解集成WebSocket 1.1、WebSocket常见注解 1.2、创建WebSocket服务端 1.3、配置ServerEndpointExpor...
PyTorch(安装及卸载)
目录 1. 安装 2. 卸载 参考文献 为什么用PyTorch:简单来说,19年之前tensorflow是大哥,19年tensorflow和PyTorch双龙并行,20年之后PyTorch一往无前。宗旨,哪个用的人多用哪个。 1. 安装 1. 先打开Anaconda Prompt&…...
webScoket
webScoket是什么? 支持端对端通讯可以由客户端发起,也可以有服务端发起用于消息通知、直播间讨论区、聊天室、协同编辑等 做一个简单的webScoket 客户端配置: 1、新建一个页面叫web-scoket.html <!DOCTYPE html> <html lang"…...
【C语言初阶(20)】调试练习题
文章目录 前言实例1实例2 前言 在我们开始调试之前,应该有个明确的思路;程序是如何完成工作的、变量到达某个步骤时的值应该是什么、出现的问题大概会在什么位置。这些东西在调试之前都需要先确认下来,不然自己都不知道自己在调试个什么东西…...
MicroPython ESP32网页实时更新DHT11数据显示
MicroPython ESP32网页实时更新DHT11数据显示 📌相关篇《MicroPython ESP32 读取DHT11温湿度传感器数据》📍《【Micropython esp32/8266】网页点灯控制示例》 ✨本例综合以上两篇文章内容实现:在本地网页中显示DHT11温度传感器数据。可以做到…...
JavaWeb之HTML基础篇(一)
系列文章目录 HTML基础篇(一) 文章目录 系列文章目录HTML基础篇(一)[TOC](文章目录) 前言一、HTML简介1.1介绍1.2HTML文件的书写规范1.3 HTML标签介绍1.4 HTML常见的标签 二、CSS的简介2.1css技术介绍2.2 CSS与HTML结合的三种方式…...
TVM_深度学习编译器
TVM_深度学习编译器 TVM所做的是要比传统compiler更偏上层的,你可以把它理解成source-to-source compiler,需要其他的后端(backend)来生成最后的指令。比如当编译的Target是Intel CPU时,翻译的顺序是Relay IR -> TVM IR/ Halide IR -> LLVM IR,之后交给LLVM生成最后…...
Flutter InheritedWidget 共享状态管理
InheritedWidget和React中的context功能类似,可以实现跨组件数据的传递。 定义一个共享数据的InheritedWidget,需要继承自InheritedWidget 这里定义了一个of方法,该方法通过context开始去查找祖先的HYDataWidget(可以查看源码查找…...
什么是反射?Java反射?反射的优缺点
目录 什么是反射(Reflection )?Java反射?反射的优缺点获取Class对象的三种方式:java反射技术的应用场景 什么是反射(Reflection )? 主要是指程序可以访问、检测和修改它本身状态或行…...
小红书2020校招测试开发后端笔试题卷三
//完全背包求组合数 #include <iostream> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; int value[300]; // vector<int>vis; // vector<int>vis1; map<vector<int>,int>m…...
python数据可视化Matplotlib
1.绘制简单的折线图 # -*- coding: utf-8 -*- import matplotlib.pyplot as pltinput_values [1, 2, 3, 4, 5] squares [1, 4, 9, 16, 25] plt.style.use(seaborn) fig, ax plt.subplots() ax.plot(input_values, squares, linewidth3) # 线条粗细# 设置图表标题并给坐标…...
firewalld防火墙
firewalld防火墙 它属于包过滤防火墙。工作在网络层,是centos7自带的默认防火墙。主要是取代iptables。 firewalld的两种配置模式: 分别是运行时配置和永久配置。 iptable是静态防火墙 firewalld是动态防火墙 它是按照区域来划分的,有9…...
iMacros WebBrowser Component for .NET
iMacros WebBrowser Component for .NET 在几分钟内实现应用程序自动化 快速轻松地将iMacro集成到您的应用程序中。不需要单独的安装程序。 无缝集成 iMacros与您的.NET应用程序无缝集成,作为Microsoft WebBrowser控件的替代品。它甚至可以用作每个.NET应用程序中的…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
