MyBatis(二)

文章目录

  • 一.MyBatis的模式开发
    • [1.1 定义数据表和实体类](#1.1 定义数据表和实体类)
    • [1.2 配置数据源和MyBatis](#1.2 配置数据源和MyBatis)
    • [1.3 编写Mapper接口和增加xxxMapper.xml](#1.3 编写Mapper接口和增加xxxMapper.xml)
    • [1.4 测试我们功能的是否实现.](#1.4 测试我们功能的是否实现.)
  • [二. Mybatis的增删查改操作](#二. Mybatis的增删查改操作)
  • [2.1 单表查询](#2.1 单表查询)
  • [2.2 多表查询](#2.2 多表查询)
  • 三.动态SQL的实现

一.MyBatis的模式开发

我们在开始MyBatis模式开发之前,我们首先来了解一下mybaits在整个框架的定位.看下图可知

MyBatis 也是一个ORM框架,ORM(Object Relational Mapping) ,即对象关系映射 。在面向对象编程语言中,将关系型数据库中的数据与对象建立起映射关系,进而自动的完成数据与对象的互相转换:

1.将输入数据(即传入对象)+SQL映射成原生SQL

2.将结果集映射为返回对象,即输出对象

也就是说使⽤ MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间

的转换,接下来我们来看 MyBatis 的使⽤吧.

使用过程中,还需要按照后端工程师的思路,来实现查询所有用户的功能.

1.1 定义数据表和实体类

创建数据表

java 复制代码
 CREATE TABLE `userinfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL,
  `password` varchar(32) NOT NULL,
  `photo` varchar(500) DEFAULT '',
  `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `state` int(11) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

创建实体类

java 复制代码
@Data
public class UserEntity {
    private Integer id;
    private String username;
    private String pwd;
    private String photo;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

1.2 配置数据源和MyBatis

在application.properties中配置以下内容

bash 复制代码
# mysql的配置文件
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
driver.class.driver-class-name=com.mysql.jdbc.Driver

#配置 MyBatis 中的 XML 路径
# 1.保存路径 2.xml格式
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml

1.3 编写Mapper接口和增加xxxMapper.xml

我们现来实现查询所有用户的功能.

定义接口UserMapper接口:

@Mapper注解代表一个Mapper

java 复制代码
@Mapper
public interface UserMapper {
 public List<UserEntity> getAll();}

定义UserMapper.xml文件

bash 复制代码
<?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.entity.UserEntity">
        select*from userinfo
    </select>
</mapper>

针对以上标签进行说明

标签:需要指定namespace 属性,表示命名空间,值为 mapper接口的全限定名,包括全包名.类名。

查询标签:是用来执行数据库的查询操作的:
id :是和Interface (接口)中定义的方法名称一样的,表示对接口的具体实现方法。
resultType:是返回的数据类型,也就是开头我们定义的实体类。

1.4 测试我们功能的是否实现.

我们会引入一个单元测试的概念,我们每实现一个功能没必要,都要去启动项目,然后去验证,这时候我们就可以启动单元测试.

在springboot中启动单元测试也是比较简单的事情,具体的步骤如下:

  1. 在要测试的类上石健Generate...

  2. 在测试方法中加上@SpringBootTest注解

    直接执行此方法,得出查询结果.

二. Mybatis的增删查改操作

我们在知道了基本的Mybatis的流程,我们来进行基本的增删改查操作

2.1 单表查询

UserMapper接口文件

java 复制代码
 //根据id查询对象
    UserEntity getUserById(@Param("id") Integer id);
    //根据名称查询用户对象
    UserEntity getUseByUserName(@Param("username")String username);
    // 登录方法
    UserEntity login(UserEntity user);
    // 修改密码
    int updatePassword(@Param("id") Integer id,
                       @Param("password") String password,
                       @Param("newpassword") String newPassword);
    //删除操作
    int delById(@Param("id") Integer id);
    //增加用户
    int addUser(UserEntity user);
    //得到用户id
    int addUserGetID(UserEntity user);

    //根据用户模糊查询
    List<UserEntity> getListByName(@Param("username")String username);

Usermapper.xml文件

bash 复制代码
    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id=#{id}
    </select>
    <select id="getUseByUserName" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username=${username}
    </select>
    <select id="login" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where username= '${username}' and password= '${password}'
    </select>
    <update id="updatePassword">
        update userinfo set password=#{newpassword}
        where id = #{id} and password=#{password}
    </update>
    <delete id="delById">
        delete from userinfo where id=#{id}
    </delete>
    <insert id="addUser">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>
    <insert id="addUserGetID" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo(username,password) values(#{username},#{password})
    </insert>
    <select id="getListByName" resultMap="BaseMap">
        select id,username,password as pwd from userinfo where username like concat('%',#{username},'%')
    </select>

这上面有参数占位符,具体的解释如下;

bash 复制代码
#预编译处理。
$:字符直接替换。
预编译处理是指:MyBatis在处理f时,会将SQL 中的州替换为?号,使用PreparedStatement的set方法来赋值。
直接替换:是MyBatis 在处理$时,就是把$替换成变量的值。

这里来说明一下预编译处理和字符串直接替换

预编译处理(Prepared Statement)和字符串替换(String Replacement)是两种不同的数据库查询参数传递方式,它们在性能和安全性方面有着明显的区别。

预编译处理(Prepared Statement):

预编译处理是一种参数化查询的方式,在查询语句中使用占位符(通常是问号 "?")来表示参数。

在执行预编译处理时,数据库会将SQL语句和参数分开处理,首先将SQL语句编译成一个准备好的查询模板,然后再将参数传递到模板中执行。

预编译处理将SQL语句与参数分开,因此能够有效地防止SQL注入攻击,提高了查询性能和安全性。

由于数据库在执行查询前已经对SQL语句进行了编译,所以对于多次执行相同查询但参数不同的情况,预编译处理能够提高性能,因为数据库可以重复使用相同的查询模板。
字符串替换(String Replacement):

字符串替换是一种直接将参数值嵌入到SQL语句中的方式。在查询语句中,直接将参数值拼接到SQL语句中的相应位置。

字符串替换的查询方式容易受到SQL注入攻击,因为恶意用户可以在参数值中插入恶意的SQL代码,破坏数据库或获取敏感数据。

由于字符串替换是每次执行查询都会生成一个新的SQL语句,所以对于相同查询的多次执行,每次都需要重新编译和执行,性能相对较低。

具体来说的话,我们来看下面的图示:

不知道大家注意到没有.上面的字符串替换,为什么会出现SQL注入问题,这里我用一张图给大家去解释

2.2 多表查询

在进行多表联查之前,我们还需要准备一个文章表

java 复制代码
 CREATE TABLE `articleinfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `uid` int(11) NOT NULL,
  `rcount` int(11) NOT NULL DEFAULT '1',
  `state` int(11) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 |

插入了几条数据:

文章表的内容:

用户表的内容:

多表查询的接口类如下:

java 复制代码
@Mapper
public interface ArticleMapper {
    //查询文章详情 一对一,一篇文章最多有一个作者
    ArticleInfoVO getDetail(@Param("id") Integer id);
    List<ArticleInfoVO> getArticleByUid(@Param("uid") Integer uid);

}

配置文件如下:

java 复制代码
  <select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id=a.uid
        where a.id=#{id}
    </select>
    <select id="getArticleByUid" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select a.* ,u.username from articleinfo a
        left join userinfo u on u.id = a.uid
        where a.uid=#{uid}
    </select>

三.动态SQL的实现

3.1 什么是动态SQL

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

当然官网对其的解释入下:

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

3.2 动态SQL的使用

if标签的使用

if标签用于在SQL语句中根据条件判断是否包含某个SQL片段。语法如下:

java 复制代码
<select id="getUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

在上面的例子中,根据传入的name和age参数的值,如果它们不为空,就会拼接对应的SQL条件,实现动态的查询语句。

trim标签的使用

trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,以避免不必要的SQL语法错误。trim标签还可以根据条件去除WHERE或AND等关键字,以确保动态SQL的正确性。

trim标签中有如下属性:

prefix:表示整个语句块,以prefix的值作为前缀

suffix:表示整个语句块,以suffix的值作为后缀.

prefixOverrides:表示整个语句块要去除掉的前缀.

suffixOverrides:表示整个语句块要去除掉的后缀

java 复制代码
<select id="getUsers" resultType="User">
  SELECT * FROM users
  <trim prefix="WHERE" prefixOverrides="AND | OR">
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
    <if test="gender != null">
      AND gender = #{gender}
    </if>
  </trim>
</select>

在上面的例子中,我们使用了trim标签来包裹if标签,prefix属性指定了在条件满足时在WHERE关键字之前添加"WHERE",prefixOverrides属性指定了当条件不满足时去除多余的"AND "或"OR "。

where标签的使用

where标签用于在SQL语句中包含WHERE子句,并根据条件动态拼接查询条件。

java 复制代码
<select id="getUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

set标签的使用

根据传⼊的⽤户对象属性来更新⽤户数据,可以使⽤标签来指定动态内容。

UserMapper 接⼝中修改⽤户⽅法:根据传⼊的⽤户 id 属性,修改其他不为 null 的属性:

java 复制代码
<update id="updateUser" parameterType="User">
  UPDATE users
  <set>
    <if test="name != null">
      name = #{name},
    </if>
    <if test="age != null">
      age = #{age},
    </if>
  </set>
  WHERE id = #{id}
</update>

foreach标签的使用

foreach的属性如下所示:

collection:绑定方法参数中的集合,如List,Set,Map或数组对象item:遍历时的每一个对象

open:语句块开头的字符串close:语句块结束的字符串

separator:每次遍历之间间隔的字符串

foreach标签用于在SQL语句中遍历集合,生成对应的SQL片段。它常用于批量插入或更新操作。

java 复制代码
 <delete id="delByIdList">
        <!--        where id in(1,2..)-->
        delete from articleinfo
        where id in
        <foreach collection="idList" item="aid" open="(" close=")" separator=",">
            #{aid}
        </foreach>
    </delete>

这上面生成的语句,入下所示

delete from articleinfo where id in (1, 2, 3)

3.3 综合练习

在我们了解了基本的动态SQL标签之后,我们来一个综合的练习.

假设我们假如我们传入的参数都是非必须的.我们怎么才能完成SQL的拼接.

SQL如下:
select * from articleinfo WHERE id=? and title like concat('%',?,'%')

我们传入参数的情况如下:

1.传入id,不传入title

2.传入title,不传入id

3.两个都不传

动态SQL的拼接策略如下:

方案一:

java 复制代码
 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select * from articleinfo
        where 1=1 
        <trim prefixOVerrides="and">
            <if test="id!=null and id>0">
               and id=#{id}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
        </trim>
    </select>

trim prefixOVerrides="and": 这是MyBatis的动态SQL标签trim的使用。trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,并可以根据条件去除特定的关键字,如这里的and。prefixOverrides属性指定了当条件不满足时去除的前缀关键字,这里是and,表示如果条件不满足,就去除SQL语句中多余的and关键字。

方案二:

java 复制代码
 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select * from articleinfo
       <trim prefix ="where" suffixOverrides="and">
            <if test="id!=null and id>0">
                id=#{id}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
        </trim>
    </select>

中间解释:
trim prefix="where" suffixOverrides="and"> : 这是MyBatis的动态SQL标签trim的使用。trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,并可以根据条件去除特定的关键字,如这里的and。prefix属性指定了在条件满足时在WHERE关键字之前添加"where",suffixOverrides属性指定了当条件不满足时去除SQL语句中多余的"and"。
方案三:

java 复制代码
 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
        select * from articleinfo
        <where>
            <if test="id!=null and id>0">
                id=#{id}
            </if>
            <if test="title!=null and title!=''">
                and title like concat('%',#{title},'%')
            </if>
        </where>
    </select>

where标签: 这是MyBatis的动态SQL标签的使用。where标签的作用是将包含在其中的条件片段包裹在WHERE子句中,如果条件满足,WHERE关键字和多余的AND或OR将会被自动添加,如果条件不满足,则WHERE关键字也不会出现在最终的查询语句中

相关推荐
wljt12 小时前
公司二-面试题
java·开发语言·mybatis
VimorphTech15 小时前
文本已经改了,旧的音频生成结果还能回写吗?
java·数据库·mybatis
麻瓜code20 小时前
双写一致性:为什么是“删缓存“,而不是“改缓存“
java·缓存·mybatis
郭小李2 天前
mybatis 动态 sql
java·sql·mybatis
知守观2 天前
技术考古:iBATIS 2.3.4 时代的持久层,是如何用 Map 玩转 307 个存储过程的?
java·后端·mybatis
captain3762 天前
MyBatis Plus(1)
java·服务器·mybatis
代码不停2 天前
MyBatis进阶
spring boot·mybatis
captain3762 天前
MyBatis(入门5)其他查询操作
java·数据库·spring boot·mybatis
captain3762 天前
MyBatis(进阶1)
mybatis
郭小李3 天前
mybatis的 Mapper.xml语法
xml·java·mybatis