神级框架 - MyBatis【初阶】

news2024/11/19 9:34:08

目录

1. 什么是 MyBatis

2. 如何学习 MyBatis

2.1 搭建 MyBatis 开发环境

2.2 使用 MyBatis 模式和语法操作数据库

2.2.1 MyBatis 的组成

 2.2.2 MyBatis 实现查询功能

 2.2.3 MyBatis 实现新增功能

2.2.3 MyBatis 实现删除功能

2.2.3 MyBatis 实现修改功能

3. 在 MyBatis 的基础上实现程序的完整交互


1. 什么是 MyBatis

MyBatis 是一款神级持久层框架, 它支持自定义 SQL , 存储过程以及高级映射. 简单来说, MyBatis 就是基于 JDBC 做到更简单的完成程序与数据库交互的高级框架. -- MyBatis 官网

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

2. 如何学习 MyBatis

学习 MyBatis 可以分为两个大的方向学习:

  1. 搭建 MyBatis 开发环境
  2. 使用 MyBatis 模式和语法操作数据库

2.1 搭建 MyBatis 开发环境

第一步: 创建一个 Spring Boot 项目, 并添加 MyBatis 框架支持

此时你的程序是不能正常运行的.

第二步: 配置数据库的连接信息

在 resource 目录下创建一个 applicaiton.yml 文件 (根据自己喜好, properties 和 yml 都行)

【注意】如果使用的 mysql-connector-java 是 5.x 系列及以前的就可以使用我上面的驱动, 大于 5.x 系列的就使用 "com.mysql.cj.jdbc.Driver". 

第三步: 配置 MyBatis 的 XML 文件存放位置和命名规则

