【MyBatis】操作数据库——入门

在这里插入图片描述

文章目录

  • 为什么要学习MyBatis
  • 什么是MyBatis
  • MyBatis 入门
    • 创建带有MyBatis框架的SpringBoot项目
    • 数据准备
    • 在配置文件中配置数据库相关信息
    • 实现持久层代码
    • 单元测试

为什么要学习MyBatis

前面我们肯定多多少少学过 sql 语言,sql 语言是一种操作数据库的一类语言,数据库是保证数据能够持久化存储的一种集合。在众多 sql 语言中,MySQL就是其中一种,并且是人们使用较多的一种 sql 语言,而就是因为 MySQL 使用较简单,使用的人较多,所以就出现了 JDBC 编程,也就是 Java 的一个 API,可以让我们通过 Java 代码来操作我们的数据库,但是呢?JDBC 编程的操作太复杂了,为什么会说 JDBC 操作复杂呢?看下面这段代码。

package com.example.mybatis20231226.Dao;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserDao {
    DataSource dataSource = null;
    public UserDao(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void addUser() throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dataSource.getConnection();
            String sql = "insert into user values (?,?,?);";
            statement = connection.prepareStatement(sql);
            statement.setString(2, "小明");
            statement.setInt(3, 0);
            statement.execute();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

使用 JDBC 操作,需要创建出 DataSource 数据源对象、Connection 对象、PrepareStatement 对象,甚至是 ResultSet 对象,并且在使用完这些资源之后还不能忘记释放掉这些资源,这些 JDBC 很多的操作都是重复的,所以就出现了能够简化 JDBC 操作的框架——MyBatis。

什么是MyBatis

MyBatis的发展历程可以追溯到2001年,当时Clinton Begin发起了一个名为iBATIS的开源项目。iBATIS最初是一个专注于密码软件开发的开源项目,但后来逐渐发展成为一个基于Java的持久层框架。

在2004年,Clinton将iBATIS的名字和源码捐赠给了Apache软件基金会,接下来的6年中,开源软件世界发生了巨大的变化,一切开发实践、基础设施、许可,甚至数据库技术都彻底改变了。

2010年,核心开发团队决定离开Apache软件基金会,并且将iBATIS改名为MyBatis。之后,MyBatis迁移到了Google Code,并在2013年11月再次迁移到了GitHub。

在功能上,MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架。它消除了几乎所有的JDBC代码和参数的手动设置以及结果集的检索。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。使得数据持久层的设计更为灵活和高效。

这里是 MyBatis 的中文官方网站https://mybatis.net.cn/

在这里插入图片描述
在 Spring 中,三层架构分别是Controller(控制层)、Service(业务逻辑层)和Dao(数据访问层),我们的 MyBatis 就处于三层架构的 Dao 层。

在这里插入图片描述
简单来说,MyBatis 就是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库的工具。

MyBatis 入门

首先我们先通过一个使用了 MyBatis 框架的程序来看看 MyBatis 有多么的方便。

创建带有MyBatis框架的SpringBoot项目

在创建项目的时候勾选上 MyBatis FrameworkMySQL Driver

在这里插入图片描述
MyBatis 不是只能用于 Java 的 Spring 框架,它可以独立存在,只是因为 MyBatis 的实用性的方便,所以 Idea 才将 MyBatis 给集成进来了。那么既然选择了 MyBatis,为什么还要选择 MySQL Driver 呢?前面我们说了,MyBatis 是一种框架,他操作的是数据库,只是简化了 JDBC 的操作,所以底层还是 JDBC。

当勾选了 MyBatis 框架了之后,在 SpringBoot 项目的 pom.xml 文件中可以发现已经自动导入了 MyBatis 和 MySQL 的依赖。

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter-test</artifactId>
    <version>3.0.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

如果我们已经创建完成了SpringBoot项目了之后,想要在当前项目添加进去 MyBatis 依赖的话,可以使用前面的 Edit Starters 插件来继续添加进去 MyBatis 依赖。

在这里插入图片描述
当然我们也可以去 maven 中央仓库通过添加 MyBatis 依赖的坐标到 pom.xml 文件中来加入依赖,其实上一个在创建 SpringBoot 项目的时候勾选 MyBatis 选项也是将 MyBatis 的坐标添加进去 pom.xml 文件中,只不过这个是 Idea 帮我们自动完成了。

注意:手动添加 Mybatis 依赖的时候,需要注意 Spring 版本和 MyBatis 版本的对应关系。

数据准备

我们先在本地数据库中存储一些数据,作为后面 MyBatis 操作的数据。

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
                            `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
                            `username` VARCHAR ( 127 ) NOT NULL,
                            `password` VARCHAR ( 127 ) NOT NULL,
                            `age` TINYINT ( 4 ) NOT NULL,
                            `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
                            `phone` VARCHAR ( 15 ) DEFAULT NULL,
                            `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
                            `create_time` DATETIME DEFAULT now(),
                            `update_time` DATETIME DEFAULT now(),
                            PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

在这里插入图片描述
在 Java 中创建出 UserInfo 类与数据库中一行的数据对应。这里为什么要与数据库中的列对应以及可不可以不对应,我们后面再说。

package com.example.mybatis20231226.Model;

import lombok.Data;

import java.util.Date;

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private int age;
    private int gender;
    private String phone;
    private int deleteFlag;
    private Date createTime;
    private Date updateTime;
}

在配置文件中配置数据库相关信息

我这里选择的是 YAML 配置文件配置,properties 也类似。

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: xxxxxx
    driver-class-name: com.mysql.cj.jdbc.Driver

如果MySQL使用的是5.x之前版本的话,driver-class-name选项的值要使用 com.mysql.jdbc.Driver ,大于5.x版本就使用 com.mysql.jdbc.cj.Driver

实现持久层代码

MyBatis 持久层接口规范一般都叫XxxMapper。

package com.example.mybatis20231226.Mapper;

import com.example.mybatis20231226.Model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo")
    public List<UserInfo> selectAll();
}

注意这里的 @Mapper 注解要选择 org.apache.ibatis.annotations 包下的。
在这里插入图片描述
在MyBatis中,@Mapper注解主要用于标识接口,它表示该接口是一个MyBatis的映射器接口。这个注解可以帮助简化代码和提高代码的可读性。

当你使用@Mapper注解标记一个接口时,MyBatis会自动为该接口生成实现类,该实现类包含了该接口中所有方法对应的SQL语句和执行逻辑。而在Spring中使用@Mapper注解,Spring会扫描到这个接口,并将其实例化为一个Bean,自动注入到MyBatis的SqlSession中。这样,你就可以通过直接调用接口方法的方式来执行相应的SQL语句,而不需要手动编写实现代码。

@Select("select * from userinfo")
public List<UserInfo> selectAll();

public List<UserInfo> selectAll() 是方法的声明,而这个 @Select("select * from userinfo") 则是这个方法的实现。Select 说明这个方法是一个查询方法。

那么有人会问了,这里类为什么会选择使用 interface 接口,而不是 class 呢?如果你是 class 的话,那么方法的具体实现就是需要我们写出来的,而上面说了这个方法的实现是通过 @Select("select * from userinfo") 注解实现的,如果我们再在这个方法中写上实现的话,就会导致冲突出现问题,而 interface 接口中的所有方法都是抽象方法,是不需要写出方法的实现的,正好对应 MyBatis 注解来实现,所以 interface 接口是最好的选择。

单元测试

当我们写完上面的代码之后,是否需要再创建一个测试类来测试这个方法呢?可以这样,但是这样比较麻烦,我们可以通过单元测试的方法快速的测试我们的代码功能。

单元测试是一种对软件中的最小可测试单元进行检查和验证的测试活动。在软件开发过程中,单元测试是在最低级别进行的测试活动,通常针对软件的独立单元进行,这些单元可能是函数、类、模块或组件。单元测试的目标是确保每个单元都能按照预期的方式工作,并且能够与其他单元协调工作。
对于单元测试中单元的含义,要根据实际情况去判定其具体含义。例如,在C语言中,单元通常指的是一个函数;在Java中,单元通常指的是一个类;在图形化的软件中,单元可能指的是一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。

我们在需要单元测试的类中右键选择generate。

在这里插入图片描述

选择 Test。

在这里插入图片描述
在这里插入图片描述
当点击ok之后,就会生成一个单元测试代码:

package com.example.mybatis20231226.Mapper;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

@Slf4j
class UserInfoMapperTest {

    @BeforeEach
    void setUp() {
    }

    @AfterEach
    void tearDown() {
    }

    @Test
    void selectAll() {
    }
}

然后我们只需要完成单元测试中函数的实现的可以了。

package com.example.mybatis20231226.Mapper;

import com.example.mybatis20231226.Model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@Slf4j
class UserInfoMapperTest {
    
    //通过@Autowired注解拿到Bean
    @Autowired
    private UserInfoMapper userInfoMapper;
    @BeforeEach
    void setUp() {
        log.info("selectAll 执行之前");
    }

    @AfterEach
    void tearDown() {
        log.info("selectAll 执行之后");
    }

    @Test
    void selectAll() {
        List<UserInfo> list = userInfoMapper.selectAll();
        log.info(list.toString());
    }
}

当我们运行会发现,运行出现了问题:

在这里插入图片描述

为什么会出现这种错误呢?出现这种错误就是因为 Spring 环境没有正确启动。所以我们需要在类上加上类注解 @SpringBootTest 来为这个类加上 Spring 上下文管理。

@SpringBootTest
@Slf4j
class UserInfoMapperTest {
}
package com.example.mybatis20231226.Mapper;

import com.example.mybatis20231226.Model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Slf4j
class UserInfoMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @BeforeEach
    void setUp() {
        log.info("selectAll 执行之前");
    }

    @AfterEach
    void tearDown() {
        log.info("selectAll 执行之后");
    }

    @Test
    void selectAll() {
        List<UserInfo> list = userInfoMapper.selectAll();
        log.info(list.toString());
    }
}

在这里插入图片描述

在这里插入图片描述
通过这种单元测试就达到了测试代码功能的作用,那么 MyBatis 的详细基础操作我就放在下一篇文章了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AIGC风格prompt】风格类绘画风格的提示词技巧

风格类绘画风格的提示词展示 主题&#xff1a;首先需要确定绘画的主题&#xff0c;例如动物、自然景观、人物等。 描述&#xff1a;根据主题提供详细的描述&#xff0c;包括颜色、情感、场景等。 绘画细节&#xff1a;描述绘画中的细节&#xff0c;例如表情、纹理、光影等。 场…

认识Linux指令之 “mv” 指令

01.mv指令&#xff08;重要&#xff09; mv命令是move的缩写&#xff0c;可以用来移动文件或者将文件改名&#xff08;move (rename) files&#xff09;&#xff0c;是Linux系统下常用的命令&#xff0c;经常用来备份文件或者目录。 语法: mv [选项] 源文件或目录 目标文件或…

影视后期:Pr 调色处理之风格调色

写在前面 整理一些影视后期相关学习笔记博文为 Pr 调色处理中风格调色&#xff0c;涉及下面几个Demo 好莱坞电影电影感调色复古港风调色赛博朋克风格调色日系小清晰调色 理解不足小伙伴帮忙指正 简单地说就是害怕向前迈进或者是不想真正地努力。不愿意为了改变自我而牺牲目前所…

jsp介绍

JSP 一种编写动态网页的语言&#xff0c;可以嵌入java代码和html代码&#xff0c;其底层本质上为servlet,html部分为输出流&#xff0c;编译为java文件 例如 源jsp文件 <% page contentType"text/html; charsetutf-8" language"java" pageEncoding&…

数据库存储引擎

一、什么是存储引擎 存储引擎是MySQL数据库中的一个【组件】&#xff0c;【负责执行实际的数据I/O操作】&#xff0c;工作在文件系统之上&#xff0c;数据库的数据会先传到存储引擎&#xff0c;在按照存储引擎的格式&#xff0c;保存到文件系统。 常用的存储引擎&#xff1a;…

在多Module项目中,给IDEA底部选项卡区域添加Services选项卡

一般一个spring cloud项目中大大小小存在几个十几个module编写具体的微服务项目。此时&#xff0c;如果要调试测需要依次启动各个项目比较麻烦。 idea其实提供了各module的启动管理工具了&#xff0c;可以快速启动和关闭各个服务&#xff0c;也能批量操作&#xff0c;比如一次…

[每周一更]-(第49期):一名成熟Go开发需储备的知识点(答案篇)- 2

答案篇 1、Go语言基础知识 什么是Go语言&#xff1f;它有哪些特点&#xff1f; Go语言&#xff08;也称为Golang&#xff09;是一种由Google开发的开源编程语言。它于2007年首次公开发布&#xff0c;并在2012年正式推出了稳定版本。Go语言旨在提供简单、高效、可靠的编程解决…

Windows 10 安装和开启VNCServer 服务

Windows 10 安装和开启VNCServer 服务 登录云服务器 使用本地RDP登录到配置VNCServer服务的Windows10系统的云服务器。 下载VNC Server安装包 打开官网下载VNCServer安装包 URL&#xff1a;https://www.realvnc.com/en/connect/download/vnc/windows/ 安装VNC Server 双击…

基于蝗虫算法优化的Elman神经网络数据预测 - 附代码

基于蝗虫算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于蝗虫算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于蝗虫优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

Adobe ColdFusion 文件读取漏洞(CVE-2010-2861)

漏洞原理 Adobe ColdFusion是美国Adobe公司的一款动态Web服务器产品&#xff0c;其运行的CFML&#xff08;ColdFusion Markup Language&#xff09;是针对Web应用的一种程序设计语言。由于AJP协议设计存在缺陷导致内部相关的属性可控&#xff0c;攻击者可以构造属性值&#xff…

微信小程序发送模板消息-详解【有图】

前言 在发送模板消息之前我们要首先搞清楚微信小程序的逻辑是什么&#xff0c;这只是前端的一个demo实现&#xff0c;建议大家在后端处理&#xff0c;前端具体实现&#xff1a;如下图 1.获取小程序Id和密钥 我们注册完微信小程序后&#xff0c;可以在开发设置中看到以下内容&a…

《Linux系列》Linux磁盘MBR分区扩容

文章目录 Linux磁盘MBR分区扩容1.前言2.控制台磁盘扩容3.分区扩容3.1 fdisk3.2 lsblk3.3 扩容分区 4.扩容文件系统4.1 df4.2 扩容文件系统 Linux磁盘MBR分区扩容 1&#xff09;参考阿里云扩容分区文档&#xff0c;整理MBR分区扩容 2&#xff09;本文档适用于MBR分区(fdisk -lu查…

【STM32】SPI通信

1 SPI通信 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是由Motorola公司开发的一种通用数据总线 四根通信线&#xff1a;SCK&#xff08;Serial Clock&#xff0c;串行时钟&#xff09;、MOSI&#xff08;Master Output Slave Input&am…

N 皇后 II[困难]

一、题目 n皇后问题 研究的是如何将n个皇后放置在n n的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。给你一个整数n&#xff0c;返回n皇后问题 不同的解决方案的数量。 示例 1&#xff1a; 输入&#xff1a;n 4 输出&#xff1a;2 解释&#xff1a;如上图所示&#…

Rust学习笔记005:结构体 struct

在 Rust 中&#xff0c;struct 是一种用于创建自定义数据类型的关键字&#xff0c;它允许你定义和组织数据的结构。struct 可以包含多个不同类型的字段&#xff08;fields&#xff09;&#xff0c;每个字段都有一个名称和一个类型。 定义结构体 下面是一个简单的例子&#xff…

基于JAVA的酒店管理系统设计

摘 要 我们对酒店进行调研&#xff0c;发现部分酒店依托第三方平台&#xff0c;但第三方平台没有办法更好帮助酒店管理&#xff0c;故我们决定帮助酒店开发一套基于 Java 的酒店管理系统。使用基于Java的酒店管理系统可以帮助酒店完成顾客入住信息的管理&#xff0c;酒店物资的…

构建高效数据流转的 ETL 系统:数据库 + Serverless 函数计算的最佳实践

作者&#xff1a;柳下 概述 随着企业规模和数据量的增长&#xff0c;数据的价值越来越受到重视。数据的变化和更新变得更加频繁和复杂&#xff0c;因此及时捕获和处理这些变化变得至关重要。为了满足这一需求&#xff0c;数据库 CDC&#xff08;Change Data Capture&#xff…

2022年全球运维大会(GOPS上海站)-核心PPT资料下载

一、峰会简介 GOPS 主要面向运维行业的中高端技术人员&#xff0c;包括运维、开发、测试、架构师等群体。目的在于帮助IT技术从业者系统学习了解相关知识体系&#xff0c;让创新技术推动社会进步。您将会看到国内外知名企业的相关技术案例&#xff0c;也能与国内顶尖的技术专家…

【大数据面试知识点】Spark中的累加器

Spark累加器 累加器用来把Executor端变量信息聚合到Driver端&#xff0c;在driver程序中定义的变量&#xff0c;在Executor端的每个task都会得到这个变量的一份新的副本&#xff0c;每个task更新这些副本的值后&#xff0c;传回driver端进行merge。 累加器一般是放在行动算子…

解决相机库CameraView多滤镜拍照错乱的BUG (一) : 复现BUG

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…