当前位置: 首页 > news >正文

MyBatis 框架的思想及其第一次使用

MyBatis 框架的思想及其第一次使用

  • 引言
    • ORM 框架
    • MyBatis 核心
  • MyBatis 的第一次使用
    • 一、创建一个 Spring MVC 项目
    • 二、搭好配置文件
      • 概览步骤
      • 步骤1
      • 步骤2
      • 步骤3
      • 步骤4
      • 步骤5
      • 总览配置
      • 注意事项
    • 三、正式查询数据库
      • 概览步骤
      • 步骤1
      • 步骤2
      • 步骤3
      • 步骤4
      • 接口和 " xml 文件 " 的对应关系
      • 步骤5
      • 步骤6
      • 注意事项
    • 四、查询结果验证
  • Spring Boot 单元测试
    • 定义
    • 框架
    • 作用
    • 生成测试类步骤
    • 点击方法启动,开始测试
  • 总结

引言

ORM 框架

ORM(Object Relational Mapping):对象关系映射。

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

1-1

MyBatis 核心

MyBatis 的核心有两个:一是接口,二是 " xml 文件 ".

此外,我认为还有一个较为核心的东西就是实体类。

映射关系:

① 数据表 => 实体类

② 一条记录 => 一个对象

③ 表中字段 => 对象的属性

0-0

MyBatis 的第一次使用

一、创建一个 Spring MVC 项目

创建一个 Spring MVC 项目,不再多说。

但当我们真正用到 MyBatis 的时候,就需要选择下面的依赖:

一个是 " MyBatis Framework ",另一个是 " MySQL Driver "
前者表示框架,后者表示驱动 ( 根据你需要连接的数据库商家进行选择 )

1-3

二、搭好配置文件

概览步骤

步骤:

步骤1:创建好配置文件 ( yml / properties )
步骤2:选择运行环境 ( 开发环境 / 运行环境 ),【下面步骤以开发环境为例】
步骤3:在配置文件中,连接数据库
步骤4:在配置文件中,开启 MyBatis SQL 打印,以便我们日常测试
步骤5:在配置文件中,配置 " xml 文件 " 保存路径

1-4

步骤1

创建 " application.yml "

步骤2

创建 " application-dev.yml " 和 " application-prod.yml "

步骤3

连接数据库固定代码:

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&&useSSL=false
    username: root
    password: 12345678
    driver-class-name: com.mysql.cj.jdbc.Driver # 这里表示 MySQL 驱动名称

注意事项:

① 使用 MyBatis 连接数据库是写在配置文件中的,它是系统类别的配置文件,所有的格式都是固定写法。

② 以往我们使用 JDBC 编程的时候, " url ", " username ", " password " 这三个属性是必不可少的,现在呢,我们需要额外添加一个 " driver-class-name " 属性,它表示需要连接哪种数据库的名称。如果你需要连接的是 Oracle 数据库,就填写 Oracle 的专属名称;如果你需要连接的是 MySQL数据库,就填写 MySQL 的专属名称。

步骤4

开启 MyBatis SQL 打印日志

logging:
  level:
    com:
      example:
        demo: debug

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

注意事项:

这一步不是必须的,但能够方便于我们测试,我认为初学者必须要配置。

步骤5

配置 " xml 文件 " 路径:

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

注意事项:

① 这里的配置代码,应该写在公共的 " application.yml " 文件下,因为不论是开发环境,还是生产环境,都需要这段公共代码。

② 前文提到,MyBatis 的核心就在于接口和 " xml 文件 " ,所以 " xml 文件 " 就应该放置在 【resources】目录下。此外,由于日后我们的 " xml 文件 " 在一个项目中不止一份,所以我们应该创建一个【mybatis】目录。

③ 这里配置 " xml 文件 " 是一种标准写法,它告知了 MyBatis 框架 " xml 文件 " 是在哪个目录底下的哪种格式,如下图所示:

1-5

总览配置

由于我们暂时不涉及云服务器上的数据库,所以我们只展示 " 公共的 yml 文件 " 和 " 开发环境的 yml 文件 ".

1-6

注意事项

① MyBatis 框架的配置既多又杂,很多写法都是固定的,这就像 " 1+1=2 " 一样,我们无需知道为什么,直接用就可以了,我们可以将这些零零碎碎的代码片段,放置我们的代码仓库中,方便我们后续使用。

② 从 0 到 1 是比较难的,尤其是这种搭配环境的事情,确实比较折腾人,但多做几次,就能够很好的熟悉整个过程。

三、正式查询数据库

概览步骤

步骤1:准备数据库
步骤2:根据数据库的字段,创建实体类
步骤3:创建 Mapper 接口
步骤4:创建 " xml 文件 "
步骤5:创建 Service 类
步骤6:创建 Controller 类

1-7

步骤1

准备数据库:

创建一个名为 " mycnblog " 的数据库,并插入两张表,【用户表】、【文章表】、

