使用MyBatis操作数据库
hi,大家好,今天为大家带来MyBatis操作数据库的知识
文章目录
- 🐷1.根据MyBatis操作数据库
- 🧊1.1查询操作
- 🍇1.1.1无参查询
- 🍇1.1.2有参查询
- 🧊1.2删除操作
- 🧊1.3修改操作
- 🧊1.4增加操作
- 🧊1.5特殊的添加:返回自增id
- 🧊1.6like查询
- 🧊1.7多表查询
- 🍇1.7.1一对一查询
- 🍇1.7.2一对多查询
- 🧊1.8动态sql
- 🐷2.动态标签
- 🧊2.1 <if>标签
- 🧊2.2<trim>标签
- 🧊2.3<where>标签
- 🧊2.4<set>标签
- 🧊2.5<foreach>标签
🐷1.根据MyBatis操作数据库
1.接口:方法的声明(给Service层调用)
2. XML:实现接口
🧊1.1查询操作
🍇1.1.1无参查询
1.定义接口
@Mapper//代表数据持久层
public interface UserMapper {List<Userinfo> getAll();
}
2.在xml里面写接口的实现

这里的namespace里面的内容表明了当前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="com.example.demo.mapper.UserMapper"><select id="getAll" resultType="com.example.demo.model.Userinfo">select * from userinfo</select>
</mapper>
根据接口写测试类
package com.example.demo.mapper;import com.example.demo.model.Userinfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;/*** Created with IntelliJ IDEA.* Description:* User: WHY* Date: 2023-08-08* Time: 9:56*/
@SpringBootTest //不能省略,表明当前测试程序当前项目是运行在spring boot项目中的
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid getAll() {List<Userinfo> list=userMapper.getAll();System.out.println(list);}
}

从结果中可以看到运行是成功的,打印了sql语句,也打印了结果
为了方便开发MyBatis,实现XML和对应的接口之间的快速跳转,我们可以安装一个MyBatisX插件



红色的小鸟和蓝色的小鸟相互点击就可以跳转
🍇1.1.2有参查询

<select id="getById" resultType="com.example.demo.model.Userinfo">select * from userinfo where id=${uid}</select>


加上这个@Param注解,在传参的时候就必须用该注解里面的名字
我们可以测试一下


错误显示说ID不存在
改成id


运行成功了
MyBatis有参查询的时候传递参数的方法有两个
1.使用$符
这俩相对应,结果 显示的是直接替换,也叫做及时执行

这是直接将id位置的数字替换成出传过来的参数
2.采用#
运行结果是采用了JDBC里面那种占位符的形式

意味sql执行是预编译执行的
问题:${}和#{}的区别
1.${}是直接替换,#{}是预执行
2.${}不安全,存在sql注入,#{}安全,不存在sql注入
sql注入:使用一些特殊的sql语句完成一些非法操作,比如一个登录功能,只有用户名和密码均输入正确,才能登录成功,但是当密码胡乱输入也登陆成功,也就是sql注入
${}可以实现的功能#{}都能实现.
👀👀👀而且${}还存在sql注入的问题,为啥还要用它?
因为有一种场景预编译做不到!
比如在网上购物时,浏览商品的时候有按照价格升序或者降序,此时如果使用#{}那么就会把升序或者降序当做value值,加一个单引号,那么在sql语句中自然是错误的,使用${}就直接替换,采用string拼接的方式,不会报错,举个例子



换成$符号


运行成功了
总结:$应用场景:当业务需要传递sql命令的时候
注意事项:使用$符传的的参数一定要被穷举
我们刚才的例子里面参数可以被穷举,一个是asc,一个是desc,符合条件
🧊1.2删除操作




因为id=85的用户压根不存在


当在测试的时候想要保证不影响数据库的数据,可以加上一个transitional注解,代表开启是事务,可以回滚


我们可以看到受影响的行数,但是也不影响数据库的数据

注意但类中属性和数据库表中的字段名不一样时.查询结果可能为null
解决办法:
🥝1.将类名属性和表中字段名改为一致
🥝2.使用sqi语句的as进行字段名重命名


