文章目录
MyBatis-Plus入门和使用实践
一、前言
- 环境说明
- 操作系统:Windows 10 专业版
- Mybatis-Plus 版本:3.4.2
- JDK 版本:1.8
- 开发工具:IntelliJ IDEA 2020.2.2
- 简介
-
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性:
- 无侵入、消耗小、强大的 CRUD 操作
- 支持 Lambda 形式调用,支持多种数据库
- 支持主键自动生成,支持 ActiveRecord 模式
- 支持自定义全局通用操作,支持关键词自动转义
- 内置代码生成器,内置分页插件,内置性能分析插件
- 内置全局拦截插件,内置 SQL 注入剥离器
MyBatis-Plus 官网:https://mp.baomidou.com/
MyBatis 官网:https://mybatis.org/mybatis-3/zh/index.html
Spring Data JPA:https://spring.io/projects/spring-data-jpa
Active Record 模式-百度百科:https://baike.baidu.com/item/Active%20Record/3106858?fr=aladdin
二、正文
1.创建项目
1)引入依赖
-
pom.xml
引入依赖 mybatis-plus、lombok、spring-boot
<!-- spring-boot-starter 父工程 -->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<!-- spring-boot 启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring-boot 测试启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis-plus spring-boot 启动器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2)SpringBoot配置
- resources 文件夹创建
application.yml
# mysql 连接配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp-db?useSSL=false&serverTimezone=GMT%2B8
username: root
password: root2020
# 输入日志,查看 sql 语句
logging:
level:
root: warn
org.example.dao: trace
pattern:
console: '%p%m%n'
-
App.java
启动 spring-boot
package org.example;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* spring-boot 启动入口
*
*/
@SpringBootApplication
@MapperScan({"org.example.dao"})
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
}
3)测试数据
- sql 脚本
#创建用户表
CREATE TABLE user (
id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
age INT(11) DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
CONSTRAINT manager_fk FOREIGN KEY (manager_id)
REFERENCES user (id)
) ENGINE=INNODB CHARSET=UTF8;
#初始化数据:
INSERT INTO user (id, name, age, email, manager_id, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
, '2019-01-11 14:20:20'),
(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553
, '2019-02-05 11:12:22'),
(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385
, '2019-02-14 08:31:16'),
(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
, '2019-01-14 09:15:15'),
(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385
, '2019-01-14 09:48:16');
- 创建
entity/User.java
package org.example.entity;
import lombok.Data;
import java.time.LocalDateTime;
/***
* 员工实体类
* */
@Data
public class User {
// 员工 ID
private Long id;
// 姓名
private String name;
// 年龄
private Integer age;
// 邮箱
private String email;
// 上级领导 ID
private Long managerId;
// 创建时间
private LocalDateTime createTime;
}
- 创建
dao/UserMapper.java
(接口)
package org.example.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.example.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
4)测试例子
- 测试类:
AppTest.java
package org.example;
import org.example.dao.UserMapper;
import org.example.entity.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.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class AppTest
{
@Autowired
private UserMapper userMapper;
/**
* 查询列表
* */
@Test
public void select()
{
List<User> users = userMapper.selectList(null);
// 判断预期值与实际值是否相同
// Assert.assertEquals(5, users.size());
// 循环输出
users.forEach(System.err::println);
}
}
2.常用注解
注解 | 说明 |
---|---|
@TableName(“数据库表名”) | 指定实体类对应的数据库表名 |
@TableId | 指定属性作为主键,mp 默认 id 为主键 |
@TableId(type = IdType.ASSIGN_UUID) | 指定属性作为主键,并指定主键策略 |
@TableField(“数据库表字段名”) | 指定属性对应的数据库表字段名 |
@TableField(exist=false) | 实体属性排除映射;将属性标记为非数据库表字段 |
@TableField(condition = SqlCondition.LIKE) | 当实体对象作为条件构造器的查询条件时,属性可进行 like 查询,而非默认的等值(SqlCondition 中还有其它常量可选) |
3.查询
1)普通条件查询
- ID 查询
@Test
public void selectById()
{
// 根据 ID 进行查询
User user = userMapper.selectById(1087982257332887553L);
System.err.println(user);
}
- 批量 ID 查询
@Test
public void selectBatchIds()
{
List<Long> ids = Arrays.asList(1087982257332887553L, 1088248166370832385L);
// 根据 ID 列表进行查询
List<User> users = userMapper.selectBatchIds(ids);
users.forEach(System.err::println);
}
- 根据 map 查询
@Test
public void selectByMap()
{
Map map = new HashMap();
map.put("name", "大boss"); // 数据库表字段名
map.put("age", 40);
// sql:where name = '大boss' and age =40
// 根据 Map {name : value} 进行查询
List<User> users = userMapper.selectByMap(map);
users.forEach(System.err::println);
}
2)条件构造器查询
- 名字中包含’雨’,并且年龄小于 40
where name like ‘%雨%’ and age < 40
@Test
public void selectByWrapper()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 名字中包含’雨’,年龄大于等于 20,且小于等于 40,且邮箱不为空
where name like ‘%雨%’ and age between 20 and 40 and email is not null
@Test
public void selectByWrapper2()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like("name", "雨")
.between("age", 20, 40)
.isNotNull("email"); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 名字姓’张’,或者年龄大于等于 30,按年龄降序排列,年龄相同的按id升序排列
where name like ‘张%’ or age >= 30 order by age desc,id asc
@Test
public void selectByWrapper3()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like("name", "张%")
.or()
.ge("age", 30)
.orderByDesc("age")
.orderByAsc("id"); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 创建日期是’2019-02-14’,且上级领导姓’王’
where date_format(create_time, ‘%Y-%m-%d’)
and manager_id in (select id from user where name like ‘王%’)
@Test
public void selectByWrapper4()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}"
, "2019-02-14") // {0} 参数序号
.inSql("manager_id"
, "select id from user where name like '王%'");
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 姓’王’,且(年龄小于 40 或邮箱不为空)
where name like ‘王%’ and (age<40 or email is not null)
@Test
public void selectByWrapper5()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.likeRight("name", "王")
.and( wq->wq.lt("age", 40)
.or()
.isNotNull("email")
); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 姓’王’,或者(年龄小于 40 且大于 20 且邮箱不为空)
where name like ‘王%’ or (age<40 and age>20 and email is not null)
@Test
public void selectByWrapper6()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.likeRight("name", "王")
.or( wq->wq.lt("age", 40)
.gt("age", 20)
.isNotNull("email")
); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- (年龄小于 40 或邮箱不为空) 且姓’王’
where (age<40 or email is not null) and name like ‘王%’
@Test
public void selectByWrapper7()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.nested( wq->wq.lt("age", 40).or().isNotNull("email") )
.likeRight("name", "王"); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 年龄包含 30、31、34
where age in (30, 31, 34)
@Test
public void selectByWrapper8()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.in("age", Arrays.asList(30, 31, 32)); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 仅获取一条数据
limit 1
@Test
public void selectByWrapper9()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.in("age", Arrays.asList(30, 31, 32))
.last("limit 1"); // last 方法存在 sql 注入的风险
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
3)Lambda条件构造器
- 使用 lambda 表达式,可以避免数据库表字段名误写
@Test
public void selectByWrapperLambda()
{
// LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
// LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda();
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.like(User::getName, "雨").lt(User::getAge, 40);
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(lambdaQueryWrapper);
users.forEach(System.err::println);
}
- 链式编程
@Test
public void selectByWrapperChain()
{
List<User> users = new LambdaQueryChainWrapper<User>( userMapper )
.like(User::getName, "雨")
.lt(User::getAge, 40)
.list();
users.forEach(System.err::println);
}
4)常用查询
排除查询字段
- 名字包含’雨’,且年龄小于 40 ( 只查询 id 和 name 字段 )
select id,name from user where name like ‘雨%’ and age < 40
@Test
public void selectByWrapper10()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.select("id", "name")
.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
- 名字包含’雨’,且年龄小于 40 ( 查询排除 create_time 和 manager_id )
select id,name,age,email from user where name like ‘雨%’ and age < 40
@Test
public void selectByWrapper11()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.select(User.class, u->!u.getColumn().equals("create_time")
&&!u.getColumn().equals("manager_id"))
.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
是否使用某个条件
- 如果 name 或 email 为空,则不使用该条件进行查询
@Test
public void selectByWrapper12()
{
String name = "雨";
String email = "";
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like(StringUtils.isNotBlank(name), "name", name)
.like(StringUtils.isNotBlank(email), "email", email); // 数据库表字段名
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
实体对象作为条件
- 名字是’李艺伟’,且年龄是28
where name=‘李艺伟’ and age=28
@Test
public void selectByWrapper13()
{
User user = new User();
user.setName("李艺伟");
user.setAge(28);
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query(user);
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
注意: 默认为等值查询,如果需要模糊查询,需要在实体类的属性中添加注解
@TableField(condition = SqlCondition.LIKE)
例如:
@TableField(condition = SqlCondition.LIKE) private String name;
条件全匹配
- 1.查询条件全匹配,包括 null 也会作为查询条件
- 2.设置 false 时;如果参数为 null,则参数会排除,不作为查询条件
- 3.通过函数,可排除某些字段作为查询条件
@Test
public void selectByWrapperAllEq()
{
Map map =new HashMap();
map.put("name", "大boss");
map.put("email", null);
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
// 1.全匹配
// queryWrapper.allEq(map);
// 2.设置为 false 时,如果参数为 null,则参数会排除,不作为查询条件
// queryWrapper.allEq(map, false);
// 3.通过函数,排除某些字段作为查询条件;例如:排除 name 字段作为查询条件
queryWrapper.allEq((k,v)->!k.equals("name"), map);
// 根据条件构造器进行查询
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.err::println);
}
Map结果(统计)
- 返回 Map 对象,可避免实体对象因为排除查询字段后,大多数字段为空的情况
@Test
public void selectByWrapperMaps()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.select("id", "name")
.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
users.forEach(System.err::println);
}
- 按上级领导分组,查询分组的评价年龄,最大年龄,最小年龄,并且只取年龄总和小于500的分组
SELECT AVG(age) avg_age, MIN(age) min_age, MAX(age) max_age
FROM user
GROUP BY manager_id
HAVING SUM(age) < 500
@Test
public void selectByWrapperMaps2()
{
// 创建条件构造器
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.select("AVG(age) avg_age", "MIN(age) min_age", "MAX(age) max_age")
.groupBy("manager_id")
.having("SUM(age) < {0}", 500); // 数据库表字段名
// 根据条件构造器进行查询
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
users.forEach(System.err::println);
}
其它查询
- 仅获取第一列数据,如下查询,仅输出 id 字段的数据
@Test
public void selectByWrapperObjs()
{
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.select("id", "name")
.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
List<Object> users = userMapper.selectObjs(queryWrapper);
users.forEach(System.err::println);
}
- 统计记录数
注意:不能指定字段
@Test
public void selectByWrapperCount()
{
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like("name", "雨")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
Integer count = userMapper.selectCount(queryWrapper);
System.out.println("总记录数:"+count);
}
- 查询一条数据
注意:查询结果有多条时,会报错
@Test
public void selectByWrapperOne()
{
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.like("name", "张雨琪")
.lt("age", 40); // 数据库表字段名
// 根据条件构造器进行查询
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
5)自定义SQL
接口类实现
dao/UserMapper.java
- 条件构造器作为sql参数
package org.example.dao;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.entity.User;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
/**
* 根据条件构造器进行查询
* */
@Select("select * from user ${ew.customSqlSegment}")
public List<User> selectByWrapper(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
- 测试类:
AppTest.java
@Test
public void selectByWrapperSQL()
{
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.like(User::getName, "雨").lt(User::getAge, 40);
// 根据条件构造器进行查询
List<User> users = userMapper.selectByWrapper(lambdaQueryWrapper);
users.forEach(System.err::println);
}
XML实现
-
application.yml
配置 mybatis-plus 的 mapper 文件目录
# mybatis-plus
mybatis-plus:
# mapper 目录
mapper-locations: classpath*:mapper/*Mapper.xml
-
resources/mapper/UserMapper.xml
(resources 资源目录下) - 条件构造器作为sql参数
<?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">
<!--
namespace:命名空间,指定为接口的全类名
-->
<mapper namespace="org.example.dao.UserMapper">
<!--接口方式:
id:接口方法名 ,resultType:返回类型
-->
<select id="selectByWrapperXML" resultType="org.example.entity.User">
select * from user ${ew.customSqlSegment}
</select>
</mapper>
dao/UserMapper.java
package org.example.dao;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.entity.User;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
/**
* 根据条件构造器进行查询,SQL 语句配置在 XML 文件中
* */
public List<User> selectByWrapperXML(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
- 测试类:
AppTest.java
@Test
public void selectByWrapperSQL2()
{
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.like(User::getName, "雨").lt(User::getAge, 40);
// 根据条件构造器进行查询
List<User> users = userMapper.selectByWrapperXML(lambdaQueryWrapper);
users.forEach(System.err::println);
}
6)分页查询
mybatis 分页仅实现了逻辑分页,即将数据全部加载到内存,然后再分页。
Config配置
- 创建
config/MybatisPlusConfig.java
package org.example.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}
BaseMapper分页查询
- 测试类:
AppTest.java
@Test
public void selectByWrapperPage()
{
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.gt(User::getAge, 20);
// 分页查询
// Page<User> page = new Page<>(1, 3);
// IPage<User> iPage = userMapper.selectPage(page, lambdaQueryWrapper);
// Map
Page page = new Page<>(1, 3);
IPage<Map<String, Object>> iPage = userMapper.selectMapsPage(page, lambdaQueryWrapper);
// 输出结果
System.err.println("当前页:"+iPage.getCurrent());
System.err.println("总页数:"+iPage.getPages());
System.err.println("总记录数:"+iPage.getTotal());
iPage.getRecords().forEach(System.err::println);
}
- 屏蔽总记录数的查询
Page<User> page = new Page<>(1, 3, false);
自定义SQL分页查询
dao/UserMapper.java
package org.example.dao;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.entity.User;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
/**
* 分页查询
* */
public IPage<User> selectUserPage(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
-
resources/mapper/UserMapper.xml
(resources 资源目录下)
<?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">
<!--
namespace:命名空间,指定为接口的全类名
-->
<mapper namespace="org.example.dao.UserMapper">
<!--接口方式:
id:接口方法名 ,resultType:返回类型
-->
<select id="selectUserPage" resultType="org.example.entity.User">
select * from user ${ew.customSqlSegment}
</select>
</mapper>
- 测试类:
AppTest.java
@Test
public void selectByWrapperPage2()
{
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.gt(User::getAge, 20);
// 分页查询
Page<User> page = new Page<>(1, 3);
IPage<User> iPage = userMapper.selectUserPage(page, lambdaQueryWrapper);
// 输出结果
System.err.println("当前页:"+iPage.getCurrent());
System.err.println("总页数:"+iPage.getPages());
System.err.println("总记录数:"+iPage.getTotal());
iPage.getRecords().forEach(System.err::println);
}
4.增删改
新增
- 测试类:
AppTest.java
@Test
public void insert()
{
User user = new User();
user.setName("李小龙");
user.setAge(22);
user.setEmail("lxl@163.com");
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
// 插入数据
int num = userMapper.insert(user);
System.err.println("影响记录数据:"+num);
System.err.println("主键:"+user.getId());
}
更新
- 根据 ID 更新
@Test
public void updateById()
{
User user = new User();
user.setId(1094592041087729666L);
user.setAge(31);
// 更新数据
int num = userMapper.updateById(user);
System.err.println("影响记录数据:"+num);
}
- 根据条件构造器更新
@Test
public void updateByWrapper()
{
// 条件构造器
UpdateWrapper updateWrapper = new UpdateWrapper();
updateWrapper.eq("name", "刘红雨");
// 更新实体对象
User user = new User();
user.setAge(34);
// 更新数据
int num = userMapper.update(user,updateWrapper);
System.err.println("影响记录数据:"+num);
}
- 条件构造器中 set 方法,更新少量字段时使用
@Test
public void updateByWrapper2()
{
// 条件构造器
/*UpdateWrapper<User> updateWrapper = new UpdateWrapper();
updateWrapper.eq("name", "刘红雨").set("age", 30);*/
// Lambda 条件构造器
LambdaUpdateWrapper<User> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.eq(User::getName, "刘红雨").set(User::getAge, 30); // set 方法设置修改的值
// 更新数据
int num = userMapper.update(null,lambdaUpdateWrapper);
System.err.println("影响记录数据:"+num);
// 链式编程
boolean isUpdate = new LambdaUpdateChainWrapper<User>(userMapper)
.eq(User::getName, "刘红雨")
.set(User::getAge, 30)
.update();
System.err.println("更新成功:"+isUpdate);
}
删除
- 根据 ID 删除
@Test
public void deleteById()
{
Long userid = 1359388531205722114L;
// 删除数据
int num = userMapper.deleteById(userid);
System.err.println("影响记录数据:"+num);
}
- 其它删除方法
@Test
public void deleteByMap()
{
Map<String, Object> map =new HashMap<>();
map.put("name", "刘红雨");
map.put("age", 30);
// 删除数据
int num = userMapper.deleteByMap(map);
System.err.println("影响记录数据:"+num);
}
@Test
public void deleteByBatchId()
{
List<Long> ids = Arrays.asList(123123123123L, 1233435234534L);
// 删除数据
int num = userMapper.deleteBatchIds(ids);
System.err.println("影响记录数据:"+num);
}
- 条件构造器删除
@Test
public void deleteByBWrapper()
{
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(User::getId, 12312312312312L);
// 删除数据
int num = userMapper.delete(lambdaQueryWrapper);
System.err.println("影响记录数据:"+num);
}
5. AR模式
百度百科:[https://baike.baidu.com/item/Active%20Record/3106858?fr=aladdin](https://baike.baidu.com/item/Active Record/3106858?fr=aladdin)
- Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
具体操作
- 实体对象继承
com.baomidou.mybatisplus.extension.activerecord.Model
(当前为 User) - 编写好继承了
com.baomidou.mybatisplus.core.mapper.BaseMapper
的Mapper
(当前为 UserMapper)
entity/UserMapper.java
package org.example.entity;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import java.time.LocalDateTime;
/***
* 员工实体类
* */
@Data
public class User extends Model {
// 用户 ID
private Long id;
// 姓名
private String name;
// 年龄
private Integer age;
// 邮箱
private String email;
// 上级领导 ID
private Long managerId;
// 创建时间
private LocalDateTime createTime;
}
- 测试类:
ARTest.java
@Test
public void arSelect()
{
User user = new User();
// 查询数据
List<User> users = user.selectAll();
// 循环输出
users.forEach(System.err::println);
}
@Test
public void arInsert()
{
User user = new User();
user.setName("路飞");
user.setAge(25);
user.setEmail("lf@163.com");
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
// 新增数据
boolean isInsert = user.insert();
System.out.println("新增成功:"+isInsert);
}
@Test
public void arUpdate()
{
User user = new User();
user.setId(1359800186100056065L);
user.setName("路飞飞");
// 修改数据
boolean isUpdate = user.updateById();
System.out.println("更新成功:"+isUpdate);
}
@Test
public void arDelete()
{
User user = new User();
user.setId(1359800186100056065L);
// 删除数据
boolean isDelete = user.deleteById();
System.out.println("删除成功:"+isDelete);
}
6.主键策略
- 默认是基于雪花算法的主键策略
com.baomidou.mybatisplus.annotation.IdType.java
IdType | 说明 |
---|---|
AUTO(0) | 数据库 ID 自增 |
NONE(1) | 该类型为未设置主键类型 (注解里等于跟随全局,全局里约等于 INPUT) |
INPUT(2) | 用户输入 ID; |
ASSIGN_ID(3) | 分配ID (主键类型为number或string);默认 雪花算法 |
ASSIGN_UUID(4) | 分配UUID (主键类型为 string) |
全局策略配置
resources/application.yml
# mybatis-plus
mybatis-plus:
# 全局主键配置
global-config:
db-config:
id-type: assign_id
7.MP配置
MP配置官网文档:https://mp.baomidou.com/config/
- 基本配置、全局配置、数据库配置
8.通用Service
- Service 接口继承
com.baomidou.mybatisplus.extension.service.IService
- Service 实现继承
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
- 具体操作,参考 dao 的操作