搞懂MyBatis?这篇文章就够了~

news2024/9/25 19:23:26

哈喽呀~你好呀~欢迎呀~一起来看看这篇宝藏文章吧~

 


目录

1.什么是MyBatis

2.配置MyBatis开发环境 

3.使用MyBatis框架去操作数据库 

3.1 实现MyBatis查询功能.

3.1.1 创建一个接口(该接口一定要加上@Mapper注解):

3.1.2 创建上面接口对应的 xml 文件 (此文件会实现接口中的所有方法):

3.1.3 用单元测试检验所写代码

3.2 实现MyBatis的增删改查功能

3.2.1 条件查询--根据id进行查询

3.2.2 添加

3.2.3 删除

​3.2.4 修改

3.2.5 多表查询

4.参数占位符#{}和${}

4.1 由${}引发的sql注入问题  

4.2 模糊查询

 5.resultType与resultMap

5.1 返回类型:resultType

5.2 返回字典映射:resultMap

 6.动态SQL使用

6.1 <if>标签

6.2 <trim>标签

6.3 <where>标签

6.4 <set>标签

6.5 <foreach>标签


1.什么是MyBatis

MyBatis是一个非常优秀的持久层框架,我们使用这个框架去对数据做持久化时,可以省略几乎所有的JDBC代码以及设置参数和获取结果集的工作.MyBatis可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Object,普通老式对象)。

MyBatis支持自定义SQL、存储过程以及高级映射。简单理解就是,MyBatis是一种能更简单完成程序和数据库交互的工具。也就是说,使用这个框架,我们可以用更简单的操作来完成和数据库的交互

本篇文章主要围绕两个方面来学习MyBatis:

  1. 配置MyBatis开发环境;
  2. 使用MyBatis框架去操作数据库.

2.配置MyBatis开发环境 

 选中Spring Initializr,点击next;

选择Maven项目和8版本的jdk,点击next; 

   添加一些基本的框架支持,如MyBatis框架和数据库驱动等,点击next;

选择存放路径,点击Finish;

  右击项目,添加maven框架支持;

 等待项目加载,直到DemoApplication类上有绿色小三角;

此时项目还不能运行起来,还需要按以下操作来配置数据库的连接信息:

 在resources下创建一个application.yml配置文件,在application.yml配置文件中配置数据库的连接信息以及mybatis的配置文件路径.图中代码如下:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

