1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 搞懂MyBatis?这篇文章就够了~

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

时间:2018-11-04 01:30:50

相关推荐

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

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

目录

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:

配置MyBatis开发环境;使用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=falseusername: rootpassword: 123456driver-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 点:

接口:包含了当前类所有声明的方法(方法定义).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', '', '-12-06 17:10:48', '-12-06 17:10:48', 1);

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

package com.example.demo.model;import lombok.Data;import java.util.Date;@Datapublic 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 "-////DTD Mapper 3.0//EN" "/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的,可以去看官网上的解释哈~

咱们下期见~

.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。