了解 MyBatis

本文,我们来了解 MyBatis

什么是 MyBatis

下面这段介绍是摘自中文官网:

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

可以概括为:MyBatis 为数据库服务。桥接 Java 原始类型、接口和 老式 Java 对象。

引入 MyBatis

在依赖中添加如下代码:

org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.0
mysql
mysql-connector-java
8.0.33
org.projectlombok
lombok
provided

CRUD 注解

CRUD -> Create,Read,Update,Delete

增删改查是主要的业务操作。

注释 说明 升级版本(3.X)
@Select 用于构建查询语句 @SelectProvider
@Insert 用于构建添加语句 @InsertProvider
@Update 用于构建修改语句 @UpdateProvider
@Delete 用于构建删除语句 @DeleteProvider
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User queryById(@Param("id") int id);
@Insert("INSERT INTO user(name,age) VALUES(#{name},#{age})")
int add(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteById(int id);
@Update("UPDATE user SET name=#{name},age=#{age} WHERE id = #{id}")
int updateById(User user)
}

映射注解

可以直接将对象和数据库之间的映射关系直接定义在 Java 代码中,而不需要编写繁琐的 XML 配置文件(用于建立实体和数据库关系的映射)。有以下三个注解:

注释 说明
@Results 结果集多个字段的映射关系
@Result 结果集单个字段的映射关系
@ResultMap 根据 ID 关联 XML 里面的
@Results({
@Result(property = "username", column = "USERNAME"),
@Result(property = "password", column = "PASSWORD")
})
@Select("SELECT * FROM user")
List list();

简单案例

下面我们实现一个增删改查的案例。

Spring Boot 版本 3.1.2 , java sdk 版本为 17

版本太高,会出现错误 Field userMapper in com.launch.controller.UserController required a bean of type 'com.launch.mapper.UserMapper' that could not be found.

之后将版本 Spring Boot 降为 2.1.3.RELEASE

文末给出完整的 pom.xml

数据表自动初始化

我们在 resources 文件夹下新增 db 目录,新增名为 schema.sql 文件。

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这里,我们将创建表用户表并进行初始化。

application.properties 文件中设定数据库的连接:

spring.datasource.url=jdbc:mysql://localhost:3306/jimmy_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.sql.init.mode=always
spring.datasource.platform=mysql
spring.sql.init.schema-locations=classpath:db/schema.sql

这里设定了连接的数据库为 jimmy_db,并设定了初始化的 schema 路径为 classpath:db/schema.sql

我们运行项目之后,会看到生成了一张 user 表。如果没有生成,可自动导入 SQL 语句,或者自己书写。

user_表.png

User 实体对象建模

我们新建包 modelUser.java 创建 User 实体。

package com.launch.model;
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}

实体和数据表的映射关系

我们新建 mapper 包,并实现 UserMapper.java 接口文件:

package com.launch.mapper;
import com.github.pagehelper.Page;
import com.launch.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user")
List queryAll();
@Select("SELECT * FROM user WHERE id = #{id}")
User queryById(@Param("id") int id);
@Insert({"INSERT INTO user(name,age) VALUES(#{name},#{age})"})
int add(User user);
@Update("UPDATE user SET name=#{name},age=#{age} WHERE id = #{id}")
int updateById(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteById(int id);
// 分页
@Select("SELECT * FROM user")
Page getUserList();
}

我们在类上添加 @Mapper 注解实现实体和数据表的映射关系。当然,也可以在入口类中添加 @MapperScan("com.launch.mapper") 实现,读者可以尝试。

操作数据 API

下面我们在包 controller 下,创建控制器 UserController.java 文件:

package com.launch.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.launch.mapper.UserMapper;
import com.launch.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
UserMapper userMapper;
@GetMapping("/")
List queryAll() {
return userMapper.queryAll();
}
@GetMapping("/query_by_id")
User queryById(int id) {
return userMapper.queryById(id);
}
@PostMapping("/add")
String add(User user) {
return userMapper.add(user) == 1 ? "success" : "failed";
}
@PutMapping("/update_by_id")
String updateById(User user) {
return userMapper.updateById(user) == 1 ? "success" : "failed";
}
@DeleteMapping("/delete_by_id")
String deleteById(int id) {
return userMapper.deleteById(id) == 1 ? "success" : "failed";
}
// 分页
@GetMapping("/list_page")
public Page getUserList(Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
Page userList = userMapper.getUserList();
return userList;
}
}

因为我们需要进行分页,我们引入包:

com.github.pagehelper
pagehelper
4.1.6

我们新建包 config,在文件 PageHelperConfig.java 文件添加:

package com.launch.config;
import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class PageHelperConfig {
@Bean
public PageHelper pageHelper() {
PageHelper pageHelper = new PageHelper();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("readonly", "true");
pageHelper.setProperties(p);
return pageHelper;
}
}

现在,我们正式完成了 CRUD 的内容,我们启动项目后,可以通过下面的操作进行:

作用 请求方法 请求路径
添加用户 POST http://localhost:8080/api/user/query_by_id?id=1
查询所有用户 GET http://localhost:8080/api/user/
查询指定 ID 用户 GET http://localhost:8080/api/user/add?name=Jimmy&age=18
更改指定 ID 用户 PUT http://localhost:8080/api/user/update_by_id?id=1&name=Jimmy007&age=20
删除指定 ID 用户 DELETE http://localhost:8080/api/user/delete_by_id?id=1
分页查询 GET http://localhost:8080/api/user/list_page?pageNum=1&pageSize=1

上面的测试,通过 params 传递参数,感兴趣读者可以优化下。

总结:留意版本之间是否有冲突等

完整的 pom.xml

4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
com.launch
launch
0.0.1-SNAPSHOT
launch
launch
1.8
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.0
org.springframework.boot
spring-boot-devtools
runtime
mysql
mysql-connector-java
runtime
com.github.pagehelper
pagehelper
4.1.6
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.jupiter
junit-jupiter
RELEASE
test
org.springframework.boot
spring-boot-maven-plugin

pexels-ray-bilcliff-17333155.jpg

参考

  • mybatis
  • 《Spring Boot 实战派》
  • Java 中 Spring Boot 使用 MyBatis 访问 MySql 数据库
  • Java Web 编写 Restful API