SpringBoot如何优雅的使用MyBatis之MyBatis-Plus

SpringBoot如何优雅的使用MyBatis之MyBatis-Plus

MyBatis-Plus 是 MyBatis 的第三方使用插件。

1、MyBatis-Plus 介绍

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、

提高效率而生。

官网地址:https://mybatis.plus/,本文大部分内容参考自官网。

特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作。

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,

    更有强大的条件构造器,满足各类使用需求。

  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错。

  • 支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、

    SQLServer2005、SQLServer 等多种数据库。

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List

    查询。

2、快速上手

2.1 准备数据

我们首先设计一个这样的用户表,如下:

idnameageemail
1neo18smile1@baomidou.com
2keep36smile2@baomidou.com
3pure28smile3@baomidou.com
4smile21smile4@baomidou.com
5it24smile5@baomidou.com

我们要创建两个 Sql 文件,以便项目启动的时候,将表结构和数据初始化到数据库。

表结构文件(schema-h2.sql)内容:

DROP TABLE IF EXISTS user;
CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

表数据文件(data-h2.sql)内容:

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'neo', 18, 'smile1@ityouknow.com'),
(2, 'keep', 36, 'smile@ityouknow.com'),
(3, 'pure', 28, 'smile@ityouknow.com'),
(4, 'smile', 21, 'smile@ityouknow.com'),
(5, 'it', 24, 'smile@ityouknow.com');

在示例项目的 resources 目录下创建 db 文件夹,将两个文件放入其中。

2.2 添加依赖

添加相关依赖包,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.4.RELEASE</version>
	</parent>

	<groupId>com.example</groupId>
	<artifactId>spring-boot-mybatis-plus</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-mybatis-plus</name>
	<description>spring-boot-mybatis-plus</description>
	<packaging>jar</packaging>


	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.1.1</version>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

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

</project>
  • lombok,帮忙省略掉 Get/Set 方法。

  • mybatis-plus-boot-starter,MyBatis Plus 的依赖包。

  • h2,本次测试我们使用内存数据库 h2 来演示。

  • spring-boot-starter-test,Spring Boot 的测试包。

2.3 配置文件

# DataSource Config
spring:
    datasource:
        driver-class-name: org.h2.Driver
        schema: classpath:db/schema-h2.sql
        data: classpath:db/data-h2.sql
        url: jdbc:h2:mem:test
        username: root
        password: test
# Logger Config
logging:
    level:
      com.neo: debug

配置了 h2 数据库,已经项目的日志级别。配置 schema 和 data 后,项目启动时会根据配置的文件地址来执行数

据。

2.4 业务代码

创建 MybatisPlusConfig 类,指定 Mapper 地址,启用分页功能。

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

创建实体类 User

package com.example.model;

import lombok.Data;

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

@Data 为 lombok 语法,自动注入 getter/setter 方法。

接下来创建对象对于的 Mapper。

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.User;
import org.springframework.stereotype.Component;

@Component
public interface UserMapper extends BaseMapper<User> {

}

以上业务代码就开发完成了,是不是很简单。

启动类

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {

		SpringApplication.run(Application.class, args);
	}

}

2.5 测试

package com.example;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mapper.UserMapper;
import com.example.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyBatisPlusTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelectOne() {
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }

    @Test
    public void testInsert() {
        User user = new User();
        user.setName("tom");
        user.setAge(3);
        user.setEmail("neo@tooool.org");
        assertThat(userMapper.insert(user)).isGreaterThan(0);
        // 成功直接拿会写的ID
        assertThat(user.getId()).isNotNull();
    }

    @Test
    public void testDelete() {
        assertThat(userMapper.deleteById(3L)).isGreaterThan(0);
        assertThat(userMapper.delete(new QueryWrapper<User>().lambda().eq(User::getName, "smile"))).isGreaterThan(0);
    }

    @Test
    public void testUpdate() {
        User user = userMapper.selectById(2);
        assertThat(user.getAge()).isEqualTo(36);
        assertThat(user.getName()).isEqualTo("keep");

        userMapper.update(null, Wrappers.<User>lambdaUpdate().set(User::getEmail, "123@123").eq(User::getId, 2));
        assertThat(userMapper.selectById(2).getEmail()).isEqualTo("123@123");
    }

    @Test
    public void testSelect() {
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }

    @Test
    public void testSelectCondition() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("max(id) as id");
        List<User> userList = userMapper.selectList(wrapper);
        userList.forEach(System.out::println);
    }

    @Test
    public void testPage() {
        System.out.println("----- baseMapper 自带分页 ------");
        Page<User> page = new Page<>(1, 2);
        IPage<User> userIPage = userMapper.selectPage(page, new QueryWrapper<User>().gt("age", 6));
        assertThat(page).isSameAs(userIPage);
        System.out.println("总条数 ------> " + userIPage.getTotal());
        System.out.println("当前页数 ------> " + userIPage.getCurrent());
        System.out.println("当前每页显示数 ------> " + userIPage.getSize());
        print(userIPage.getRecords());
        System.out.println("----- baseMapper 自带分页 ------");
    }

    private <T> void print(List<T> list) {
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(System.out::println);
        }
    }
}