我们的思想是博客系统,一个用户拥有自己的专属的文章,并将用户的信息放在用户表中,文章信息放在文章表中。后续,我们可以通过这些字段来增删改查。

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

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 '123.png',
    createtime datetime default now(),
    updatetime datetime default now(),
    `state` int default 1
);

-- 创建【文章表】
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
);

-- 添加一个用户信息
insert into userinfo (id, username, password, `state`) values (null, 'Jack', '123', 1);

insert into userinfo (id, username, password, photo, `state`) values (null, '李明', '321', '李明.png',  1);

insert into userinfo (id, username, password, `state`) values (null, 'Rose', '456', 1);

-- 文章添加测试数据
insert into articleinfo(title,content,uid) values ('C++','C++语法',1);

insert into articleinfo(title,content,uid) values ('Java','JavaWeb',2);

insert into articleinfo(title,content,uid) values ('Python','基本结构',3);

步骤2

根据数据库的字段,创建实体类:

0-1

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private String createtime;
    private String updatetime;
    private int state;
}

注意事项:

创建实体类的步骤非常关键! 我们需要仔细地将 Java 和 数据库对应起来。

① Java 实体类的类名应该和数据表的表名吻合。
② 实体类中的属性 (成员变量) 应该和表中的字段吻合。

为什么一定要这样做?

① 首先,这是一种标准。
② 其次,这里的实体类需要与项目中的 " xml " 文件、mapper 接口联系起来,只要其中一个环节出错,那么就会出现整个项目抛异常的情况,到那个时候,可能就不仅仅是代码层面的报错,也有可能是框架报错。所以,为了避免调试这样的麻烦事,我们不能随心所欲,我们应该与之前数据库设计好的那样去约定实体类。

步骤3

创建 Mapper 接口:

@Mapper
public interface UserMapper {

    // 根据用户 id 来查询某个用户的所有信息
    public UserInfo getUserById(@Param("id") Integer id);

}

步骤4

创建 " 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">

    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where id = #{id}
    </select>
    
</mapper>

注意事项:

① " namespace " 属性,填入的是 Mapper 接口。( 需要具体到包名、接口名 )

② 如果我们进行查询操作,就使用 select 标签;修改操作,就使用 update 标签…

③ 在上面的 select 标签中," id " 属性表示 Mapper 接口中的方法名;" resultType" 属性表示当前查询操作返回的类型 ( 需要具体到包名、实体类名 )

④ 最重要的是 SQL 语句,它决定了我们是否真正对数据库执行了操作。下面的 #{id} 就表示 JDBC 中的问号,表示占位符。后面我还会介绍 ${id}.

select * from userinfo where id = #{id}

-- select * from userinfo where id = ?

备注: 在写上面的 SQL 语句之前,我们应该先在自己的数据库上进行原 SQL 的测试,如果原 SQL 没问题了,那么我们再变换形式写在 " xml " 文件中,这样不容易出错。

接口和 " xml 文件 " 的对应关系

接口和 " xml 文件 " 的对应关系是整个 MyBatis 的核心,虽然这里的关联关系并不难,但操作起来非常的乱,且容易出错,所以我们应该重视起来。

1-8

步骤5

创建 Service 类:

在 UserService 类中,我们采取 " 属性注入 " 的方式,将 " userMapper " 对象存入进来,之后就能使用接口中的方法了。

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    public UserInfo getUserById(Integer id) {
        return userMapper.getUserById(id);
    }
    
}

备注: 属性注入不仅可以存入类,也可以存入接口。

步骤6

创建 Controller 类:

在 UserController 类中,我们依然采取 " 属性注入 " 的方式,将 " userService " 对象存入进来,之后就能使用类中的方法了。

在这里,我们明确了给前端返回的是一个数据,也明确了路由、传入参数。

@RestController
public class UserController {

    @Resource
    private UserService userService;

    @RequestMapping("/get_user")
    public UserInfo getUserId(Integer id) {
        if (id == null) return null;
        return userService.getUserById(id);
    }

}

注意事项

这里需要思考,我们为什么不使用 " Controller 类 " 直接调用 " Mapper 接口 ",而是让 " Service " 在中间插了一杠子?

① 首先,这是一个 Web 项目查询数据库的标准步骤。

② 其次,这样分层地拆分程序,能够更好地解耦合,也能够更好地为后端分工。

与前端交互的事情,就让 " Controller " 层去做,交互出了问题,直接看这一层。
调用接口的事情,就让 " Service " 层去做,出了问题,直接定位这一层。
查询数据库的事情,就让 " Mapper " 接口去做…

1-2

四、查询结果验证

后端运行启动类,前端传入一个 id = 2 的参数,查询结果:

1-9

我们查看 MyBatis 日志文件:发现 #{id} 就是一个占位符,相当于一个问号,只有前端传入参数进来的时候,才会进行替换。

2-1

Spring Boot 单元测试

定义

