MyBatis 详解 1 -- 环境搭建、查询操作
- 一、MyBatis 是什么
- 二、为什么学习 MyBatis
- 三、MyBatis 查询
- 3.1 前言
- 3.2 创建数据库和表
- 3.3 添加 MyBatis 框架支持
- 添加 MyBatis 和 MySQL 驱动
- 3.4 配置连接字符串 和 MyBatis
- 3.4.1 配置连接字符串
- 3.4.2 配置 MyBatis 中的 XML 路径
- 3.5 添加业务代码
- 3.5.1 MyBatis 实现思路
- 3.5.2 添加实体类
- 3.5.3 添加 mapper 接口 (数据持久层)
- 3.5.4 创建与接口对应的 xml 文件
- 3.6 进行单元测试
- 3.7 更多查询操作
- 根据 id 查 ...
- 3.8 实现完整交互
- 3.8.1 添加 Service
- 3.8.2 添加 Controller
- 3.8.3 验证
一、MyBatis 是什么
MyBatis 是⼀款优秀的持久层框架,它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通⽼式 Java 对象)为数据库中的记录。
简单来说 MyBatis 是更简单完成程序和数据库交互的⼯具,也就是更简单的操作和读取数据库⼯具。
Mybatis 官网:https://mybatis.org/mybatis-3/zh/index.html
二、为什么学习 MyBatis
对于后端开发来说,程序是由以下两个重要的部分组成的:
- 后端程序
- 数据库
而这两个重要的组成部分要通讯,就要依靠数据库连接工具,那数据库连接⼯具有哪些?
之前我们学习的 JDBC 就是,还有我们将要介绍的 MyBatis… 那么已经有 JDBC 了,为什么还要学习 MyBatis?
JDBC 的操作太繁琐了!我们回顾⼀下 JDBC 的操作流程:
- 创建数据库连接池 DataSource
- 通过 DataSource 获取数据库连接 Connection
- 编写要执⾏带 ? 占位符的 SQL 语句
- 通过 Connection 及 SQL 创建操作命令对象 Statement
- 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
- 使⽤ Statement 执⾏ SQL 语句
- 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量
- 处理结果集
- 释放资源
JDBC 详解 博客链接:https://blog.csdn.net/yyhgo_/article/details/128061324
JDBC 整个操作流程非常繁琐,我们不仅要拼接每⼀个参数,而且还要按照模板代码的方式⼀步步操作数据库,并且在每次操作完,还要⼿动关闭连接等… 而所有的这些操作步骤都需要在每个方法中重复书写。
于是我们就想,有没有⼀种⽅法可以更简单、更方便的操作数据库呢?
答案是肯定的,这就是我们学习 MyBatis 的原因,它可以帮助我们更方便、更快速地操作数据库 ~
MyBatis 实际就是对 JDBC 的封装!~
三、MyBatis 查询
3.1 前言
开始搭建 MyBatis 之前,我们先来看⼀下 MyBatis 在整个框架中的定位,框架交互流程图:
MyBatis 也是⼀个 ORM 框架,ORM(Object Relational Mapping),即对象关系映射。在面向对象编程语⾔中,将关系型数据库中的数据与对象建⽴起映射关系,进⽽⾃动的完成数据与对象的互相转换:
- 将输⼊数据(即传⼊对象)+ SQL 映射成原⽣ SQL
- 将结果集映射为返回对象,即输出对象
ORM 把数据库映射为对象:
- 数据库表(table)–> 类(class)
- 记录(record,行数据)–> 对象(object)
- 字段(field) --> 对象的属性(attribute)
⼀般的 ORM 框架,会将数据库模型的每张表都映射为⼀个 Java 类。
也就是说使⽤ MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间的转换,接下来我们来看 MyBatis 的使⽤吧。
3.2 创建数据库和表
博客系统库 ~~
-- 创建数据库
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';
3.3 添加 MyBatis 框架支持
添加 MyBatis 和 MySQL 驱动
此时启动:
此时没有配置数据库的链接地址,所以并不能正常启动,接下来:
3.4 配置连接字符串 和 MyBatis
此步骤需要进⾏两项设置,数据库连接字符串设置和 MyBatis 的 XML ⽂件配置。
3.4.1 配置连接字符串
如果是 application.yml 添加如下内容:
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false
username: root
password: 632yyh..
driver-class-name: com.mysql.cj.jdbc.Driver # 驱动!是固定的~~
注意根据自己的数据库信息稍作修改 ~
(使用的 mysql-connector-java 是 5.x 之前的:com.mysql.jdbc.Driver;大于 5.x:com.mysql.cj.jdbc.Driver)
3.4.2 配置 MyBatis 中的 XML 路径
MyBatis 的 XML 中保存的是查询数据库的具体操作 SQL,配置如下:
# 配置 mybatis xml 的⽂件路径,在 resources/mybatis 创建所有表的 xml ⽂件
mybatis:
mapper-locations: classpath:mybatis/**Mapper.xml
classpath:mybatis
表示存放 .xml 配置文件的路径;
(classpath 是自定义的,习惯性使用 “mapper” / “mybatis”)
**Mapper.xml
表示所有以 Mapper.xml 结尾的都是 mybatis 的配置文件。
除了 .xml 文件,还可以使用注解来完成 sql 语句,但是并不推荐 ~
此时就可以成功启动了。
3.5 添加业务代码
3.5.1 MyBatis 实现思路
下⾯按照后端开发的⼯程思路,也就是下⾯的流程来实现 MyBatis 查询所有⽤户的功能:
3.5.2 添加实体类
添加用户的实体类:
package com.example.demo.model;
import lombok.Data;
import java.util.Date;
/**
* 普通的实体类,用于 Mybatis 做数据库表(userinfo表)的映射
* 注意事项:保证类属性名称和userinfo表的字段完全一致!
*/
@Data
public class UserInfo {
private int id;
private String name;
private String password;
private String photo;
private Date createtime;
private Date updatetime;
private int state;
}
普通的实体类,用于 Mybatis 做数据库表(userinfo表)的映射。
注意事项:保证类属性名称和 userinfo 表的字段 完全一致!
3.5.3 添加 mapper 接口 (数据持久层)
数据持久层的接口定义:
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper // mybaits 接口,此注解一定不能忽略
public interface UserMapper {
// 查询所有的信息
public List<UserInfo> getAll();
}
mybaits 接口,@Mapper 注解一定不能忽略!
- 对应其 .xml 文件
- 其他类可以注入它 (类似五大类注解)
3.5.4 创建与接口对应的 xml 文件
根据前面的设置:
# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
mapper-locations: classpath:mybatis/**Mapper.xml
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="">
</mapper>
编辑 UserMapper.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="getAll" resultType="com.example.demo.model.UserInfo">
select * from userinfo
</select>
</mapper>
<mapper></mapper>
标签:需要指定 namespace 属性,表示命名空间,值为 mapper 接口的全限定名,包括全包名.类名。- 查询操作:
<select>,</select>
标签- 接口中的方法名:
id="getAll"
- 查询返回对象的类型 (包名+类名):
resultType="com.example.demo.model.UserInfo"
3.6 进行单元测试
创建完成后:
生成后,需要添加一些代码:
(设置当前测试的环境为 Spring Boot,并且注入要测试的类[接口])
package com.example.demo.mapper;
import com.example.demo.model.UserInfo;
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 // 当前测试的上下文环境为 springboot
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void getAll() {
List<UserInfo> list = userMapper.getAll();
for (UserInfo user : list) {
System.out.println(user.toString());
}
}
}
先添加一个用户信息:
-- 添加一个用户信息
insert into `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
启动单元测试:
成功查询到了数据:
3.7 更多查询操作
根据 id 查 …
UserMapper 接口:
@Mapper // mybaits 接口,此注解一定不能忽略
public interface UserMapper {
// 查询所有的信息
public List<UserInfo> getAll();
// 根据用户id查询用户
public UserInfo getUserById(@Param("uid") Integer id);
}
@Param("uid") Integer id
:拿到参数“uid”,赋值到变量“id”上。
(加上 @Param 注解通用性更好!)
.xml 文件:
<select id="getUserById" resultType="com.example.demo.model.UserInfo">
select * from userinfo where id=#{uid}
</select>
注意:
select * from userinfo where id=#{uid}
sql 语句这里写的是 uid!是把 uid (sql) 复制给了变量 (id)。
(保持一致就不会出问题了 ~)
进行单元测试:
@Test
void getUserById() {
UserInfo userInfo = userMapper.getUserById(1);
System.out.println(userInfo);
}
方法所在接口没有变,单元测试也是在同样的类中进行的。步骤参考目录 3.6 ~
成功打印了。
根据其他字段来查也是一样的 ~
3.8 实现完整交互
3.8.1 添加 Service
服务层实现代码如下:
package com.example.demo.service;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserInfo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserService {
@Resource
private UserMapper userMapper;
public List<UserInfo> getAll() {
return userMapper.getAll();
}
}
3.8.2 添加 Controller
控制器层实现代码如下:
package com.example.demo.controller;
import com.example.demo.model.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/u")
public class UserController {
@Resource
private UserService userService;
@RequestMapping("/getall")
public List<UserInfo> getAll(){
return userService.getAll();
}
}
3.8.3 验证
启动后,访问 http://localhost:8080/u/getall:
交互成功了 ~