本文,我们来了解 MyBatis

什么是 MyBatis

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

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

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

引入 MyBatis

在依赖中添加如下代码:

<!-- MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<!-- MySQL Driver -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

<!-- Lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

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 里面的 <resultMap>

@Results({
  @Result(property = "username", column = "USERNAME"),
  @Result(property = "password", column = "PASSWORD")
})
@Select("SELECT * FROM user")
List<User> 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 语句,或者自己书写。

了解 MyBatis_前端

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<User> 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<User> 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<User> 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<User> getUserList(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<User> userList = userMapper.getUserList();
        return userList;
    }
}

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

<!-- pom.xml -->
<!-- Page Helper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.6</version>
</dependency>

我们新建包 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

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.launch</groupId>
    <artifactId>launch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>launch</name>
    <description>launch</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- Page Helper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

了解 MyBatis_User_02

参考