yml 配置文件中的 MyBatis/**Mapper.xml 的意思是 :

  • 在 resource 下创建一个 MyBatis 目录, 然后所有的 xml 都存放在这个目录下, xml 里面写的就是 SQL 语句. 当然 MyBatis 是我自己取的名字, 这个可以随意命名. 
  • **Mapper.xml 就表示在 Mybatis 目录下创建的 xml 文件的命名要以 Mapper.xml 结尾, 例如 UserMapper.xml

配置 mapper-location 的作用是需要搭配一个注解来说的, 后面会提到.

此时我们的项目就可以正常运行起来了.

2.2 使用 MyBatis 模式和语法操作数据库

2.2.1 MyBatis 的组成

  1. 接口 【当前类的所有方法声明 (CRUD 方法)】
  2. xxxMapper.xml 【CRUD 的 SQL语句】

MyBatis 由接口和 xml 组成, 一个类会有一个接口和一个对应实现相应操作的 xml 文件.

  • 接口中是增、删、改、查等方法的声明, 存在的目的就是给别人调用的.
  • xml 中存放的就是增删改查的 SQL 语句, xml 中的每条 SQL 和接口中的方法一一对应. (sql 如果存写在类中, 需要用双引号引起来, 有时候有变量还需要处理拼接, 太麻烦, 所以存放在 xml 中)

大致流程图: 

 

 2.2.2 MyBatis 实现查询功能

先准备数据 - 建库建表

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
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 userinfo (username,password,photo) 
        values ('李白','123','cat.jpg');

第一步: 创建实体类

@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;
}
  • 实体类是用于 MyBatis 做数据库表的映射的.
  • 要保证实体类中的属性名和数据库表中的字段名一致.

第二步: 创建一个接口

import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;  // MyBatis 以前叫做 ibatis

import java.util.List;


@Mapper // 此注解必不可少, 该注解会将 接口 和 xml 对应起来
public interface UserMapper {
    // 查询
    public List<UserInfo> selectAll();
}

【重点】接口上必须要添加 @Mapper 注解, 此注解的作用:

  • 将当前接口实例化  (后续其它类中需要使用该接口, 只需要注入就行了)
  • 关联接口中的方法和对应 xml 的具体实现 (第三步有详细讲到)

第三步: 创建与接口对应的 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="com.example.demo.mapper.UserMapper">
    
</mapper>

>>> MyBatis 的接口和 xml 是如何关联起来的 ? 【重点理解

1. xml 的创建和命名规则前面在 yml 中已经配置了 (根据自己的配置) , 必须在创建在 MyBatis 文件夹下, 命名要以 Mapper.xml 结尾. 当程序运行的时候, MyBatis 会去找它自己的注解 @Mapper, 然后再根据 yml 文件中配置的路由再去匹配当前接口所有对应的 xml 文件中的具体实现.从而将接口和 xml 关联起来. 这一切的一切都是 MyBatis 去做的, 但是我们必须要遵守规范!!

2. 上面 MyBatis 中的 xml 模板是通用的, 唯独要自己写的地方就是 namespace, namespace 里需要配置当前 xml 要实现的接口的路径, 配置好 xml 时, 此时接口和 xml 就关联上了. 

该路径是: 包名 + 接口名. 如下图:

第四步: 在 xml 中写 SQL 语句 

<?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="selectAll" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
    </select>
</mapper>

1. 查询使用 <select> 标签

  • id 属性上的 selectAll 对应接口中的方法名 【千万不敢写错】
  • resultType 表示查询返回对象的类型 (包名 + 实体类类名)   【千万不敢漏写】

2. <select> 标签写 SQL 语句, 最后的分号可以省略.【建议在 cmd 上执行成功后再复制进来】

>>> SQL 语句是如何将查询结果带回的呢 ? 【重点理解

我们的查询语句首先会从数据库中查到数据, 然后再根据 resultType 去找对应的实体类, 然后通过 setXXX() 方法, 将查到的每条数据的每个字段设置到实体类的每个属性中, 此时数据库中每条记录的值就能够在对应实体类中的属性上体现出来了, 所以 MyBatis 做的事情就是封装了 JDBC 的代码, 然后将数据保存到 List<UserInfo>  里面了, 此时我们在项目中只要实现注入了,  就能够在任何地方拿到查询的结果了.   所以我们一定要保证实体类属性名和数据库中字段名保持一致!!

(如果不一致, 也有解决方法, 下一篇博客会详细讲到).

第五步: 将接口中对应的方法生成 Spring Boot 单元测试

 【单元测试】

单元测试的好处:  以最小成本, 花最短时间去验证我们的程序是否正确.

如何使用单元测试验证程序功能:  

  • 这一步是不需要我们操作的, 因为我们在创建 Spring Boot 项目的时候, 默认会给每个项目都内置单元测试的框架.
  • 在接口中右击选择 Generate -> Test,   然后选中要单元测试的方法,  然后点击 ok, 就会生成如下单元测试类: 

 这时候, 我们还需要做一些事情, 才能测试查询功能是否正确:

1. 对单元测试的类加上 @SpringBootTest 注解, 表示当前测试的上下文环境为 Spring Boot.

2. 注入需要测试的接口, 这里需要测试 UserMapper (属性注入, Setter 注入, 构造方法注入)

3. 在测试方法中使用接口中的方法, 去实现业务逻辑.

4. 点击测试方法左边的三角形, 运行程序, 验证测试结果.

测试结果: 

 对比数据库中的记录, 判断查询结果是否与数据库相匹配:

 发现结果正确, 查询功能实现完成!!!

 

 2.2.3 MyBatis 实现新增功能

此处我们实现新增并得到用户的自增 id 功能,  这个功能实现了, 那么普通的新增功能就更加没问题了, 所以此处就不单独写新增了.

由于我们现在操作的实体类还是 UserInfo,  所以准备工作在前面已经做好了, 现在只需要做三步:

  1. 在 UserMapper 接口中声明新增方法.
  2. 在对应的 xml 中写具体的实现 (写 sql).
  3. 对新增功能进行单元测试.

第一步: 在接口中声明新增方法

public int insert(@Param("userInfo") UserInfo userInfo);

1. 此处的 @Param 注解可加可不加,  加上更加规范.(个人见解)

2. 前面在学习 Spring MVC 的时候, 接受各种参数都已经掌握的差不多了, 所以此处传递对象就不再过多的赘述了.  -- Spring MVC 核心

第二步: 在对应的 xml 中写具体的实现

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into userinfo(username,password,photo)
    values(
        #{userinfo.username},
        #{userinfo.password},
        #{userinfo.photo}
    )
</insert>

对于普通的增 <insert> 删 <delete> 查 <select> 改 <update> , 只有 <select> 标签除了要设置 id 参数, 还要设置 resultType 或 resultMap 参数, 其他三种标签, 只需要设置 id 参数即可, 但是此处属于特殊的新增, 所以需要多设置 useGeneratedKeys 参数和 keyProperty 参数.

  • useGenerateKeys:  设置后会让 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键, 默认值:false.
  • keyProperty: 此处设置的就是数据库中的主键在实体类中对应的属性名.

>>> 当接口中的方法来调用 xml 中的具体实现时, 在 xml 中通过 #{} 的方式获取接口中的参数.

【#{} 注意事项】:

1. 如果传递的是普通参数, 只需将参数名写进 #{} 即可.

2. 如果传递的是对象, 则需要使用 #{对象.属性} 的方式去获取.

3. 如果 @Param 注解中的参数名和接口方法中用来接收参数的变量名不同时, 则 #{} 中的参数需要根据 @param 注解中的参数名相匹配.

如果不使用 @Param 注解, 那么以上注意事项第一条还是一样的, 就不存在第 3  条这样的区别了,  但是第 2 条区别还是挺大的.

对于上面第二条注意事项, 我们看到了加 @Param 注解和不加 @Param 注解, xml 中写法上的区别, 但是又有一个共同点: #{} 中设置的参数都是实体类对应的属性名, 所以此处我们在实体类中设置的属性名和数据库中的字段名不相同都没有关系. 由此得出结论 >>>

  • 实现查询功能的时候, 属性名必须要和字段名相匹配. 因为数据是从数据库中查出来再将字段一一设置到属性上. (此时属性名和数据库中的字段相关)
  • 实现增删改的时候, 属性名不需要和字段名相匹配. 因为增删改是从前端获取到数据再设置到数据库上的字段上. (此时属性名是和前端相关)

但是我们回到 MyBatis ORM (对象关系映射) 框架的初衷上来说, 它实现的功能就是将数据库和程序中的类进行映射, 并且在进行映射的时候就是使用程序中的对象名(属性)和数据库表中的字段名做映射的. 所以一般情况下, 我们应该遵守约定将类中的属性名和表中的字段名全部一一对应上. (当然也有属性名和字段名有时候不相同的特殊情况, 下一篇博客会详细讲解到)

回到我们的新增功能上, 此时我们已经完成两个大的步骤了, 现在只需要生成单元测试, 进行验证我们的新增功能.

第三步: 对新增功能进行单元测试

生成单元测试的步骤还是和查询一样, 就不赘述了. 看代码:

此处 result 接受的是受影响的行数, 获取自增 id , 直接可以从属性中获取.

>>> 为什么我在构造数据的时候没有设置 id, 还能直接调用该对象的 get 方法去拿自增 id 呢?

因为我们在 xml 中设置了开启自增, 并且把返回的结果设置给属性 id, 所以我们在单元测试的时候, 没有设置 id, 调用 getXXX() 方法, 依旧能得到.

执行结果:

查看数据库中是否添加了新的记录:

发现数据成功新增到数据库中, 并且单元测试也拿到了自增 id.

 

2.2.3 MyBatis 实现删除功能

经过查询和新增功能的学习, 那么删除和修改就如鱼得水了. 

删除操作三部曲:

  • 在 UserMapper 接口中声明新增方法.
  • 在对应的 xml 中写具体的实现 (写 sql).
  • 对删除功能进行单元测试.

第一步: 在 UserMapper 接口中声明删除方法.

public int deleteById(@Param("id") Integer id);

第二步: 在对应的 xml 中写具体的实现

<delete id="deleteById">
    delete from userinfo where id=#{id}
</delete>

第三步: 对删除功能进行单元测试

执行结果:

查询数据库中的记录:

 发现 id 为 2 的用户已经删除, 删除功能成功实现.

2.2.3 MyBatis 实现修改功能

修改操作三部曲:

  • 在 UserMapper 接口中声明新增方法.
  • 在对应的 xml 中写具体的实现 (写 sql).
  • 对修改功能进行单元测试.

第一步: 在 UserMapper 接口中声明修改方法.

public int update(@Param("id")Integer id,
                  @Param("password") String password);

第二步: 在对应的 xml 中写具体的实现

<update id="update">
    update userinfo set password=#{password} where id=#{id}
</update>

第三步:  对修改功能进行单元测试.

 执行结果:

查询数据库记录:

发现记录更新成功, 修改操作成功实现.

3. 在 MyBatis 的基础上实现程序的完整交互

我们上面所讲述的都是持久层操作数据库的操作, 还没有提供相应的入口, 算不上一个完整的项目, 一个最小的项目的完整目录都至少分为三层: controller -> service -> Mapper.

接下来, 针对查询功能实现一个简单的交互.  Mapper 层有了, 现在只需要添加 Controller 层和 Service 层了.

  • 第一步: 添加 Service 层
  • 第二步: 添加 Controller 层
  • 第三步: 构造 HTTP 请求

第一步: 添加 Service 层

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    
    public List<UserInfo> selectAll() {
        return userMapper.selectAll();
    }
}

第二步: 添加 Controller 层

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/select")
    public List<UserInfo> selectAll() {
        return userService.selectAll();
    }
}

第三步: 构造 HTTP 请求

此处为了视觉效果, 先在数据库中多添加几条数据.

浏览器输入 URL : http://127.0.0.1:8080/user/select

 发现执行结果和数据库是完全相同的, 到这一步, 我们就已经实现一次完整的交互了.


本篇博客就到这里, 下一篇博客将讲解 MyBatis 中更加进阶一点的知识, 期待大家的关注!!

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

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

相关文章

XC7A50T-1FTG256I、XC6SLX150-2FGG900I嵌入式FPGA 技术参数

XC7A50T-1FTG256I IC FPGA 170 I/O 256FTBGA&#xff08;图左&#xff09; 说明&#xff1a;Artix-7 FPGA能够在多个方面实现更高的性价比&#xff0c;这些方面包括逻辑、信号处理、嵌入式内存、LVDS I/O、内存接口&#xff0c;以及收发器。Artix-7 FPGA非常适合用于需要高端功…

论文阅读笔记 | 三维目标检测——PV-RCNN++算法

如有错误&#xff0c;恳请指出。 文章目录1. 背景2. 网络结构2.1 Sectorized Proposal-Centric SamplingProposal-Centric FilteringSectorized Keypoint Sampling2.2 VectorPool Aggregation3. 实验结果paper&#xff1a;《PV-RCNN: Point-Voxel Feature Set Abstraction With…

STM32F4 | GPIO工作原理和配置 | GPIO库函数 | IO口操作步骤

文章目录一、GPIO基础知识1.GPIO是什么&#xff1f;2.引脚和GPIO的区别和联系&#xff1f;3.绝多数引脚都是GPIO&#xff0c;有限的引脚怎么实现更多的功能&#xff1f;4. 怎么知道具体的芯片外设资源?5.怎么查看GPIO引脚功能&#xff1f;二、GPIO的8种工作模式三、GPIO寄存器…

腾讯Robotics X Lab低电压电刺激触觉方案,单手指25个电极

关于体感手套的案例&#xff0c;青亭网曾经报道过许多种&#xff0c;有低成本的DIY阻力模拟手套&#xff0c;也有价格昂贵的启动微流体VR手套方案&#xff0c;或是基于SMA驱动器、SMI压力传感器的手套技术。但是&#xff0c;要模拟人类体感系统多样且敏感的触觉体验&#xff08…

TI Lab_SRR学习_3 速度扩展_3完结篇 interFrameProcessing

这篇信息量有点大,为了方便理解,还是先把帮助理解的图放在这里。 MmwDemo_interFrameProcessing函数的代码比较长,分段来看。先将数据从1DFFT的结果从L3内存中的radarCube移动到L1内存中的dstPingPong。for循环表示每一个RangeBins都要进行多普勒FFT等处理。从这里开始,可以…

Java——反射详解

目录 一、概念 二、功能 三、反射相关的重要的类 3.1 class类 3.2 获取class类的方法 3.3 class类中的方法 3.4 Field类方法 3.5 打破封装 一、概念 反射库&#xff08;reflection library&#xff09;提供了一个非常丰富且精心设计的工具集&#xff0c;以便编写能够动态…

口腔医院管理系统 | 口腔医院小程序 | 数字化门店转型

人们生活质量提升&#xff0c;在饮食方面不仅吃的饱&#xff0c;而且吃的好&#xff0c;相应的口腔问题就随之增多了&#xff0c;市面上的口腔医院不少&#xff0c;就诊的患者也不少。 目前&#xff0c;随着消费升级/互联网信息便捷化的大场景下&#xff0c;无论口腔门店经营还…

【Python项目】圣诞节快到了,Python基于海龟(turtle)实现的圣诞树效果,是好几个哟 | 附源码

前言 halo&#xff0c;包子们上午好 圣诞节快到了 今天我的好兄弟们安排了一波圣诞节的Python代码 主要是用海龟&#xff08;turtle&#xff09;画图实现的&#xff0c;非常简单的啦 话不多说&#xff0c;直接开整 相关文件 关注小编&#xff0c;私信小编领取哟&#xff01;…

推动教育信息化2.0变革!重建5平方公里的实景三维校园....

当前&#xff0c;各地市智慧校园建设方兴未艾&#xff0c;随着《教育信息化“十四五”规划》的发布实施&#xff0c;明确指出要以人工智能、大数据、物联网、云计算等新兴技术为依托&#xff0c;推动教育信息化2.0变革&#xff0c;打造全新的教育生态模式&#xff0c;让校园变得…

Nacos配置管理

Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.1.在nacos中添加配置文件 然后在弹出的表单中&#xff0c;填写配置信息&#xff1a; 1.2.从微服务拉取配置 1&#xff09;引入nacos-config依赖 <!--nacos配置管理依赖--> <dependency><gr…

简化基于Maven的Scala项目创建详解

使用 Maven 来构建 Scala 项目方便虽然方便&#xff0c;但依赖于每一个开发人员都去配置一遍项目的必要依赖&#xff0c;包括 Scala 插件的编译配置以及 Scala 的依赖类库&#xff0c;让每个人通过拷贝&#xff08;Copy&#xff09;之前的项目配置当然可以&#xff0c;但难免会…

二叉树与递归

前言 二叉树与递归 文章目录前言一、第一种方法1、如何思考二叉树相关的问题&#xff1f;1&#xff09;最大深度的定义2&#xff09;由具体到一般3&#xff09;公式4&#xff09;总结2、为什么需要使用递归&#xff1f;1&#xff09;循环和递归2&#xff09;递和归的过程3、为什…

GitHub上传文件和文件夹以及大于25M的单个文件

有好几个地方直接拖拽上传即可&#xff08;其中之一见下图&#xff09;&#xff0c;不管是文件还是文件夹目录结构不会变的。一次可上传的文件夹要求其内部的文件个数不超过100个&#xff0c;否则先GitHub上新建文件夹&#xff08;空文件的嘎货&#xff09;然后文件分批上传到G…

使用Python谋生的10种方法

这里本文的目录前言在质量保证部&#xff08;QA&#xff09;工作成为小型组织的IT员工为应用程序执行专业脚本管理网络教编程技能帮助人们决定位置执行数据挖掘与嵌入式系统互动开展科学任务进行数据实时分析零基础Python学习资源介绍&#x1f449;Python学习路线汇总&#x1f…

小程序ScrollView置顶只会成功一次,小程序如何做一键置顶?

现在会出现的问题就是点击置顶只会成功触发一次触顶 问题录像 置顶出现的问题为什么会出现这个问题呢&#xff1f; 先看看怎么控制scrollView实现置顶的。 scroll-top number/string 否 设置竖向滚动条位置scroll-view官网地址 通过动态的设置scroll-top来控制滚动条的位置…

Python编码问题整理

GB2312是中国规定的汉字编码&#xff0c;也可以说是简体中文的字符集编码 GBK 是 GB2312的扩展 ,除了兼容GB2312外&#xff0c;它还能显示繁体中文&#xff0c;还有日文的假名 cp936&#xff1a;中文本地系统是Windows中的cmd&#xff0c;默认codepage是CP936&#xff0c;cp936…

three.js之光源

文章目录简介分类环境光点光源平行光聚光灯光源辅助对象相关计算颜色计算阴影相关属性castShadowreceiveShadowshadowLightShadow基类专栏目录请点击 简介 光源是对于自然界光照的模拟&#xff0c;往往为了更好的渲染场景&#xff0c;需要设置不同的光源&#xff0c;设置不同的…

如何利用Python中的scipy做卡方检验?

1.简单介绍 卡方检验是一种用途很广的计数资料的假设检验方法。它属于非参数检验的范畴&#xff0c;主要是比较两个及两个以上样本率&#xff08;构成比&#xff09;以及两个分类变量的关联性分析。其根本思想就是在于比较理论频数和实际频数的吻合程度或拟合优度问题。 应用场…

【数据架构】如何通俗易懂的介绍数据模型

一直以来&#xff0c;如何和业务领导讲明白什么是数据模型&#xff0c;是沟通的一大难题&#xff0c;下面演示一个示例&#xff0c;仅供参考。 介绍抽象世界 先从大佬胡本立的《以人为中心的数据观》说起。这个世界可以划分为3个世界&#xff0c;一个是客观存在的客观世界&am…

Lecture3:神经网络与反向传播

目录 1.计算图 2.反向传播与计算图 2.1 第一个例子 2.2 第二个例子--sigmoid 2.3 第三个例子--MAX门 2.4 第四和例子--对于向量的梯度 3.神经网络 4.常见矩阵求导公式 4.1 标量对向量求导 4.2 二次型对向量求导 1.计算图 在实践中我们想要推导和使用解析梯度&…