当前位置: 首页 > news >正文

Java_Mybatis

        Mybatis是一款优秀的持久层框架,用户简化JDBC(使用Java语言操作关系型数据库的一套API)开发

使用Mybatis查询所有用户数据:

代码演示:
UserMapper:
@Mapper  //被调用时会通过动态代理自动创建实体类,并放入IOC容器中
public interface UserMapper {@Select("select * " +"from user")public List<User> list();}
单元测试中使用:
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {@Autowiredpublic UserMapper userMapper;@Testpublic void contextLoads() {List<User> list = userMapper.list();list.stream().forEach(user -> System.out.println(user));}}

JDBC

JDBC与Mybatis相比:

数据库连接池:

总结:

lombok:

Mybatis日志:

        在application.properties中添加代码

#配置Mybatis的日志信息,并输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

数据库操作

1.通过注解操作数据库

删除操作

根据主键删除:

代码演示:
Mapper类:
@Mapper
public interface EmpMapper {@Delete("delete from emp where id = #{id}")public void delete(Integer id);}
单元测试:
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {@Autowiredpublic EmpMapper empMapper;@Testpublic void deleteTest() {empMapper.delete(17);}}
注意:

        Mapper中的SQL语句“delete from emp where id = #{id}”,这里我们使用的#占位符,表示大括号中间的id为传递的参数,除了#占位符还有$占位符,但是它们有一些区别

★#占位符和$占位符的区别:

        使用#占位符执行SQL时会将#{...}替换为?,生成预编译SQL,会自动设置参数值,使用时机:参数传递

        使用$占位符执行SQL时会直接将参数拼接到SQL语句中,存在SQL注入问题.

SQL注入:

        SQL注入就是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

        比如username='....' and password='.....',传递给password参数:' or '1' = '1 ,这样会得到username='....' and password='' or '1' = '1',总是为true,这样不知道用户名和密码也可以登录了,使用时机:对表名、列表进行动态设置时使用。

SQL预编译的好处:

        1.性能更高:要想执行SQL语句,要连接上数据库,然后将SQL语句发送到数据库中,再进行SQL语法解析检查,优化SQL,编译SQL,执行SQL。但是在SQL语法解析检查,优化SQL,编译SQL过程中,为了提高效率,它会将优化编译后的SQL缓存起来,比如delete from emp where id = #{id},会缓存为delete from emp where id = ?,这样如果只有后面传递的id参数值改变,只需要在缓存中调用这一句即可,就只需要编译一次

        2.更安全(防止SQL注入),通过参数赋值的方法不会更改原本的SQL语义

新增操作

新增:

代码演示:
Mapper类:
@Mapper
public interface EmpMapper {@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +"values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")public void insert(Emp emp);}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid insertTest() {Emp emp = new Emp();emp.setUsername("han");emp.setName("韩");emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2010,1,1));emp.setDeptId(1);emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());empMapper.insert(emp);}}
新增(主键返回):

代码演示:
@Mapper
public interface EmpMapper {@Options(useGeneratedKeys = true,keyProperty = "id")@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +"values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")public void insert(Emp emp);}

更新操作:

更新:

代码演示:
Mapper:
@Mapper
public interface EmpMapper {@Update("update emp set username= #{username},name= #{name},gender= #{gender},image= #{image}," +"job= #{job},entrydate= #{entrydate},dept_id= #{deptId},update_time = #{updateTime} where id = #{id}")public void update(Emp emp);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid updateTest() {Emp emp = new Emp();emp.setId(19);emp.setUsername("han1");emp.setName("韩1");emp.setImage("1.jpg");emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2010,1,1));emp.setDeptId(1);emp.setUpdateTime(LocalDateTime.now());empMapper.update(emp);}}

查询操作:

根据id查询:
代码演示:
Mapper:
@Mapper
public interface EmpMapper {@Select("select * from emp where id = #{id}")public Emp getById(Integer id);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid getByIdTest() {Emp emp = empMapper.getById(19);System.out.println(emp);}}
注意:

        这种编写方式得到的结果中有一部分属性值为null

        这是因为mybatis的数据封装特性(如下)。