单元测试,就是指对软件中的最小可测试单元进行检查和验证的过程。

最小可测单元就是方法,方法无法再拆分了。

框架

一般来说,当我们成功创建一个 Spring Boot 项目的时候," pom.xml " 会自动为我们生成下面的依赖。

2-2

作用

① 单元测试可以非常简单、直观、快速地测试某一个功能是否正确。

② 使用单元测试可以帮我们在打包的时候,发现一些问题,因为在打包之前,所有的单元测试必须通过,否则就不能打包成功。

使用单元测试,在测试功能的时候,可以不污染连接的数据库,也就是可以不对数据库进行任何改变的情况下,进行测试。( 使用 " @Transactional " 注解实现 )

生成测试类步骤

步骤1: 在你需要进行测试的 类 / 接口 中,点击鼠标右键进行如下操作。

注意事项: 点击鼠标右键之前,我们鼠标必须要挪动到下面的红色框框中,否则就不会出现 " Test " 选项。

2-3

步骤2: 勾选你需要测试的成员方法,其他的选项默认即可,框架会自动帮我们生成的。

2-4

步骤3: 系统会自动帮我们生成一个测试类,在测试类中,有对应的同名测试方法。测试类的保存路径在 " 绿色的 java 文件下 " ,与 " 蓝色的 java 文件 " 保存形式很相似。

2-5

点击方法启动,开始测试

@SpringBootTest // 表示当前单元测试运行在 Spring Boot 环境中
class UserMapperTest {

    @Resource
    private UserMapper userMapper;

    @Test
    void getUserById() {
        UserInfo userInfo = userMapper.getUserById(2);
        System.out.println("测试结果:" + userInfo);
    }
}

测试结果:

2-6

注意事项:

① 这是 Spring Boot 的单元测试,所以需要添加 " @SpringBootTest " 注解。

② 使用 " 属性注入 " 的方式来存入对象,后续就可以拿到原类的方法了。

③ 属性注入时,既可以使用 " @Autowired " 注解,也可以使用 " @Resource " 注解。但前者放在专业版 IDEA 下时,软件会报错,但不影响测试运行。

总结

第一次使用 MyBatis 框架的时候,其实是比较难的。我认为,这个难点就是存在于折腾环境这件事上,并不是业务代码层面上的难点。关于配置环境,只要出现一点问题,就会出现意想不到的报错异常,看到你头皮发麻,所以,每次我们配置环境的时候,都需要按照标准写法来,不要随心所欲。只有环境搭建好了,才能真正地使用 SQL 语句。

然而,MyBatis 对 JDBC 进行了封装,只要我们有 JDBC 的基础,学习起来就很快了。最起码,思想层面我们就不用问更多为什么了。

相关文章:

  • 流量回放的数据隔离
  • 关于http协议中的各种请求头、请求类型的作用以及用途
  • Spring Cloud Gateway网关下的文档聚合(knife4j)
  • 【星环社区版TDH2024年度大事件】全新版本?全新组件?性能提升10倍?
  • allegro 打开 brd文件时提示 WARNING(SPMHDB-212) 告警 应该如何解决呢?
  • 文心一言 VS 讯飞星火 VS chatgpt (285)-- 算法导论21.2 4题
  • linux ps 命令详解
  • SpringCloud微服务-Eureka注册中心
  • 微信小程序(4)- 事件系统和模板语法
  • express+mysql+vue,从零搭建一个商城管理系统5--用户注册
  • 【系统分析师】-系统规划
  • 05_第五章 Servlet(@WebServlet,Servlet继承结构,生命周期,ServletConfig和ServletContext)
  • 【Unity Shader】Unity中如何创建Cubemap?
  • 面试百问:项目上线后才发现bug怎么办?
  • C语言《文件版本通讯录》
  • 【无人机】基于EKF、UKF、PF、改进PF滤波算法的无人机航迹预测(Matlab代码实现)
  • 一篇文章让你搞懂Java中的静态代理和动态代理
  • ROS1云课-导航实践测评
  • React中路由的参数传递 - 路由的配置文件
  • (附源码)计算机毕业设计SSM基于web的健康饮食信息管理系统
  • 算法的意义、如何学习算法和算法的复杂度
  • 由浅到深带你详谈Java实现数组扩容的三种方式【建议收藏】
  • 【ML on Kubernetes】第 1 章:机器学习的挑战
  • 技巧分享-电脑版微信如何登录多个账号
  • 精品微信小程序springboot居家养老服务+后台管理前后分离
  • GBase 8c 系统表之DB4AI.SNAPSHOT
  • 高频故障-文件扩展名消失(windows)
  • 冲突域与广播域(详解 + 区别)
  • 国庆征文获奖名单公布
  • java毕业设计大学生创新创业项目管理Mybatis+系统+数据库+调试部署
  • Mysql在可重复读事务隔离级别下怎么解决幻读的
  • 【数据结构Java版】链表之单链表的实现