#配置MyBatis中的XML路径
mybatis:
  #所有关于数据库的操作都在resources/mapper路径下的配置文件中
  mapper-locations: classpath:mapper/**Mapper.xml   #**Mapper.xml中存放的是sql操作语句

此时启动项目,项目就可以正常跑起来了.如下图:

至此,我的这个MyBatis开发环境的搭建就完成了~

3.使用MyBatis框架去操作数据库 

要想使用用MyBatis框架来操作管理数据库,我们首先要知道MyBatis的组成,主要为以下 2 点:

  1. 接口:包含了当前类所有声明的方法(方法定义).
  2. xxx.xml:与接口一一对应,包含接口的具体实现操作(方法实现).

为什么主要由这两部分呢?我们先来看一下以下这张图:

要知道,控制器层调用服务层,服务层调用数据持久层.而服务层调用数据持久层主要就是调用数据持久层所提供的接口,而接口具体的实现在其对应的XXX.xml配置文件中.可以理解为接口是对外的,XXX.xml是对内的.所以我们说构成数据持久层的主要是接口和其对应的XXX.xml文件这两部分.因此,我们要做好对数据的持久化处理就需要按照规定的模式来完成好这两部分.

现在我将通过代码来进行更细致的讲解.

以下为准备工作:

我先在数据库mycnblog中建以下这张表,以便于我后续的讲解(后续的操作都是基于此表的):

use mycnblog;

-- 创建文章表
drop table if exists  userinfo;
create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime datetime default now(),
    updatetime datetime default now(),
    `state` int default 1
) default charset 'utf8mb4';

-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES 
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);

然后,我需要先创建一个普通的实体类,用于MyBatis 做以上这张数据库表的映射.需要注意,实体类的属性名要与数据库表的字段完全一致.代码如下:

package com.example.demo.model;

import lombok.Data;

import java.util.Date;
@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private Date createtime;
    private Date updatetime;
    private int state;
}

3.1 实现MyBatis查询功能.

3.1.1 创建一个接口(该接口一定要加上@Mapper注解):

 3.1.2 创建上面接口对应的 xml 文件 (此文件会实现接口中的所有方法):

在此xml文件中完成我们的具体操作:

(以下代码为mybatis的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>

以下为具体的查询操作: 至此,查询功能就完成啦,是不是很简单呢,其实主要就是完成接口和配置文件xml.

3.1.3 用单元测试检验所写代码

虽然理论上完成了查询操作,但是我们还是来检验一下代码是否达到了我们的预期.

右击要测试的模块,选择Generate,然后选择Test,接着勾选你要测试的方法.操作如下: 

 完成以上操作之后,会自动在test目录下生成一个测试类:

接着我们就可以在该类中写测试代码了:

我们来运行一下这个类,结果如下:

 成功的查询出了数据库表的数据,测试验证成功. 

大致知道怎么使用MyBatis框架之后,我们再来写几个例子加深一下对MyBatis的用法.

3.2 实现MyBatis的增删改查功能

3.2.1 条件查询--根据id进行查询

3.2.2 添加

我们现在来实现文章的添加.所以我们要先做一下准备工作:在数据库mycnblog下建一份文章表(articleinfo)和写一个映射于这张表的实体类.具体代码如下:

use mycnblog;

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
    id int primary key auto_increment,
    title varchar(100) not null,
    content text not null,
    createtime datetime default now(),
    updatetime datetime default now(),
    uid int not null,
    rcount int not null default 1,
    `state` int default 1
)default charset 'utf8mb4';


 

 接下来就是实行添加操作的具体步骤了:

 1).新建一个接口:

 2).创建接口对应的xml文件:

这样就完成文章的添加了. 

MyBatis添加---得到添加文章的自增id:

3.2.3  删除

 3.2.4 修改

3.2.5 多表查询

要求:查询文章的作者

1).在ArticleInfo实体类中添加name属性

 2).在接口中添加相应方法:

3) 在xml配置文件中添加具体操作:

如果还想查询其他字段的haul,直接在类里面添加相应的属性即可.  

到这里,关于数据持久层的一系列操作就差不多了.


以上只是在实现数据持久层的操作,接下来我将站在项目的角度上,一层调用一层,来实现触发数据持久层的操作,我们再来回顾一下一个普通项目的分层调用:

通过以上图我们可以发现,Service层是调用Mapper层,现在有了Mapper层,所以我们来创建一个Service层,通过service来调用mapper,代码如下:

接着,Controller层调用Service层,我们再来创建一个Controller层,用来调用Service层,代码如下:

这样我们的一整个的调用关系就补充完整了.

当我们在游览器中输入 localhost:8080/user/getall 时,就可以查询到用户的所有信息了,结果如下:

4.参数占位符#{}和${}

在上面有讲到,当我们通过id来查询用户时,参数id的值是通过参数占位符#{}来获取的,比如以下:

但是在这里,我们也可以用${}.比如这样:

那#{}和#{}的区别究竟是什么呢?我们来看.

  • #{}:预编译处理,即MyBtais在处理#{}时,会将SQL中的#{}替换成?,使用PreparedStatement的set方法来赋值.
  • ${}:字符直接替换,即MyBatis在处理${}时,就是把${}替换成变量的值.

故示例代码中的 select * from userinfo where id=#{uid} ,如果传的uid为1,则在编译后就变成了: select * from userinfo where id='1';而 select * from userinfo where id=${uid}会被直接替换为:select * from userinfo where id=1.这两条sql语句都是对的,所以在上述例子中项目没有出现错误.

但是试想一下,如果传的参数为String类型的呢?比如这样:

select * from userinfo where name=#{name}

select * from userinfo where name=${name}

如果传过来的name参数的值为张三,则最后这两条sql语句会被分别编译为:

select * from userinfo where name='张三'

select * from userinfo where name=张三

很显然,使用${}的这条sql语句就出现问题了,正确写法应该是select * from userinfo where name='张三'.所以在某些情况下#{}和${}是不能随便乱用的.

${}往往用于关键字的替换.比如使用${sort}可以实现排序查询,而如果用#{sort}查询,当传递的值为String时,就会加上单引号'',从而导致sql错误.

4.1 由${}引发的sql注入问题  

${}采用的是参数直接替换.如果参数直接替换,会存在这样的情况:

比如我现在需要这样的一条sql语句来查询一些信息:

select * from userinfo where username='admin' and password='admin';

如果数据库中有这样的数据的话,就会被查询出来.

但是因为${}是直接替换,所以当我传入这样的参数:''or 1='1',直接替换后,sql语句就变成了:

select * from userinfo where username='admin' and password='' or 1='1';

仔细看一下,不管username和password是否正确,这条语句可以实现所有的查询,这就是sql注入.

它的查询条件只要满足username='admin' and password=''为真,或者1='1'为真即可,而1='1'恒为真.也就是说不管前面的username='admin' and password=''是否为真,我都可以查询出来.试想一下,不需要用户名和密码就可以查询出数据库信息,是不是很可怕.这很显然是利用了sql语句的特点而做出的非法行为.因为${}是直接替换的,所以会有sql注入的隐患,是不安全的.而#{}采用的是预处理,是安全的,这也是二者最大的区别.

4.2 模糊查询

以下是错误写法:

因为用的是#{},会自动加上单引号''.所以相当于: 

select * from userinfo where username like '%'username'%'

很显然这是错误的.虽然${}是直接替换,不会加引号,在这里确实也可被查询出来,但是不建议用,因为当参数直接替换容易引起sql注入,存在安全隐患.${}往往用来占位sql中本就存在的关键字的.比如升序,降序等.所以在模糊查询中,我们可以考虑使⽤ mysql 的内置函数 concat() 来处理,实现代码如下:

 5.resultType与resultMap

不知道你有没有发现,我的xml配置文件中的<select>查询标签至少需要 2 个属性:

  • id属性:用于标识实现接口中的方法;
  • 结果映射属性:返回值的类型(全路径).

结果映射有两种实现标签:<resultMap>和<resultType>.

5.1 返回类型:resultType

使用场景:

  • 绝大数查询场景可以使用 resultType返回,但是数据库表的字段和实体类的属性名必须完全一样.

优点:使用简单.

5.2 返回字典映射:resultMap

使用场景:

  • 数据库表的字段和实体类的属性名不同时,可使⽤ resultMap 配置映射;
  • ⼀对⼀和⼀对多关系可以使⽤ resultMap 映射并查询数据(多表查询)。

当字段名和属性名不一样时:

可以在xml文件中使用resultMap这样配置:

分析:

 这样使用resultMap就解决了属性名与字段不一致的问题了

 6.动态SQL使用

动态 sql 是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接。

6.1 <if>标签

有的注册网站在注册用户时,有为两种字段:必填字段和⾮必填字段,那如果在添加⽤户的时候有不确定的字段传⼊,程序应该如何实现呢,一一枚举出来吗?很显然不现实.

此时就需要使⽤动态标签 <if> 来判断了,⽐如添加的时候性别 sex 为⾮必填字段,具体实现如下:

比如我现在要添加用户,但是头像photo为非必填项目,所以对于后端来说,不知道前端是否传photo参数,那么就可以对应的xml中这么来写:

注意:test中的photo是传入对象中的属性名,不是数据库字段名。

6.2 <trim>标签

上面的插入用户,只有一个非必填字段.但是当插入的用户有多个非必填字段时,光靠<if>标签就不好写了,会因为逗号'","的拼接导致sql语句报错.这时候我们就需要同时使用<if>标签和<trim>标签了.

<trim>标签中有如下属性:

  • prefix:表示整个语句块要以prefix的值作为前缀
  • suffix:表示整个语句块要以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除掉的前缀
  • suffixOverrides:表示整个语句块要去除掉的后缀

示例:

分析:

在以上 sql 动态解析时,会将第⼀个 <trim> 部分做如下处理:
基于 prefix 配置,开始部分加上"(";
基于 suffix 配置,结束部分加上 ")";
基于 suffixOverrides 配置,会去掉语句块中的最后⼀个 ",";

这样我们sql最终的拼接就不会报错了.

6.3 <where>标签

做条件查询时,会用到where关键字.因为后端不能保证前端一定按照后端写的来传入相应的参数进行查询,所以我们要用到<where>标签.

示例:

分析:使用<where>标签时,会根据标签内的内容判断是否在语句最前面加上"where",并且去掉第一个"and".

聪明的小伙伴可能发现了,<where>标签可以用<trim prefix="where" prefixOverrides="and">来代替.

6.4 <set>标签

set关键字用于sql语句中的更新操作.

示例:

分析:它的用法和<where>标签基本一样.使用<set>标签时,会根据标签内的内容判断是否在语句最前面加上"set",并且去掉最后一个","

<set>标签也可以使⽤ <trim prefix="set" suffixOverrides=","> 替换

6.5 <foreach>标签

对集合进行遍历时可以使用该标签.<foreach>标签有如下属性:

  • controller:绑定方法中的参数.如List,Set或数组等.
  • item:遍历时的每⼀个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符
  • separator:集合中每个元素之间间隔的字符串

示例:

 


好啦,到这里就结束啦, 这是MyBatis官网:mybatis – MyBatis 3 | 简介,还想了解更多关于MyBatis的,可以去看官网上的解释哈~

咱们下期见~

 

 


 

 


 

.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

易基因|METTL3 通过调节m6A 修饰抑制口腔鳞状细胞癌安罗替尼敏感性| 肿瘤研究

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。2022年9月27日&#xff0c;中山大学附属第一医院口腔颌面外科王安训和何倩婷课题组在《Cancer Cell International》杂志发表了《METTL3 suppresses anlotinib sensitivity by regulating …

Tomcat弱口令+后端getshell漏洞

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是Tomcat弱口令后端getshell漏洞。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁…

指针进阶之数组指针和指针数组

文章目录一、指针数组1.概念2.用法&#xff08;1&#xff09;案例一&#xff08;2&#xff09;案例二二、数组指针1.概念&#xff08;1&#xff09;引子&#xff08;2&#xff09;写法&#xff08;3&#xff09;辨析&#xff08;4&#xff09;总结&#xff08;5&#xff09;案例…

ThreeJS—OrbitControls使其控制模型而不是场景

转载核心代码 项目场景&#xff1a; 来公司之前公司有一个地球组件&#xff0c;大概是张这个样子的⬇️&#xff0c;会转有飞线&#xff0c;有城市涟漪&#xff0c;很炫酷。可惜不是我做的。 一个大屏项目上需要额外增加一些需求 转动到某一城市&#xff0c;暂停转动&#…

K8S Pod 基本使用

K8S Pod 基本使用 Pod基本概念 Pods是在Kubernetes集群中创建和管理最小的部署单元&#xff0c;一个Pod内部可以运行一个或多个容器&#xff0c;多个容器之间具共享的存储和网络资源&#xff0c;共享运行上下文。Pod共享运行时上下文是通过linux 命名空间实现&#xff0c;不同…

项目管理工具dhtmlxGantt甘特图入门教程(五):甘特图实例特点

DHTMLX专注于JavaScript和HTML5 UI小部件和库&#xff0c;以帮助开发人员更快地构建功能丰富的、交互式的Web界面。 遵循现代网络开发的标准和做法&#xff0c;DHTMLX提供针对桌面和移动设备定制的顶级Web应用程序框架。 本文重点介绍使用Gantt Instance的主要功能。 DhtmlxG…

springBoot集成阿里云短信

第一步导入依赖 <dependencies><dependency><groupId>com.atguigu</groupId><artifactId>service-base</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springfram…

【3】SCI易中期刊推荐——人工智能领域(中科院1区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

百货商场用户画像描绘与价值分析在线实习项目

通过实习可以让学生通过实践进行检验&#xff0c;它是衔接学生在校学习与步入社会两个阶段的重要桥梁。一个好的实习机会可以帮助学生积累工作经验&#xff0c;验证职业宣传同时提升综合素质。 在线实习项目重点是让学生巩固并拓展已学到的数据分析理论知识&#xff0c;对…

【无标题】测试开发 | TestNG 与 Junit 对比,测试框架如何选择?

TestNG 和 Junit 作为两大流行的测试框架&#xff0c;有哪些区别&#xff1f;各有哪些优缺点&#xff1f;该如何选择呢&#xff1f;这里简要总结下&#xff1a; 1. Junit 更适合隔离性比较强的单元测试&#xff1b; 2. TestNG 是比 Junit 涵盖功能更全面的测试框架&#xff0c…

【自学Java】Java for循环

Java for循环 Java for循环 在 Java 语言 中&#xff0c;关键字 for 用来操作已经知道了循环次数的循环操作&#xff0c;前面我们介绍过 while 和 do while 循环控制&#xff0c;他们一般情况下用于循环次数不知道的情况下。 Java for语句详解 语法 for(赋值初值 : 判断条…

第七章:使用Netlify零成本部署组件文档

第七章&#xff1a;使用Netlify无成本发布组件文档 为什么使用Netlify&#xff1f; 一开始一共有三个方案&#xff1a; 1、Github Page 2、Netlify 3、Vercel Github Page只支持一个repo发布一个网站&#xff0c;而我们的项目是一个mononrepo项目&#xff0c;后续可能还有其他…

数字转汉字支持负数和小数

private static String numToChinese(String str) {if(strnull)return null;boolean isPositivetrue;//判断是不是负数if(str.charAt(0)-)isPositivefalse;StringBuffer sbnew StringBuffer();if(!isPositive)sb.append("负");//整数部分和小数部分&#xff08;如果有…

2023年1月实时获取地图边界数据方法,省市区县多级联动【附区县乡镇街道geoJson文件下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

QT 学习笔记(十三)

文章目录一、QDataStream 二进制文件读写1. QDataStream 简介2. QDataStream 实际演示2.1 QDataStream 读写文件操作2.2 实现代码——主窗口头文件 widget.h2.3 实现代码——主窗口源文件 widget.cpp二、QTextStream 文本文件读写1. QTextStream 简介2. QTextStream 实际演示2.…

【王道操作系统】3.2.3 页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法)

页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法) 文章目录页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法)1.最佳置换算法---OPT2.先进先出置换算…

[安洵杯 2019]不是文件上传(文件名不能用“,数据库可识别hex编码)

打开题目尝试上传文件发现只能上传图片&#xff0c;然后看见了图片的路径&#xff0c;但是图片码连不上蚁键&#xff0c;结合题目&#xff0c;然后看到了题目给出的github源码 <?php include("./helper.php"); $show new show(); if($_GET["delete_all&qu…

STS安装,SVN配置及WEB工程配置简单说明_1.0.0

Spring Tool Suite构建java web项目概述1, 下载安装Spring Tool Suite Spring Tool Suite 简称为sts, 为构建基于Spring企业应用&#xff0c;提供了最好的Eclipse开发环境。STS 提供了最新基于Java和Spring应用所需要的所有工具,STS官网主页地址为http://spring.io/tools/sts/,…

画布创作,签名大致就是起笔落笔

画布创作&#xff0c;签名大致就是起笔落笔 前言 在画布创作过程中&#xff0c;签名手的基本形态是&#xff0c;不停的点、划。 就像我们写字一样&#xff0c;字越写越大&#xff0c;但是我们不知道笔画的大小。 一个字是一个非常小的点、横&#xff0c;一个横就把这个字给分…

JVM学习(一):简单聊聊性能调优这门艺术

一、性能调优背景说明1.1 生产环境中的问题生产环境发生了内存溢出该如何处理&#xff1f;生产环境应该给服务器分配多少内存合适&#xff1f;如何对垃圾回收器的性能进行调优&#xff1f;生产环境CPU负载飙高该如何处理&#xff1f;生产环境应该给应用分配多少线程合适&#x…