数据封装:

解决方案一:

        给字段起别名,让别名与实体类属性保持一致

代码演示:

Mapper:

@Mapper
public interface EmpMapper {/*//与属性名不一致的字段会赋值为null@Select("select * from emp where id = #{id}")public Emp getById(Integer id);*///解决方案一:给字段起别名,让别名与实体类属性保持一致@Select("select id, username, password, name, gender, image, job, entrydate, " +"dept_id deptId, create_time createTime, update_time updateTime" +" from emp where id = #{id}")public Emp getById(Integer id);}
解决方案二:

        通过@Results,@Result注解手动映射封装

 代码演示:

Mapper:

@Mapper
public interface EmpMapper {/*//与属性名不一致的字段会赋值为null@Select("select * from emp where id = #{id}")public Emp getById(Integer id);*//*//解决方案一:给字段起别名,让别名与实体类属性保持一致@Select("select id, username, password, name, gender, image, job, entrydate, " +"dept_id deptId, create_time createTime, update_time updateTime" +" from emp where id = #{id}")public Emp getById(Integer id);*///解决方案二:通过@Results,@Result注解手动映射封装@Results({@Result(column = "dept_id",property = "deptId"),@Result(column = "create_time",property = "createTime"),@Result(column = "update_time",property = "updateTime")})@Select("select * from emp where id = #{id}")public Emp getById(Integer id);}
解决方案三(推荐):

        开启mybatis的驼峰命名自动映射开关

操作步骤:

        只需要在mybatis配置文件application.properties中添加代码

#开启mybatis的驼峰命名自动映射开关(camel)
mybatis.configuration.map-underscore-to-camel-case=true

        这样就可以使用最初的代码也能正确赋值

        但是需要注意:数据库中的字段名要采用下划线命名,Java类中的属性名要采用驼峰命名法

条件查询:

        根据姓名(模糊匹配)、性别、入职日期范围,来查找员工

代码演示:
Mapper:
@Mapper
public interface EmpMapper {//条件查询@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +"entrydate between #{begin} and #{end} order by update_time DESC")public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);}