分步讲解

创建 MyBatisPlusTest 类,注入上面创建的 UserMapper 类。

package com.example;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mapper.UserMapper;
import com.example.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyBatisPlusTest {

    @Autowired
    private UserMapper userMapper;

}

测试查询单挑数据,并输出:

@Test
public void testSelectOne() {
    User user = userMapper.selectById(1L);
    System.out.println(user);
}
User(id=1, name=neo, age=18, email=smile1@ityouknow.com)

测试添加数据:

@Test
public void testInsert() {
    User user = new User();
    user.setName("tom");
    user.setAge(3);
    user.setEmail("neo@tooool.org");
    assertThat(userMapper.insert(user)).isGreaterThan(0);
    // 成功直接拿会写的 ID
    assertThat(user.getId()).isNotNull();
}

assertThat() 是 Assert 的一个精通方法,用来比对返回结果,包来自

import static org.assertj.core.api.Assertions.assertThat

测试删除数据

@Test
public void testDelete() {
    assertThat(userMapper.deleteById(3L)).isGreaterThan(0);
    assertThat(userMapper.delete(new QueryWrapper<User>()
            .lambda().eq(User::getName, "smile"))).isGreaterThan(0);
}

QueryWrapper 是 MyBatis-Plus 内部辅助查询类,可以使用 lambda 语法,也可以不使用。利用 QueryWrapper

类可以构建各种查询条件。

测试更新数据

@Test
public void testUpdate() {
    User user = userMapper.selectById(2);
    assertThat(user.getAge()).isEqualTo(36);
    assertThat(user.getName()).isEqualTo("keep");

    userMapper.update(
            null,
            Wrappers.<User>lambdaUpdate().set(User::getEmail, "123@123").eq(User::getId, 2)
    );
    assertThat(userMapper.selectById(2).getEmail()).isEqualTo("123@123");
}

测试查询所有数据

@Test
public void testSelect() {
    List<User> userList = userMapper.selectList(null);
    Assert.assertEquals(5, userList.size());
    userList.forEach(System.out::println);
}
User(id=1, name=neo, age=18, email=smile1@ityouknow.com)
User(id=2, name=keep, age=36, email=smile@ityouknow.com)
User(id=3, name=pure, age=28, email=smile@ityouknow.com)
User(id=4, name=smile, age=21, email=smile@ityouknow.com)
User(id=5, name=it, age=24, email=smile@ityouknow.com)

按照条件查询

@Test
public void testSelectCondition() {
	QueryWrapper<User> wrapper = new QueryWrapper<>();
	wrapper.select("max(id) as id");
	List<User> userList = userMapper.selectList(wrapper);
	userList.forEach(System.out::println);
}
User(id=5, name=null, age=null, email=null)

测试非分页查询

@Test
public void testPage() {
    System.out.println("----- baseMapper 自带分页 ------");
    Page<User> page = new Page<>(1, 2);
    IPage<User> userIPage = userMapper.selectPage(page, new QueryWrapper<User>()
            .gt("age", 6));
    assertThat(page).isSameAs(userIPage);
    System.out.println("总条数 ------> " + userIPage.getTotal());
    System.out.println("当前页数 ------> " + userIPage.getCurrent());
    System.out.println("当前每页显示数 ------> " + userIPage.getSize());
    print(userIPage.getRecords());
    System.out.println("----- baseMapper 自带分页 ------");
}

private <T> void print(List<T> list) {
	if (!CollectionUtils.isEmpty(list)) {
		list.forEach(System.out::println);
	}
}
----- baseMapper 自带分页 ------
总条数 ------> 5
当前页数 ------> 1
当前每页显示数 ------> 2
User(id=1, name=neo, age=18, email=smile1@ityouknow.com)
User(id=2, name=keep, age=36, email=smile@ityouknow.com)
----- baseMapper 自带分页 ------

查询大于 6 岁的用户,并且分页展示,每页两条数据,展示第一页。

3、总结

简单使用了一下 MyBatis-Plus 感觉是一款挺不错的 MyBatis 插件,使用 MyBatis-Plus 操作数据库确实可以少写

一些代码,另外 MyBatis-Plus 的功能比较丰富,文中仅展示了常用的增删改查和分页查询,如果想进一步学习可

以关注官网示例。

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值