【SSM】MyBatis 操作数据库(重点:Mybatis两种使用方式)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 本文重点介绍ORM 框架和Mybatis的关系、如何通过注解 或者 通过XML配置文件的使用Mybatis,以及参数占位符 #{} 和 ${} 的区别, 什么是sql 注入。

【大家好,我是爱干饭的猿,本文重点介绍ORM 框架和Mybatis的关系、如何通过注解 或者 通过XML配置文件的使用Mybatis,以及参数占位符 #{} 和 ${} 的区别, 什么是sql 注入。

后续会继续分享其他重要知识点总结,如果喜欢这篇文章,点个赞👍,关注一下吧】

上一篇文章:《【SSM】Spring AOP 统一问题处理(重点:Spring AOP 实现原理)》


🤞目录🤞

🎁1.MyBatis 是什么?

🎁2. 什么是ORM框架?

🎁3. MyBatis 的使用

3.1 添加MyBatis框架支持

1. 新项目添加MyBatis框架

2. 旧项目添加MyBatis框架

3.2 配置连接字符串和MyBatis

1. 配置连接字符串

2. 配置 MyBatis 中的 XML 路径

3.3 通过注解使用Mybatis

1. 查询

2. 插入

3. 修改

4. 删除

5. 总览(增删查改)

3.4 通过XML配置文件的形式使用Mybatis

0. 关于resultMap

1. 查询

2. 插入

3. 修改

4. 删除

5. 总览(增删查改)

3.5 参数占位符 #{} 和 ${} 和 sql 注入


🎁1.MyBatis 是什么?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获 取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

简单来说 MyBatis 是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具。

🎁2. 什么是ORM框架?