        这里使用concat函数,是由于#{}会生成预编译SQL,编译后会转换成?,而?存在于单引号中会被认为是字符串,所以使用concat函数,来进行字符串的拼接。

单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid listTest() {List<Emp> list = empMapper.getList("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));System.out.println(list);}}

2.通过XML映射文件操作数据库:

        除了可以使用注解来操作数据库,还可以使用XML映射文件。

代码演示:
xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper"><!--resultType:单条记录所封装的类型--><select id="getList" resultType="com.han.pojo.Emp">select * from emp where name like concat('%',#{name},'%') and gender = #{gender} andentrydate between #{begin} and #{end} order by update_time DESC</select></mapper>
Mapper:
@Mapper
public interface EmpMapper {public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid listTest() {List<Emp> list = empMapper.getList("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));System.out.println(list);}}

3.使用场景

        使用Mybatis的注解,主要是来完成一些简单的增删改查功能/如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

动态SQL:

标签:

1.<if>(<where>、<set>)

查找(<where>):

更新(<set>):

2.<foreach>

        <foreach>一般用于批量操作。

批量操作:
代码演示(批量删除):
XML文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper"><!--resultType:单条记录所封装的类型--><delete id="deleteByIds">delete from emp where id in /*(11,12,13)*/<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete></mapper>
Mapper:
@Mapper
public interface EmpMapper {public void deleteByIds(List<Integer> ids);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {@Autowiredprivate EmpMapper empMapper;@Testvoid deleteByIdsTest() {List<Integer> list = Arrays.asList(11, 12, 13);empMapper.deleteByIds(list);}}

3.<sql>&<include>

代码演示:

        如下面的XML文件代码,其中有一段动态SQL条件查询代码和一段根据id查询代码,它们中有大段的复用代码,如:

        select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
        from emp

使用前代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper"><!--resultType:单条记录所封装的类型--><select id="getById" resultType="com.han.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom empwhere id = #{id}</select><!--resultType:单条记录所封装的类型--><select id="getList" resultType="com.han.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp<where><if test="name != null">name like concat('%', #{name}, '%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time DESC</select></mapper>

        使用<sql>和<include>可以减少代码复用

如下面代码

使用后代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper"><sql id="commonSelect">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp</sql><!--resultType:单条记录所封装的类型--><select id="getById" resultType="com.han.pojo.Emp"><include refid="commonSelect"/>where id = #{id}</select><!--resultType:单条记录所封装的类型--><select id="getList" resultType="com.han.pojo.Emp"><include refid="commonSelect"/><where><if test="name != null">name like concat('%', #{name}, '%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time DESC</select></mapper>

相关文章:

Java_Mybatis

Mybatis是一款优秀的持久层框架&#xff0c;用户简化JDBC(使用Java语言操作关系型数据库的一套API)开发 使用Mybatis查询所有用户数据&#xff1a; 代码演示&#xff1a; UserMapper&#xff1a; Mapper //被调用时会通过动态代理自动创建实体类&#xff0c;并放入IOC容器中…...

2024HW|常见红队使用工具

目录 什么是HW&#xff1f; 什么是网络安全红蓝对抗&#xff1f; 红队 常见工具 信息收集工具 Nmap 简介 漏洞扫描工具 Nessus简介 AWVS 简介 抓包工具 Wireshark简介 TangGo 简介 web 应用安全工具 Burpsuite 简介 SQLMap webshell 管理工具 蚁剑 冰蝎 后…...

Redisson集成SpringBoot

前言&#xff1a;Redisson集成SpringBoot主要有两种方式&#xff0c;一个是使用redisson-spring-boot-starter依赖&#xff08;优先推荐&#xff09;&#xff0c;毕竟springboot主打的就是约定大于配置&#xff0c;这个依赖就是为springboot准备的。 再一种方式就是引入rediss…...

设计模式(十二)行为型模式---模板方法模式

文章目录 模板方法模式结构优缺点UML图具体实现UML图代码实现 模板方法模式 模板方法模式&#xff08;Template Method&#xff09;是一种基于继承实现的设计模式&#xff0c;主要思想是&#xff1a;将定义的算法抽象成一组步骤&#xff0c;在抽象类中定义算法的骨架&#xff…...

【气象常用】剖面图

效果图&#xff1a; 主要步骤&#xff1a; 1. 数据准备&#xff1a;我用的era5的散度数据&#xff08;大家替换为自己的就好啦&#xff0c;era5数据下载方法可以看这里【数据下载】ERA5 各高度层月平均数据下载_era5月平均数据-CSDN博客&#xff09; 2. 数据处理&#xff1a…...

LabVIEW高低温试验箱控制系统

要实现LabVIEW高低温试验箱控制系统&#xff0c;需要进行硬件配置、软件设计和系统集成&#xff0c;确保LabVIEW能够有效地监控和控制试验箱的温度。以下是详细说明&#xff1a; 硬件配置 选择合适的试验箱&#xff1a; 确定高低温试验箱的型号和品牌。 确认试验箱是否支持外…...

Flutter 中的 SliverFillViewport 小部件:全面指南

Flutter 中的 SliverFillViewport 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言来构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中&#xff0c;SliverFillViewport 是一个用于 Custo…...

明日周刊-第12期

以前小时候最期待六一儿童节了&#xff0c;父母总会给你满足一个愿望&#xff0c;也许是一件礼物也许是一次陪伴。然而这个世界上其实还有很多儿童过不上儿童节&#xff0c;比如某些地区的小孩子&#xff0c;他们更担心的是能不能见到明天的太阳。 文章目录 一周热点航天探索火…...

算法之美阅读笔记

这里写自定义目录标题 序04 缓存 -- 忘了它吧 序 在图书馆闲逛时&#xff0c;一本封面为绿色的清新的书引起了我的兴趣&#xff0c;书名是算法之美。我心里不禁嘀咕&#xff0c;大家好喜欢使用某某之美作为书名&#xff0c;比如&#xff1a;数学之美、架构之美。美丽美好的事物…...

新手学习STM32还是ESP32

对于新手来说&#xff0c;选择学习STM32还是ESP32取决于个人的学习目标和背景。以下是针对这两种微控制器的详细分析&#xff0c;以便您做出更明智的选择&#xff1a; STM32 1. 处理器架构与性能 STM32采用单核或多核处理器架构&#xff0c;基于ARM Cortex-M0&#xff0c;M0…...

关于vlookup的第一个参数的个人理解

VLOOKUP&#xff08;查阅值&#xff0c;包含查阅值和返回值的查找区域&#xff0c;查找区域中返回值的列号&#xff0c;精确查找或近似查找&#xff09; 我个人理解&#xff0c;第一个参数应该叫线索值&#xff0c;因为我们要通过它去找与其对应的&#xff08;也就是与其同行的…...

vector实现后半部分

一.迭代器失效 1.定义 指原迭代器在扩容/缩容/修改后指向无效元素或无效地址处 erase的迭代器失效 2.原因&#xff1a; 1.有的编译器实现erase会缩容拷贝 2.删除最后一个后&#xff0c;其指向无效元素 VS中不允许再次使用erase完的迭代器&#xff0c;为了让编写的代码移植…...

Maven配置

Maven – Download Apache Maven https://maven.apache.org/install.html 得下载有 bin的...

python 第一天

循环打印 while循环 languages ["Regional Assembly Language","Autocode","FORTRAN","IPL (LISP的先驱)","FLOW-MATIC (COBOL的先驱)","COMTRAN (COBOL的先驱)","LISP","ALGOL 58","F…...

Day03 左侧菜单数据绑定

一.左侧菜单数据绑定 1.首先&#xff0c;进行项目结构塔建。按照Prism 框架约定&#xff0c;要使用自动查找绑定功能。即View &#xff08;视图&#xff09;中自动查找并绑定到对应的ViewModel&#xff08;视图模型&#xff0c;处理视图业务逻辑&#xff09;。就需要在项目中按…...

JavaScript笔记三-JavaScript常用对象

1、数字对象&#xff08;Number&#xff09; 1.1 、属性 属性描述Number.MAX_VALUEJavaScript 中所能表示的最大值Number.MIN_VALUEJavaScript 中所能表示的最小值Number.NaN非数字Number.NEGATIVE_INFINITY负无穷&#xff0c;在溢出时返回Number.POSITIVE_INFINITY正无穷&am…...

最新的CleanMyMac X4.15.4中文破解版新功能介绍及CleanMyMac 安装激活指南

知名的Mac系统清理软件CleanMyMac发布了最新的CleanMyMac X4.15.4&#xff0c;更换了矩形图标&#xff0c;更好的融合和兼容macOS Snoma系统。新版CleanMyMac 支持Intel芯片和苹果M1/M2芯片的Mac。 优化 Mac 电脑&#xff0c;用 CleanMyMac X4.15.4中文版 就够了&#xff01;强…...

密文域可逆信息隐藏安全性研究-从图像到视频

前言 随着云存储、云计算等新兴技术的兴起&#xff0c;海量的隐私信息被广泛地上传、存储到服务器上。为保证用户的隐私性&#xff0c;必须对用户的数据进行加密&#xff0c;然后再将其上传到服务器上。因此&#xff0c;密文域的可逆信息隐藏(reversible data hiding in encry…...

使用Python进行图像锐化的4个基础操作

想要让你的照片从模糊变锐利&#xff0c;就像魔法师轻轻一挥魔杖&#xff1f;今天我们就来学习如何用Python施加这神奇的“锐化滤镜”&#xff01;&#x1f389; 首先&#xff0c;你需要一位得力助手——Pillow库&#xff0c;它能让我们轻松处理图像。如果你还没安装&#xff…...

图解 Python 编程(9) | 模块和包

&#x1f31e;欢迎来到Python的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年6月2日&…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...