🥝3.定义一个resultMap,将属性名和字段名进行手动映射


<resultMap id="AseMap" type="com.example.demo.model.Userinfo"><id column="id" property="id"></id><result column="username" property="name"></result><result column="password" property="password"></result><result column="photo" property="photo"></result><result column="createtime" property="createtime"></result><result column="updatetime" property="updatetime"></result><result column="state" property="state"></result>
</resultMap>
column代表的是字段名,property代表的是属性名


可以看到显示了名字
🧊1.3修改操作





可以看到修改成功
修改,删除,增加都默认返回受影响的行数
🧊1.4增加操作




插入成功
🧊1.5特殊的添加:返回自增id

<insert id="add2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">insert into userinfo(username,password,photo) values(#{username},#{password},#{photo})</insert>

@Testvoid add2() {Userinfo userinfo=new Userinfo();userinfo.setUsername("詹妮");userinfo.setPassword("5896");userinfo.setPhoto("null");int result=userMapper.add2(userinfo);System.out.println("受影响的行数"+result+"id"+userinfo.getId());}
为什么我这里没有设置id我却可以使用getid方法?
因为数据库的id已经设置到了该属性中


🧊1.6like查询
List<Userinfo> getByLike();
<select id="getByLike" resultType="com.example.demo.model.Userinfo">select * from userinfo where username like '_%三'</select>
@Testvoid getByLike() {List<Userinfo> list=userMapper.getByLike();System.out.println(list.toString());}

当查询的时候不一定是按照这个字匹配,可以换成一个动态的,把匹配条件放到测试类里面
<select id="getByLike" resultType="com.example.demo.model.Userinfo">select * from userinfo where username like #{username}</select>
@Testvoid getByLike() {String username="_三%";List<Userinfo> list=userMapper.getByLike(username);System.out.println(list.toString());}

2.使用mysql内置函数concat
<select id="getByLike" resultType="com.example.demo.model.Userinfo">select * from userinfo where username like concat('%',#{username},'%')</select>
@Testvoid getByLike() {String username="三";List<Userinfo> list=userMapper.getByLike(username);System.out.println(list.toString());}
}

🧊1.7多表查询
🍇1.7.1一对一查询
在查询文章表的过程中显示用户姓名
我们不采用xml实现接口,我们采用注解的方式
增删改查都有对应的注解
package com.example.demo.model;import lombok.Data;import java.time.LocalDateTime;/*** Created with IntelliJ IDEA.* Description:* User: WHY* Date: 2023-08-08* Time: 18:43*/
@Data
public class Articleinfo {private int id;private String title;private String content;private LocalDateTime createtime;private LocalDateTime updatetime;private int uid;private int rcount;private int state;//联表字段private String username;}
@Mapper
public interface ArticleMapper {@Select("select * from articleinfo")List<Articleinfo> getAll();
}
package com.example.demo.mapper;import com.example.demo.model.Articleinfo;
import com.example.demo.model.Userinfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;/*** Created with IntelliJ IDEA.* Description:* User: WHY* Date: 2023-08-08* Time: 18:52*/
@SpringBootTest
class ArticleMapperTest {@Autowiredprivate ArticleMapper articleMapper@Testvoid getAll() {List<Articleinfo> list=articleMapper.getAll();System.out.println(list.toString());}
}

将联合查询的语写在注解里面即可
@Mapper
public interface ArticleMapper {@Select("select articleinfo.*,userinfo.username from articleinfo,userinfo where articleinfo.uid=userinfo.id")List<Articleinfo> getAll();
}

所以MyBatis不仅可以采用接口+xml实现
还可以采用接口+注解的方式实现
🍇1.7.2一对多查询
查询一个用户的多篇文章
我们采用线程的方式
一个查用户表,一个查文章表,最后拼接起来
先采用单线程的方式来写
@Data
public class Userinfo {//这里的属性要和数据库表的字段对应private int id;private String username;private String password;private String photo;private LocalDateTime createtime;private LocalDateTime updatetime;private int state;private List<Articleinfo> article;
}
List<Userinfo> getByLike(@Param("username") String username);@Select("select * from userinfo where id=#{id}")Userinfo getByid(@Param("id") Integer id);
@Select("select * from articleinfo where uid=#{uid}")List<Articleinfo> getByarticle(@Param("uid") Integer uid);
@Testvoid getUserList(){int uid=1;//1.先根据uid查询用户表Userinfo userinfo= userMapper.getByid(uid);System.out.println(userinfo);//2.根据uid查询文章List<Articleinfo> list= articleMapper.getByarticle(uid);//组装数据userinfo.setArticle(list);System.out.println(userinfo);}
}

采用多线程的方式
@Testvoid getUserList(){int uid=1;//定义线程池ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(5,10,3000, TimeUnit.SECONDS,new LinkedBlockingDeque<>(100));final Object[] result=new Object[2];//1.先根据uid查询用户表threadPoolExecutor.submit(new Runnable() {@Overridepublic void run() {result[0] = userMapper.getByid(uid);}});//2.根据uid查询文章threadPoolExecutor.submit(new Runnable() {@Overridepublic void run() {result[1] = articleMapper.getByarticle(uid);}});//组装数据(等线程池执行结束以后)while (threadPoolExecutor.getTaskCount() !=threadPoolExecutor.getCompletedTaskCount()) {}Userinfo userinfo=(Userinfo) result[0];userinfo.setArticle((List<Articleinfo>)result[1]);System.out.println(userinfo);}

🧊1.8动态sql
动态sql是MyBatis的强大特性之一
在填写某一个页面的时候,有些页面不需要填写,不插入这个字段
动态sql主要是在xml里面动态的进行判断
我们拿userinfo表中的photo来进行举例

看到photo默认是空



现在的问题是当不设定时photo啥也没有,符合预期,当设定photo的时候,就出现了值,我们想要的效果是当该字段默认为空,不可进行显示设置,所以我们需要使用标签
🐷2.动态标签
🧊2.1 标签
<insert id="add3">insert into userinfo(username,password<if test="photo!=null">,photo</if>)values(#{username},#{password}<if test="photo!=null">,#{photo}</if>)</insert>
单元测试来一波~~~
@Testvoid add3() {Userinfo userinfo=new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("123");userinfo.setPhoto("dor.png");int result=userMapper.add3(userinfo);System.out.println("受影响的行数"+result);}

现在将photo的设定取消


可以看到没有photo再出现
🧊2.2标签
标签针对单个字段是选填项的时候比较方便,当所有字段都是选填项时,我们可以使用标签
标签中有如下属性:
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixOverrides:表示整个语句块要去除掉的前缀
suffixOverrides:表示整个语句块要去除掉的后缀
<insert id="add4">insert into userinfo<trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null">username,</if><if test="password!=null">password,</if><if test="photo!=null">photo</if></trim>values<trim prefix="(" suffix=")" suffixOverrides="," ><if test="username!=null">#{username},</if><if test="password!=null">#{password},</if><if test="photo!=null">#{photo}</if></trim></insert>


🧊2.3标签
该标签也是和标签一起使用的.但是仅仅使用在where查询当中
<select id="getBywhere" resultType="com.example.demo.model.Userinfo">select * from userinfo<where><if test="id>0">id=#{id}</if><if test="username!=null">and username=#{username}</if><if test="photo!=null">and password=#{password}</if></where></select>
这个and为什么要加在属性的前面


可以看到没有sql语句,没有多余的and
这也恰恰体现了标签的特性
1.根据标签里面的内容决定是否生成关键字
2.去除最前面的and
那么where的功能用trim可以实现吗?
当然啦
<select id="getBywhere" resultType="com.example.demo.model.Userinfo">select * from userinfo<trim prefix="where" prefixOverrides="and"><if test="id>0">id=#{id}</if><if test="username!=null">and username=#{username}</if><if test="photo!=null">and password=#{password}</if></trim></select>
🧊2.4标签
用来修改数据,有值生成set,去掉的是最后面的符号
<update id="update2">update userinfo<set><if test="username!=null">username=#{username},</if><if test="password!=null">password=#{password}</if><if test="photo!=null">photo=#{photo}</if></set>where id=#{id}</update>

🧊2.5标签
<foreach> 标签常用于遍历集合或数组类型的数据。其属性如下:
collection: 指定要遍历的集合或数组类型的数据item: 指定遍历的集合中的元素别名,可以在标签中使用该别名访问元素index: 指定遍历的集合中的元素索引别名,可以在标签中使用该别名访问元素索引open: 指定遍历的开始标记close: 指定遍历的结束标记separator: 指定遍历元素之间的分隔符javaType: 指定集合或数组所对应的 Java 类型,如果未指定,则 MyBatis 会自动选择最匹配的类型。
适用情况:适用于多条sql删除的时候

<delete id="deleteById2">delete from userinfowhere id in<foreach collection="ids" open="(" close=")" item="id" separator=",">#{id}</foreach></delete>
@Testvoid deleteById2() {List<Integer> list =new ArrayList<Integer>() {{add(10);add(11);add(12);add(13);}};int result=userMapper.deleteById2(list);System.out.println("result"+result);}

这期的内容就到这,我们下期再见咯~~
相关文章:
使用MyBatis操作数据库
hi,大家好,今天为大家带来MyBatis操作数据库的知识 文章目录 🐷1.根据MyBatis操作数据库🧊1.1查询操作🍇1.1.1无参查询🍇1.1.2有参查询 🧊1.2删除操作🧊1.3修改操作🧊1.4增加操作🧊…...
SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--功能实现[五]
文章目录 SSM--功能实现实现功能09-带条件查询分页显示列表需求分析/图解思路分析代码实现测试分页条件查询带条件分页查询显示效果 实现功能10-添加家居表单前端校验需求分析/图解思路分析代码实现完成测试测试页面效果 实现功能11-添加家居表单后端校验需求分析/图解思路分析…...
Qt应用程序窗体最大化失效问题的解决方法
记录一个在Qt开发过程中遇到的问题: 【问题描述】在showEvent中调用showMaximized(),应用程序窗体仍然无法最大化。 【定位分析】在Qt应用程序中,如果窗体最大化失效,可能是因为在窗体的showEvent事件中使用了showMaximized()方…...
python怎么判断变量的数据类型
在编程的世界里,了解各种数据类型是非常重要的。在Python中,有着丰富的数据类型用于存储和处理不同类型的数据。掌握这些数据类型的定义和作用,我们能够更好地在程序中管理和操作数据,提高代码的效率和可读性。 Python中常见的数据…...
FastAPI 构建 API 高性能的 web 框架(二)
上一篇 FastAPI 构建 API 高性能的 web 框架(一)是把LLM模型使用Fastapi的一些例子,本篇简单来看一下FastAPI的一些细节。 有中文官方文档:fastapi中文文档 假如你想将应用程序部署到生产环境,你可能要执行以下操作&a…...
如何实现 Java SpringBoot 自动验证入参数据的有效性
Java SpringBoot 通过javax.validation.constraints下的注解,实现入参数据自动验证 如果碰到 NotEmpty 否则不生效,注意看下 RequestBody 前面是否加上了Valid Validation常用注解汇总 Constraint详细信息Null被注释的元素必须为 nullNotNull被注释的元…...
golang学习随记
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 go学习快捷键及快速生成代码片段go基础循环流程控制关键字切片,拷贝函数闭包 defer语句格式化输出go语言随机数rand.seed() 包管理并发编程goroutinecha…...
【PCL-6】PCL基于凹凸型的分割算法(LCCP)
凹凸型分割算法适用于颜色类似、棱角分明的物体场景分割。LCCP方法不依赖点云颜色,只使用空间信息和法线信息。 算法流程: 1、基于超体聚类的过分割; 2、在超体聚类的基础上再聚类。 算法思路: 1、基于CC和SC判断凹凸性&…...
多进程并发服务器
文章目录 思路问题多进程并发回环服务器代码客户端代码 思路 每当一个客户端连接服务器后,创建一个子进程负责与该客户端通信,客户端断开连接之后,服务器回收子进程资源。 问题 问题1:父进程阻塞在等待连接(accept())处…...
2021秋招总结
2021 秋招总结 作为星球第一批准备秋招的人,经过这几个月的面试之后,感觉也算是有一些小小的经验了吧,就做一个简单的记录,希望能够为星球中准备秋招的伙伴们提供一些参考吧~ 序 4月初加入星球,到9月底,一…...
Linux6.34 Kubernetes yaml文件详解
文章目录 计算机系统5G云计算第三章 LINUX Kubernetes yaml文件详解一、yaml文件概述1.查看 api 资源版本标签2.写一个yaml文件demo 计算机系统 5G云计算 第三章 LINUX Kubernetes yaml文件详解 一、yaml文件概述 Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式…...
防火墙笔记
什么是防火墙 在计算机网络中是指设置在可信任的内部网络和不可信任的外部网络之间的屏障,通过强化边界控制保障内容安全,同时不妨碍内部对外部的访问。 20世纪80年代,最早的防火墙几乎与路由器同时出现,第一代防火墙主要基于包过…...
使用代码下载开源的大模型文件示例以及中文微调llama资源汇总:
一、下载示例 from huggingface_hub import snapshot_downloadrepo_id "THUDM/chatglm2-6b" local_dir ./chatglm2-6b/ cache_dir local_dir "/cache" while True:try:snapshot_download(cache_dircache_dir,local_dirlocal_dir,repo_idrepo_id,loca…...
Wav2vec2 论文阅读看到的一些问题
Wav2vec2 论文阅读看到的一些问题 这里只是简单的思考一下论文的一些问题,不是论文解读。 Q1. 为什么wav2vec依旧需要Transformer来做推理,而不直接使用VQ生成的内容? A1. Transformer在更长的序列上有更好的编码效果,例如论文也写…...
爬虫学习记录(持续更新)
一、问题记录 1.使用webdriver报错AttributeError: str object has no attribute capabilities 解决:目前使用的selenium版本是4.11.2,可以不必设置driver.exe的路径,selenium可以自己处理浏览器和驱动程序,因此,使用…...
libevent源码学习1---创建event
libevent源码学习1—创建event Libevent是一个用于开发可扩展性网络服务器的基于事件驱动(event-driven)模型的非阻塞网络库。安装请参考ubuntu下载安装libevent event_base 使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个 event_base 结构体持有一个…...
Python类的设计
Python类的设计 # 定义一个闹钟类 class Clock:__cureen_keyNone # 私有成员不能改变和使用def __init__(self, id, price): # 类对象是立即自动执行self.id idself.price pricedef ring(self):import winsound # 内置声音方法winsound.Beep(2000,3000)clock1 Clock(…...
微信小程序的项目解构
视频链接 黑马程序员前端微信小程序开发教程,微信小程序从基础到发布全流程_企业级商城实战(含uni-app项目多端部署)_哔哩哔哩_bilibili 接口文档 https://www.escook.cn/docs-uni-shop/mds/1.start.html 1:微信小程序宿主环境 1:常见的宿…...
【Archaius技术专题】「Netflix原生态」动态化配置服务之微服务配置组件变色龙
前提介绍 如果要设计开发一套微服务基础架构,参数化配置是一个非常重要的点,而Netflix也开源了一个叫变色龙Archaius的配置中心客户端,而且Archaius可以说是比其他客户端具备更多生产级特性,也更灵活。*在NetflixOSS微服务技术栈…...
python条件分支和循环语句
python中没有{}的写法,一般时通过缩进的方式来确定分支和循环需要执行的代码块。 if 需要判断的条件表达式:条件成立时的动作 elif 需要判断的条件表达式:条件成立时的动作 else:动作for 变量 in 迭代对象:动作 示例: while 退出条件:动作...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

