前言
本篇记录我在学习SpringBoot时,引入MybatisPlus的学习经验。一、MybatisPlus
1.1 介绍
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,避免了我们重复的书写CRUD语句;
1.2 启动器坐标
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!-- 基于内存的数据库 方便测试,可换成自己的数据库,但是要注意连接驱动 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
1.2 常用注解
MyBatisPlus提供了一些注解供我们在实体类和表信息出现不对应的时候使用。通过使用注解完成逻辑上的匹配。
1.2.1
注解 | 作用 |
---|---|
@Tablename | 实体类的类名和数据库表名不一致 |
@TableId | 实体类的主键名称和表中主键名称不一致 |
@TableField | 实体类中的成员名称和表中字段名称不一致 |
1.2.2 使用示例
1.2.2.1 @Tablename
处理类名与数据库表名不一致的情况
@TableName("user")
public class Temp {
}
1.2.2.1 @TableId
处理类属性名与数据库表主键字段名不一致的情况
type:生成策略 具体可参考IdType类
// type:生成策略 具体可参考IdType类 /
// 采用雪花算法生成全局唯一主键ASSIGN_ID(3)
@TableId(type = IdType.AUTO)
private Long id;
1.2.2.1 @TableField
处理类属性名与数据库表字段名不一致的情况
// type:生成策略 具体可参考IdType类 /
// 采用雪花算法生成全局唯一主键ASSIGN_ID(3)
@TableId("user_name)
private String username;
// exist 排除非数据库表字段 的属性
@TableField(exist = false)
private String login;
1.3 内置CRUD
具体请看下面的入门案例中的使用
1.4 分页
分页方式可分为三种
1.4.1 MybatisPlus内置分页
使用条件:PaginationInterceptor分页插件
1.4.2 自定义的分页语句
使用条件:自己书写的分页语句
1.4.1 PageHelper分页插件
使用条件:
① PageInterceptor分页拦截器
② 自定义的SQL语句
二、入门案例
1 导入依赖
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kaikeba</groupId>
<artifactId>sb-mp</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.11.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatisplus.version>3.3.2</mybatisplus.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.11</version>
</dependency>
</dependencies>
</project>
2 测试类
UserMapperTest.java
package com.kaikeba.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kaikeba.entity.pojo.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Resource
private UserMapper userMapper;
/**
* 列表查询数据
*/
@Test
public void selectList() {
List<User> users = userMapper.selectList(null);
users.stream().forEach(System.out::println);
Assert.assertEquals(25, users.size());
}
/**
* 插入数据
*/
@Test
public void insert() {
User user = new User();
user.setAge(20);
user.setName("编的");
user.setEmail("1143192667@qq.com");
userMapper.insert(user);
List<User> users = userMapper.selectList(null);
users.stream().forEach(System.out::println);
}
/**
* 主键删除
*/
@Test
public void delete() {
List<User> users = userMapper.selectList(null);
users.stream().forEach(System.out::println);
System.out.println("---------------------------------------");
int i = userMapper.deleteById(24);
System.out.println(i);
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 批量删除
*/
@Test
public void deleteBatch1() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
int delete = userMapper.delete(new QueryWrapper<User>().like("name", "kai"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 批量删除2
*/
@Test
public void deleteBatch2() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
int delete = userMapper.delete(Wrappers.<User>query().like("name", "kaike"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 批量删除3
*/
@Test
public void deleteBatch3() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
int delete = userMapper.delete(Wrappers.<User>query().lambda().like(User::getName, "kaike"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 主键修改
*/
@Test
public void updateById() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
userMapper.updateById(new User().setId(1L).setAge(6000).setEmail("111111"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 批量修改
*/
@Test
public void updateBatch1() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
userMapper.update(null, Wrappers.<User>update().set("name", "211@qq.com").like("name", "kai"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 批量修改
*/
@Test
public void updateBatch2() {
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
userMapper.update(new User().setEmail("123456"), Wrappers.<User>update().like("name", "kai"));
userMapper.selectList(null).stream().forEach(System.out::println);
System.out.println("---------------------------------------");
}
/**
* 查询一个:基本查询
*/
@Test
public void select() {
User user = userMapper.selectOne(Wrappers.<User>query().eq("name", "Jone"));
System.out.println(user);
}
/**
* 投影查询
*/
@Test
public void select2() {
List<User> user = userMapper.selectList(new QueryWrapper<User>().select("name", "id"));
user.stream().forEach(System.out::println);
}
/**
* 分页查询
* Mybatis Plus 内置的分页查询
*/
@Test
public void page() {
IPage<User> page = new Page<>(1, 3);
IPage<User> pr = userMapper.selectPage(page, Wrappers.<User>query());
pr.getRecords().stream().forEach(System.out::println);
}
/**
* 自定义分页查询
* Mybatis Plus 内置的分页查询
*/
@Test
public void pageMy() {
IPage<User> page = new Page<>(1, 3);
IPage<User> pr = userMapper.selectUserByPage(page, new User().setName("kaike"));
pr.getRecords().stream().forEach(System.out::println);
}
/**
* PageHelper分页插件测试
*/
@Test
public void testPageHelper() {
PageHelper.startPage(1, 2);
User u = new User();
u.setAge(20);
PageInfo<User> page = new PageInfo<User>(userMapper.selectUserByPage2(u));
List<User> list = page.getList();
System.out.println("总行数=" + page.getTotal());
System.out.println("当前页=" + page.getPageNum());
System.out.println("每页行数=" + page.getPageSize());
System.out.println("总页数=" + page.getPages());
System.out.println("起始行数=" + page.getStartRow());
System.out.println("是第一页=" + page.isIsFirstPage());
System.out.println("是最后页=" + page.isIsLastPage());
System.out.println("还有下一页=" + page.isHasNextPage());
System.out.println("还有上一页=" + page.isHasPreviousPage());
System.out.println("页码列表" + Arrays.toString(page.getNavigatepageNums()));
}
}
3 配置文件
application.yml
server:
port: 8080
logging:
level:
com.kaikeba: debug
# h2 基于内存的数据库
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
# 关闭thymeleaf缓存
thymeleaf:
cache: false
# 别名 映射配置文件 自定义分页要使用
mybatis-plus:
type-aliases-package: com.kaikeba.entity
mapper-locations: classpath:com/kaikeba/mapper/*.xml
4 h2数据库文件
数据库创建文件:schema-h2.sql
DROP TABLE IF EXISTS user2;
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, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'kaikeba1', 331, 'test4@baomidou.com'),
(6, 'kaikeba2', 331, 'test4@baomidou.com'),
(7, 'kaikeba3', 331, 'test4@baomidou.com'),
(8, 'kaikeba4', 331, 'test4@baomidou.com'),
(9, 'kaikeba5', 331, 'test4@baomidou.com'),
(10, 'kaikeba6', 331, 'test4@baomidou.com'),
(11, 'kaikeba7', 331, 'test4@baomidou.com'),
(12, 'kaikeba8', 331, 'test4@baomidou.com'),
(13, 'kaikeba9', 331, 'test4@baomidou.com'),
(14, 'kaikeba10', 331, 'test4@baomidou.com'),
5 映射配置文件
<?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.kaikeba.mapper.UserMapper">
<sql id="selectSql">
SELECT
*
FROM
user
</sql>
<!-- 自定义分页查询SQL语句 -->
<select id="selectUserByPage" resultType="User">
<include refid="selectSql"></include>
<where>
<if test="c.age !=null">
age = #{c.age}
</if>
<if test="c.email !=null">
and email like '%${c.email}%'
</if>
</where>
</select>
<!-- pageHelper插件sql语句 -->
<select id="selectUserByPage2" resultType="user">
<include refid="selectSql"></include>
<where>
<if test="age !=null">
age = #{age}
</if>
<if test="email !=null">
and email like '%${email}%'
</if>
</where>
</select>
</mapper>
6 启动类MybatislusApplication
package com.kaikeba;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.kaikeba.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
7 实体类User
package com.kaikeba.entity.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author sunyang
* @date 2021/5/31 22:08
*/
@Data
@Accessors(chain = true)
@TableName("user")
public class User {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private Integer age;
private String email;
@TableField(exist = false)
private String sex;
}
8 PageHelper配置类
使用PageHelper分页插件的时候配置上去就行。与MybatisPlus自带的分页查询的配置不冲突。我这里是两种方式的测试都有所以都贴出来。
package com.kaikeba.config;
import com.github.pagehelper.PageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @desc pageHelper配置
* @author sunyang
* @date 2021/6/1 10:43
*/
@Configuration
public class PageHelperConfiguration {
@Bean
public PageInterceptor pageInterceptor() {
return new PageInterceptor();
}
}
9 MybatisPlus分页配置类
使用MybatisPlus分页功能的时候进行配置,与PageHelper的配置不冲突,若是都有使用,两个配置都写上就行。
package com.kaikeba.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author sunyang
* @date 2021/6/1 10:07
*/
@Configuration
public class MybatisPlusPageConfiguration {
/**
* @desc MybatisPlus 分页插件配置
* @date 2021/6/1 10:17
* @auther sunyang
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
// 开启count的join优化 只针对left join
return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
}
}
10 测试结果展示
10.1 内置方法
都一样,可以自己运行,我这只放一个方法的测试结果