• MyBatis入门详解


     本MyBatis~

    目录

    1.mybatis相关介绍

    1.1什么是mybatis

    1.2为什么要学mybatis

    2.mybatis实战操作

    2.1项目创建

    2.1.1准备数据表

    2.1.2创建一个mybatis项目

    2.2使用mybatis进行增删查改操作

    2.2.1查询操作

    2.2.2使用springboot进行单元测试介绍

    2.2.3修改操作

    2.2.4删除操作

    2.2.5增添操作


    1.mybatis相关介绍

    1.1什么是mybatis

    MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

    1.2为什么要学mybatis

    因为对于后端开发来说,程序主要是由后端程序和数据库两部分来组成的。而这两个部分要进行通讯,就需要有连接数据库的工具,前面我们已经学过了JDBC,但正是因为JDBC相对于MyBatis太过繁琐,所以我们就要开始学习MyBatis。

    2.mybatis实战操作

    2.1项目创建

    2.1.1准备数据表

    ①创建一个如下的数据库和数据表:

    1. -- 创建数据库
    2. drop database if exists mycnblog;
    3. create database mycnblog DEFAULT CHARACTER SET utf8mb4;
    4. -- 使用数据数据
    5. use mycnblog;
    6. -- 创建表[用户表]
    7. drop table if exists userinfo;
    8. create table userinfo(
    9. id int primary key auto_increment,
    10. username varchar(100) not null,
    11. password varchar(32) not null,
    12. photo varchar(500) default 'default.png',
    13. createtime datetime default now(),
    14. updatetime datetime default now(),
    15. `state` int default 1
    16. ) default charset 'utf8mb4';
    17. -- 创建文章表
    18. drop table if exists articleinfo;
    19. create table articleinfo(
    20. id int primary key auto_increment,
    21. title varchar(100) not null,
    22. content text not null,
    23. createtime datetime default now(),
    24. updatetime datetime default now(),
    25. uid int not null,
    26. rcount int not null default 1,
    27. `state` int default 1
    28. )default charset 'utf8mb4';
    29. -- 创建视频表
    30. drop table if exists videoinfo;
    31. create table videoinfo(
    32. vid int primary key,
    33. `title` varchar(250),
    34. `url` varchar(1000),
    35. createtime datetime default now(),
    36. updatetime datetime default now(),
    37. uid int
    38. )default charset 'utf8mb4';
    39. -- 添加一个用户信息
    40. INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
    41. (1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
    42. -- 文章添加测试数据
    43. insert into articleinfo(title,content,uid)
    44. values('Java','Java正文',1);
    45. -- 添加视频
    46. insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

    ②将其放在mysql中:

    2.1.2创建一个mybatis项目

    ①添加MyBatis相关依赖

    (1)新项目添加MyBatis依赖

    1.基于spring项目进行创建:

    (a)

    (b) 

    (c)

     (d)

     (2)老项目添加MyBatis:

    我们在pom.xml中点击鼠标右键,然后如下图所示操作

     ②配置数据库连接字符串和MyBatis(保存的xml目录)

    (1)配置数据库的连接信息

    1.主配置文件(application.yml)

    1. #生产环境的配置文件
    2. spring:
    3. profiles:
    4. active: dev

    2.开发环境配置文件(application-dev.yml)

    1. #开发环境的配置文件
    2. #无论是生产环境和开发环境都要配置以下四项
    3. # 配置数据库的连接
    4. spring:
    5. datasource:
    6. url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8
    7. username: root # 用户名(默认是root)
    8. password: 123456 # 自己的密码
    9. driver-class-name: com.mysql.cj.jdbc.Driver # mysql的驱动名称

    3.当前运行环境配置文件(application-prod.yml)

    这里先不做配置

    (2)配置MyBatis的xml保存路径

    xml属于资源文件,放于resource目录下。因此我们在resource目录下新建一个mybatis目录文件。

     代码:

    1. # 配置当前运行的环境(配置文件)
    2. spring:
    3. profiles:
    4. active: dev # 使用开发环境的配置文件
    5. # 配置 MyBatis 的 XML 的保存路径
    6. # 在resource底下新建一个文件夹,用来放 XML
    7. mybatis:
    8. mapper-locations: classpath:mybatis/**Mapper.xml

    ③使用Mybatis的操作模式操作数据库:

    创建controller,service,model,mapper的package在com.example.demo的目录下,方便在其中创建对应的类

    (1)在model里创建实体类UserInfo(这里最好和数据中的同名,这样便于看)代码如下:

    1. //这是一个实体类,对象的名字最好和数据库表名保持一致,看起来清楚
    2. package com.example.demo.model;
    3. import lombok.Data;
    4. import org.springframework.stereotype.Controller;
    5. @Data
    6. @Controller
    7. public class UserInfo {
    8. private int id;
    9. private String username;
    10. private String password;
    11. private String photo;
    12. private String createtime;
    13. private String updatetime;
    14. private String state;
    15. }

    (2)在mapper中创建UserMapper(这样写比较规范,因为会引入@Mapper,当然也可以不这么写)

    代码如下:(即定义普通的接口)

    1. package com.example.demo.mapper;
    2. import com.example.demo.model.UserInfo;
    3. import org.apache.ibatis.annotations.Mapper;
    4. import org.apache.ibatis.annotations.Param;
    5. //实现xml和interface之间的交互
    6. @Mapper//从普通的接口变成了mybatis的interface;可以通过xml实现,而普通的xml是要通过java才能实现的
    7. public interface UserMapper {
    8. //根据用户id来查询用户
    9. //@param是参数在xml中叫id,相当于重命名,但是使用中,只能用修改后的名字
    10. public UserInfo getUserById(@Param("id") Integer id);
    11. }

    (3)创建xml实现上面的接口

    注意:我们在前面配置的时候,就写了xml的存放路径需要在mybatis的目录下,并且命名为**Mapper.xml(而在这里为了方便我们更好的知道这里的xml对应的是哪个接口,所以我们将其前面命名一致为UserMapper)

    1.mybatis的固定xml格式:(每新建一个项目都会用到的,但是namepace需要根据自己的情况来填写)

    1. "1.0" encoding="UTF-8"?>
    2. mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    3. <mapper namespace="com.example.demo.mapper.UserMapper">
    4. <select id="getUserById" resultType="com.example.demo.model.UserInfo">
    5. select * from userInfo where id=${id}
    6. select>
    7. mapper>

    注意:(在查询操作的时候,这两个参数都是需要的,查询语句,有结果集的时候,都要映射到Java的对象,映射方式有很多种,但是必须指定一种,这里我们指定的就是resultType)

     我们写的时候,就是interface中写方法申明,在xml中写具体实现就OK了。

    ④对以上查询操作进行测试:

    (我们利用service中的类调用mapper,而controller里的类去调用service)

    (1)service相关代码:

    1. package com.example.demo.service;
    2. import com.example.demo.mapper.UserMapper;
    3. import com.example.demo.model.UserInfo;
    4. import org.springframework.stereotype.Service;
    5. import javax.annotation.Resource;
    6. @Service
    7. public class UserService {
    8. @Resource
    9. private UserMapper userMapper;//因为是mybatis接口,所以可以用
    10. public UserInfo getUserById(Integer id){
    11. return userMapper.getUserById(id);
    12. }
    13. }

    (2)Controller相关代码:

    1. package com.example.demo.controller;
    2. import com.example.demo.model.UserInfo;
    3. import com.example.demo.service.UserService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.stereotype.Controller;
    6. import org.springframework.web.bind.annotation.RequestMapping;
    7. import org.springframework.web.bind.annotation.RestController;
    8. @RestController
    9. public class UserController {
    10. @Autowired
    11. private UserService userService;
    12. @RequestMapping("/getUserById")
    13. public UserInfo getUserById(Integer id){
    14. if (id==null)return null;
    15. return userService.getUserById(id);
    16. }
    17. }

    输出结果:

    对应数据库中内容进行查看:

     一致的,查询成功

    ⑤MyBatis的执行过程:

     这也就是为什么我们在④中需要引入controller下的类,以及service下的类,已经他们返回的代码的意义所在。

    注意:为了更容易的排查sql中的问题,我们在开发环境中application-dev.yml设置日志进行打印(这个也是固定的写法)

    1. # 开启 MyBatis SQL 打印
    2. logging:
    3. level:
    4. com:
    5. example:
    6. demo: debug
    7. mybatis:
    8. configuration:
    9. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    写后我们运行程序成功,就可以在控制台上看到:

    2.2使用mybatis进行增删查改操作

    2.2.1查询操作

    ①在Mapper接口中声明一个方法:(注意!!!Mapper接口中,必须得有@Mapper注解,否则是不能够与xml产生映射的)

    ② 在xml中执行查询操作:使用预处理符#{}或者替换符${}来将程序传入的参数替换到sql语句中:

     ③查询结果:

    2.2.2使用springboot进行单元测试介绍

    ①什么是单元测试?

    1、可以非常简单、直观、快速的测试某个功能是否正确。
    2、使用单元测试可以帮我们在打包的时候,发现一些问题,因为在打包之前,所以的单元测试必须通过,否则不能打包成功。
    3、使用单元测试,在测试功能的时候,可以不污染连接的数据库,也就是可以不对数据库进行任何改变的情况下,测试功能的正确性。
    ②为什么使用单元测试?

    因为其可以不污染数据库,因此我们可以在添加进去前进行测试

    ③如何创建单元测试?

    (1)框架支持(在我们创建spring boot项目时会自动进行添加,所以这个地方不做过多说明)

    (2)我们在需要测试方法的所在类中,右键点击Generate,Test,然后对测试的内容进行勾选。(下面我们以测试UserMapper类中的getUserById为例)

    a.

    b.

    c.

    (3)进入测试页面后,我们先选择添加配置单元测试类的注解:@SpringBootTest注解

    (4)在测试方法上添加@Test注解

    (5)注入Mapper对象,调用里面操作数据库的方法,进行单元测试。

    a.直接输出结果方式进行测试: 

     (注意:在一个测试中是可以有多个测试方法,且每个测试方法都可以独立地进行启动)

     输出结果如下:

    b.通过断言来进行测试:(断言常用方法如下)

    示例:(我们以assert不为null来进行判断,如果不为null,就会返回√,否则则表示测试用例不通过) 

    这就表示测试例成功。

    失败显示如下:(很显然id=1的是不为null 的)

     (6)使用@Transactional注解可以防止污染数据库

    使用这个注解后,是不会修改数据库里的内容的,因此当我们进行增删查改的时候,可以先这样进行测试看到底有没有问题,再进行后续操作。这个在下面的操作中也会进行演示。

    2.2.3修改操作

    ①在Mapper接口中声明一个方法:(注意!!!Mapper接口中,必须得有@Mapper注解,否则是不能够与xml产生映射的)

    1. //根据id来修改用户名称,且返回值为影响的行数
    2. public Integer updateName(@Param("id")Integer id,@Param("username")String name);

    ② 在xml中执行查询操作:使用预处理符#{}或者替换符${}来将程序传入的参数替换到sql语句中:

    1. <update id="updataName">
    2. update userinfo set username=#{username} where id=#{id}
    3. update>

     ③测试代码:

    1. @Test
    2. @Transactional
    3. void updateName() {
    4. int result = userMapper.updateName(1, "李四");
    5. Assertions.assertSame(1,result);
    6. }

    测试结果:

    我们可以发现测试是通过了的,但是由于我们加了@Transactional这个注解的话,数据库是不会进行实际的修改的,我们可以查一下:

    ④我们去掉测试代码中的 @Transactional,来看一下是否会更改数据库的值

    仍然是通过了测试,这个时候,我们来查询一下数据库:

     ⑤我们也可以通过类似于上述查询的方式,在url中对数据库的内容进行修改:

    在UserService,UserController中分别添加如下内容:

    (我们返回的仍然是受影响的行数) 

     输出结果:

    此时,我们查看数据库,看username是否已经被改成了lisi。 

     

    2.2.4删除操作

    ①声明方法:

    1. //根据id删除某一个用户的信息,返回受影响行数
    2. public Integer deleteUser(@Param("id")Integer id);

    ②在xml中编写sql:

    1. <delete id="deleteUser">
    2. delete from userInfo where id=#{id};
    3. delete>

    ③测试代码:

    1. @Test
    2. @Transactional
    3. void deleteUser(){
    4. int result=userMapper.deleteUser(1);
    5. Assertions.assertSame(1,result);
    6. }

    ④输出结果:

    测试成功,因为本身这个数据表就只有一行数据,这里就不真正删除啦 

    2.2.5增添操作

    增加的操作会相对复杂一点。我们声明方法中的形参传入一个UserInfo对象

    ①返回一个参数

    (1)声明方法:

    1. //插入一行数据,返回受影响的行数
    2. public Integer add(UserInfo userInfo);

    (2)在xml中编写sql:

    1. <insert id="add">
    2. insert into userinfo(username, password, photo) values (#{username}, #{password},#{photo});
    3. insert>

    (3)测试代码:

    1. @Test
    2. void add(){
    3. UserInfo userInfo=new UserInfo();
    4. userInfo.setId(2);
    5. userInfo.setUsername("张三");
    6. userInfo.setPhoto("abc.png");
    7. userInfo.setPassword("123456");
    8. int result=userMapper.add(userInfo);
    9. Assertions.assertSame(1,result);
    10. }

    (4)输出结果:

    测试成功,此时只返回了一个参数

     我们来查看该表现在的内容:

     ②返回多个参数:

    比如返回受影响的行数和自增id的值,这个时候我们就需要对xml的insert标签进行配置。

    (1)声明:

     public Integer addId(UserInfo userInfo);

    (2)xml中:(注意!!!insert标签中还需要设置useGeneratedKeys="true"表示为自增主键,keyProperty="id"表示哪一个是自增主键)

    1. <insert id="addId" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    2. insert into userinfo(username, password, photo) values (#{username}, #{password},#{photo});
    3. insert>

    (3)测试代码:

    1. @Test
    2. void addId() {
    3. UserInfo userInfo = new UserInfo();
    4. userInfo.setUsername("王五");
    5. userInfo.setPassword("123456");
    6. userInfo.setPhoto("default.png");
    7. System.out.println("插入之前的id=" + userInfo.getId());
    8. int result = userMapper.addId(userInfo);
    9. System.out.println("插入之后的id=" + userInfo.getId());
    10. Assertions.assertSame(1,result);
    11. }

    (4)输出结果:

    测试成功 

     查看现在的数据表:

    最后尝试通过名字来改id,上面我们看到张三的id为3,我们来试一试能不能改为2:

    ①声明方法:

     public Integer updateidByname(Integer id,String username);

    ②在xml中修改:

    1. <update id="updateidByname">
    2. update userInfo set id=#{id} where username=#{username};
    3. update>

    ③测试代码:

    1. @Test
    2. void updateidByname(){
    3. int result = userMapper.updateidByname(2, "张三");
    4. Assertions.assertSame(1,result);
    5. }

    ④输出结果:

    测试成功

    本期MyBatis到此结束,这一期的内容可以支撑我们做SSM项目了,下期,我们将延伸一下。 

  • 相关阅读:
    计算机网络---TCP
    机器学习每周挑战——旅游景点数据分析
    HCIP练习(OSPF)
    JVM调优工具使用
    请解释一下React中的条件渲染(conditional rendering)。
    为何越来越多人选择进入软件测试行业?深度剖析软件测试的优势...
    Ninja: Towards Transparent Tracing and Debugging on ARM【TEE的应用】
    户外运动耳机推荐、十大户外运动耳机品牌推荐排名清单
    【追光者】大学即(已)将(经)毕业,四年,我的所感所想(部分)。
    LayUi-----------用户管理
  • 原文地址:https://blog.csdn.net/weixin_58850105/article/details/127633633