了解 MyBatis

本文,我们来了解 MyBatis

什么是 MyBatis

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

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

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

引入 MyBatis

在依赖中添加如下代码:

xml 复制代码
<!-- 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
java 复制代码
@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>
java 复制代码
@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 文件。

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 文件中设定数据库的连接:

bash 复制代码
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 实体对象建模

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

java 复制代码
package com.launch.model;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

实体和数据表的映射关系

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

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 文件:

kotlin 复制代码
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;
    }
}

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

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

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

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 复制代码
<?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>

参考

相关推荐
百万蹄蹄向前冲26 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
anlogic27 分钟前
Java基础 8.18
java·开发语言
追逐时光者1 小时前
.NET 使用 MethodTimer 进行运行耗时统计提升代码的整洁性与可维护性!
后端·.net
朝阳5811 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
练习时长一年1 小时前
AopAutoConfiguration源码阅读
java·spring boot·intellij-idea
ssshooter2 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友2 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
源码宝2 小时前
【智慧工地源码】智慧工地云平台系统,涵盖安全、质量、环境、人员和设备五大管理模块,实现实时监控、智能预警和数据分析。
java·大数据·spring cloud·数据分析·源码·智慧工地·云平台
Jerry2 小时前
Jetpack Compose 中的状态
前端