ORM 把数据库映射为对象:

    • 数据库表(table)--> 类(class)
    • 记录(record,行数据)--> 对象(object)
    • 字段(field) --> 对象的属性(attribute)

    一般的 ORM 框架,会将数据库模型的每张表都映射为一个 Java 类。 也就是说使用 MyBatis 可以像操作对象一样来操作数据库中的表,可以实现对象和数据库表之间的转换。

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

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

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

    image.gif编辑

    一些其他框架:

      • Hibernate框架:偏向简化SQL的模式
      • MyBatis框架:偏向ORM的模式
      • Spring 内部提供的JdbcTemplate:偏向简化SQL的模式
      • JPA :完全倒向了ORM的形式,建表的过程都被抽象,我们看到的只有类(我写了类,框架根据类建表)

      🎁3. MyBatis 的使用

      3.1 添加MyBatis框架支持

      1. 新项目添加MyBatis框架

      image.gif编辑

      2. 旧项目添加MyBatis框架

      a. 使用 EditStarters插件

      image.gif编辑

      image.gif编辑b. 手动添加

      <!-- 把 DataSource对象注册到Spring 中-->
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
          </dependency>
          <!-- 添加 mybatis 框架 -->
          <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
          </dependency>
          <!-- 添加 MySQL 驱动 -->
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
          </dependency>

      image.gif

      3.2 配置连接字符串和MyBatis

      此步骤需要进行两项设置,数据库连接字符串设置和 MyBatis 的 XML 文件配置。

      1. 配置连接字符串

      如果是 application.yml 添加如下内容:

      spring:
        datasource:
          url: jdbc:mysql://127.0.0.1:3306/***?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
          username: root
          password: 123456

      image.gif

      2. 配置 MyBatis 中的 XML 路径

      通过XML配置文件的形式使用Mybatis 时需要配置,通过注解使用Mybatis时,不需要配置

      mybatis:
        mapper-locations: classpath:mapper/**.xml

      image.gif

      3.3 通过注解使用Mybatis

      定义Mapper 接口

      @Repository // 消除报错
      @Mapper   // Mapper 注解
      public interface UserMapper {
      }

      image.gif

      1. 查询

      // 1. 查询
          // 1.1 通过uid 查询得到Map对象
          @Select("select uid, username, password from users where uid = #{uid}")
          Map<String, Object> select1(@Param("uid") int uid);
          // 1.2 通过uid 查询得到User类对象
          @Select("select uid, username, password from users where uid = #{uid}")
          UserDO select2(@Param("uid") int uid);

      image.gif

      2. 插入

      // 2. 插入
          // 2.1 插入,返回插入成功的条数
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          int insert1(UserDO userDO);
          // 2.2 由于用不到这个返回值,所以写成 void 更常见
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          void insert2(UserDO userDO);
          // 2.3 插入后拿到自增id
          // 通过 @Options 注解,添加一些配置,得到自增主键,设置成 uid
          // keyProperty : 对象的属性名是 uid
          // keyColumn : 表的字段名的 uid
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          @Options(useGeneratedKeys = true, keyProperty = "uid", keyColumn = "uid")
          void insert3(UserDO userDO);

      image.gif

      3. 修改

      // 3. 修改
          @Update("update users set username = #{username}, password = #{password} where uid = #{uid}")
          int update(UserDO userDO);

      image.gif

      4. 删除

      // 4. 删除
          @Delete("delete from users where uid = #{uid}")
          int delete(@Param("uid") int uid);

      image.gif

      5. 总览(增删查改)

      import org.apache.ibatis.annotations.*;
      import org.springframework.stereotype.Repository;
      import java.util.Map;
      @Repository // 消除报错
      @Mapper   // Mapper 注解
      public interface UserMapper {
          // 1. 查询
          // 1.1 通过uid 查询得到Map对象
          @Select("select uid, username, password from users where uid = #{uid}")
          Map<String, Object> select1(@Param("uid") int uid);
          // 1.2 通过uid 查询得到User类对象
          @Select("select uid, username, password from users where uid = #{uid}")
          UserDO select2(@Param("uid") int uid);
          // 2. 插入
          // 2.1 插入,返回插入成功的条数
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          int insert1(UserDO userDO);
          // 2.2 由于用不到这个返回值,所以写成 void 更常见
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          void insert2(UserDO userDO);
          // 2.3 插入后拿到自增id
          // 通过 @Options 注解,添加一些配置,得到自增主键,设置成 uid
          // keyProperty : 对象的属性名是 uid
          // keyColumn : 表的字段名的 uid
          @Insert("insert into users (username, password) values (#{username}, #{password})")
          @Options(useGeneratedKeys = true, keyProperty = "uid", keyColumn = "uid")
          void insert3(UserDO userDO);
          // 3. 修改
          @Update("update users set username = #{username}, password = #{password} where uid = #{uid}")
          int update(UserDO userDO);
          // 4. 删除
          @Delete("delete from users where uid = #{uid}")
          int delete(@Param("uid") int uid);
      }

      image.gif

      3.4 通过XML配置文件的形式使用Mybatis

      先配置 MyBatis 中的 XML 路径,然后在mapper下 .xml 文件中写

      image.gif编辑

      定义Mapper 接口:

      import org.apache.ibatis.annotations.Mapper;
      import org.apache.ibatis.annotations.Param;
      import org.springframework.stereotype.Repository;
      import java.util.List;
      @Repository
      @Mapper
      public interface UserMapper {
          // 1. 查询
          // 1.1 单个查询
          User selectOneByUid(@Param("uid") int uid);
          // 1.2 多个查询
          List<User> selectListByUidList(@Param("uidList") List<Integer> uidList);
          // 1.3 动态查询
          User selectByUser(@Param("user") User user);
          // 2. 插入
          // 2.1 单个插入
          int insertOneUser(@Param("user") User user);
          // 2.1 批量插入
          int insertBatch(@Param("userList") List<User> userList);
          // 3. 修改
          void update(int uid , String username);
          // 4. 删除
          void delete(int uid);
      }

      image.gif

      0. 关于resultMap

      使用场景:

        • 字段名称和程序中的属性名不同的情况,可使用 resultMap 配置映射;
        • 一对一和一对多关系可以使用 resultMap 映射并查询数据。
        <!-- 返回字典映射-->
            <resultMap id="xxx" type="com.haomin.mybatis_xml.User">
                <id property="uid" javaType="Integer" column="uid" jdbcType="INTEGER" />
                <result property="username" javaType="String" column="username" jdbcType="VARCHAR" />
                <result property="password" column="password" />
            </resultMap>

        image.gif

        image.gif编辑

        1. 查询

        <!-- 1.1 单个查询 -->
            <select id="selectOneByUid" resultType="com.haomin.mybatis_xml.User" parameterType="int">
                select uid, username, password from users where uid = #{uid}
            </select>
            <!-- 1.2 多个查询 -->
            <select id="selectListByUidList" resultMap="xxx" parameterType="List">
                select uid, username, password from users where uid in (
                    <foreach collection="uidList" item="id" separator=", ">
                        #{id}
                    </foreach>
                ) order by uid
            </select>
            <!-- 1.3 动态查询-->
            <select id="selectByUser" resultMap="xxx" parameterType="com.haomin.mybatis_xml.User">
                select uid, username, password from users where
                <if test="user.uid != null">
                    uid = #{user.uid}
                </if>
                <if test="user.username != null">
                    and username = #{user.username}
                </if>
                <if test="user.password != null">
                    and password = #{user.password}
                </if>
            </select>

        image.gif

        2. 插入

        <!-- 2.1 单个插入-->
            <insert id="insertOneUser" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
                insert into users (username, password) values
                (#{user.username}, #{user.password})
            </insert>
            <!-- 2.2 批量插入-->
            <insert id="insertBatch" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
                insert into users (username, password) values
                <foreach collection="userList" item="user" separator=", ">
                    (#{user.username}, #{user.password})
                </foreach>
            </insert>

        image.gif

        3. 修改

        <!-- 3. 修改-->
            <update id="update">
                update users set username = #{username} where uid = #{uid}
            </update>

        image.gif

        4. 删除

        <!-- 4. 删除-->
            <delete id="delete">
                delete from users where uid = #{uid}
            </delete>

        image.gif

        5. 总览(增删查改)

        <?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.haomin.mybatis_xml.UserMapper">
            <!-- 返回字典映射-->
            <resultMap id="xxx" type="com.haomin.mybatis_xml.User">
                <id property="uid" javaType="Integer" column="uid" jdbcType="INTEGER" />
                <result property="username" javaType="String" column="username" jdbcType="VARCHAR" />
                <result property="password" column="password" />
            </resultMap>
            <!-- 1.1 单个查询 -->
            <select id="selectOneByUid" resultType="com.haomin.mybatis_xml.User" parameterType="int">
                select uid, username, password from users where uid = #{uid}
            </select>
            <!-- 1.2 多个查询 -->
            <select id="selectListByUidList" resultMap="xxx" parameterType="List">
                select uid, username, password from users where uid in (
                    <foreach collection="uidList" item="id" separator=", ">
                        #{id}
                    </foreach>
                ) order by uid
            </select>
            <!-- 1.3 动态查询-->
            <select id="selectByUser" resultMap="xxx" parameterType="com.haomin.mybatis_xml.User">
                select uid, username, password from users where
                <if test="user.uid != null">
                    uid = #{user.uid}
                </if>
                <if test="user.username != null">
                    and username = #{user.username}
                </if>
                <if test="user.password != null">
                    and password = #{user.password}
                </if>
            </select>
            <!-- 2.1 单个插入-->
            <insert id="insertOneUser" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
                insert into users (username, password) values
                (#{user.username}, #{user.password})
            </insert>
            <!-- 2.2 批量插入-->
            <insert id="insertBatch" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
                insert into users (username, password) values
                <foreach collection="userList" item="user" separator=", ">
                    (#{user.username}, #{user.password})
                </foreach>
            </insert>
            <!-- 3. 修改-->
            <update id="update">
                update users set username = #{username} where uid = #{uid}
            </update>
            <!-- 4. 删除-->
            <delete id="delete">
                delete from users where uid = #{uid}
            </delete>
        </mapper>

        image.gif

        当然还有更多用法:可以参考 Mybatis 官方文档

        3.5 参数占位符 #{} 和 ${} 和 sql 注入

        #{}:预编译处理。

        ${}:字符直接替换。

        #{}预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使用 PreparedStatement 的 set 方法来赋值,编译后会带上 ‘ ’。

        ${}直接替换:是 MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。

        结论:

          • 用于查询的字段,尽量使用 #{} 预查询的方式,如果用${} 可能会出现sql注入问题。
          • 使用 ${sort} 可以实现排序查询或者分页,而使用 #{sort} 就不能实现排序查询了,因为当使用 #{sort} 查询时,如果传递的值为 String 则会加单引号,就会导致 sql 错误。

          sql 注入代码例子:

          执行:

          select * from userinfo where username = '${name}' and password = '${pwd}'

          image.gif

          当sql 为 : ' or 1=1  时

          执行语句:

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

          image.gif


          当然,Mybatis 还有更多用法:可以参考 Mybatis 官方文档

          分享到此,感谢大家观看!!!

          如果你喜欢这篇文章,请点赞关注吧,或者如果你对文章有什么困惑,可以私信我。

          🏓🏓🏓

          相关实践学习
          如何快速连接云数据库RDS MySQL
          本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
          全面了解阿里云能为你做什么
          阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
          相关文章
          |
          1月前
          |
          SQL Java 数据库连接
          深入 MyBatis-Plus 插件:解锁高级数据库功能
          Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
          230 26
          深入 MyBatis-Plus 插件:解锁高级数据库功能
          |
          1月前
          |
          SQL 安全 Java
          MyBatis-Plus条件构造器:构建安全、高效的数据库查询
          MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
          32 1
          MyBatis-Plus条件构造器:构建安全、高效的数据库查询
          |
          29天前
          |
          SQL Java 数据库连接
          canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
          canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
          |
          2月前
          |
          Java 关系型数据库 MySQL
          springboot学习五:springboot整合Mybatis 连接 mysql数据库
          这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
          239 0
          springboot学习五:springboot整合Mybatis 连接 mysql数据库
          |
          2月前
          |
          前端开发 Java 数据库连接
          表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
          本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
          77 0
          表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
          |
          4月前
          |
          SQL 关系型数据库 MySQL
          解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
          该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
          |
          4月前
          |
          XML SQL JavaScript
          在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作
          这篇文章介绍了如何在Vue页面中结合SpringBoot、MyBatis、ElementUI和ECharts,实现从数据库获取数据并展示为图表的过程,包括前端和后端的代码实现以及遇到的问题和解决方法。
          在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作
          |
          4月前
          |
          druid Java 数据库连接
          SpringBoot项目整合MybatisPlus持久层框架+Druid数据库连接池,以及实现增删改查功能
          SpringBoot项目整合MybatisPlus和Druid数据库连接池,实现基本的增删改查功能。
          396 0
          |
          5月前
          |
          Oracle 关系型数据库 Java
          实时计算 Flink版操作报错合集之cdc postgres数据库,当表行记录修改后报错,该如何修改
          在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
          |
          5月前
          |
          SQL 监控 关系型数据库
          实时计算 Flink版操作报错合集之在设置监控PostgreSQL数据库时,将wal_level设置为logical,出现一些表更新和删除操作报错,怎么办
          在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。