这是我的gitee地址,可以在上面拉代码下来看,对照看比较容易理解
https://gitee.com/workRep/spring-cloud-learn.git
1、MyBatis-plus快速入门使用
MyBatis-Plus的官方网站,上面有很详细的各种文档,后续需要可以去查询
简介 | MyBatis-Plus
https://baomidou.com/introduce/首先我们需要知道一点,Mybatisplus是可以完美兼容MyBatis的,也就是说,如果你之前用的是MyBatis的话,可以无感切换成Mybatisplus的
MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
这是他官网上的一句话,用来定义和描述Mybatisplus的
如果之前是Mybatis的项目的话,直接把依赖替换成Mybatisplus的就可以了,照常可以使用的
<!-- <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
导入之后记得刷新依赖
如果是直接使用Mybatisplus的话,新建了Springboot项目之后,除了依赖的添加,还需要添加配置文件
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 密码
driver-class-name: com.mysql.cj.jdbc.Driver
SQL
CREATE TABLE `user` (
`id` bigint NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
`create_by` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(255) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` varchar(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '0',
`remark` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
这边新建一个BaseEntity
package com.jha.springcloudlearn.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class BaseEntity implements Serializable {
//创建人,插入时自动填充
//@TableField(fill = FieldFill.INSERT)
private String createBy;
//更新人,插入时自动填充
//@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
//创建时间,插入时自动填充
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
//更新时间,插入时自动填充
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
//逻辑删除字段
@TableLogic
private String delFlag;
/**
* 备注
*/
@TableField(exist = false)
private String remark;
}
新建一个User实体类
package com.jha.springcloudlearn.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(
value = "user", // 指定表名为 user
schema = "mybatis", // 指定数据库 Schema 为 mybatis
keepGlobalPrefix = true, // 保持使用全局表前缀
resultMap = "userResultMap", // 指定 XML 中的 resultMap ID
autoResultMap = true, // 自动构建 resultMap
excludeProperty = {"pwd", "salt"} // 排除 password 和 salt 属性
)
//@TableName("user")
public class User extends BaseEntity {
//@TableId(value = "id",type = IdType.AUTO)//自增
@TableId(value = "id", type = IdType.ASSIGN_ID)//雪花
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField(value = "name")
private String name;
private String pwd;
private String salt;
private String phone;
}
新建vo、bo
UserVo
package com.jha.springcloudlearn.entity.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.jha.springcloudlearn.entity.BaseEntity;
import lombok.Data;
@Data
public class UserVo extends BaseEntity {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String name;
private String pwd;
}
UserBo
package com.jha.springcloudlearn.entity.bo;
import com.jha.springcloudlearn.entity.User;
public class UserBo extends User {
}
然后我们需要实现自动填充功能的话,需要实现MetaObjectHandler接口
添加一个MyMetaObjectHandler
package com.jha.springcloudlearn.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jha.springcloudlearn.entity.BaseEntity;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
try {
if (metaObject != null && metaObject.getOriginalObject() instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
Date current = (baseEntity.getCreateTime())!= null
? baseEntity.getCreateTime() : new Date();
baseEntity.setCreateTime(current);
baseEntity.setUpdateTime(current);
}
} catch (Exception e) {
throw new RuntimeException("自动注入异常 => " + e.getMessage());
}
}
@Override
public void updateFill(MetaObject metaObject) {
if (metaObject != null && metaObject.getOriginalObject() instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
Date current = (baseEntity.getUpdateTime())!= null
? baseEntity.getUpdateTime() : new Date();
baseEntity.setUpdateTime(current);
}
// 更新时自动填充更新时间
// this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
// 如果需要,可以设置更新人
// this.strictUpdateFill(metaObject, "updateBy", String.class, "system");
}
}
这样就可以完成创建时间,更新时间的自动填充了,至于创建人和修改人,这个需要用到token,暂且不实现。
我们添加测试的控制层-服务层-mapper层
controller
package com.jha.springcloudlearn.controller;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserInfoController {
@Autowired
private IUserService iUserService;
@GetMapping("/info")
public List<User> info() {
return iUserService.ListUsers();
}
@DeleteMapping("/delete/{id}")
public Boolean delete(@PathVariable String id) {
return iUserService.deleteUser(id);
}
@PostMapping("/add")
public Boolean add(@RequestBody User user) {
return iUserService.addUser(user);
}
}
Service
package com.jha.springcloudlearn.service;
import com.jha.springcloudlearn.entity.User;
import java.util.List;
public interface IUserService {
public abstract List<User> ListUsers();
public abstract Boolean addUser(User user);
public abstract Boolean deleteUser(String id );
}
ServiceImp
package com.jha.springcloudlearn.service.impl;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.UserMapper;
import com.jha.springcloudlearn.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImp implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> ListUsers() {
return userMapper.SelectUsers();
}
@Override
public Boolean addUser(User user) {
return userMapper.insert(user) > 0;
}
@Override
public Boolean deleteUser(String id) {
return userMapper.deleteById(id) > 0;
}
}
Mapper
package com.jha.springcloudlearn.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jha.springcloudlearn.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
public List<User> SelectUsers();
}
Mapper.xml
<?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.jha.springcloudlearn.mapper.UserMapper">
<resultMap id="userResultMap" type="com.jha.springcloudlearn.entity.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="pwd"/>
<result column="create_by" property="createBy"/>
<result column="update_by" property="updateBy"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="del_flag" property="delFlag"/>
</resultMap>
<select id="SelectUsers" resultMap="userResultMap">
SELECT * FROM user;
</select>
</mapper>
运行测试,新增用户,删除用户就能发现可以看到创建时间个更新时间自动填充上去了
常用注解
@TableName
用来指定表名,指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,需要使用这个注解来明确指定表名。一般来说按照驼峰来命名的不存在这个问题
value
类型: String
默认值: ""
指定实体类对应的数据库表名。如果实体类名与表名不一致,使用这个属性来指定正确的表名。
一般如果只有value使用的话,不用显式的声明
如:@TableName("user")
schema
类型: String
默认值: ""
指定数据库的 Schema 名称。通常情况下,如果你的数据库没有使用 Schema 来组织表,这个属性可以不填写。
keepGlobalPrefix
类型: boolean
默认值: false
当全局配置了 tablePrefix 时,这个属性决定是否保持使用全局的表前缀。如果设置为 true,即使注解中指定了表名,也会自动加上全局的表前缀。一般不使用
resultMap
类型: String
默认值: ""
指定在 XML 中定义的 ResultMap 的 ID,用于将查询结果映射到特定类型的实体类对象。
autoResultMap
类型: boolean
默认值: false
是否自动构建 resultMap。如果已经设置了 resultMap,这个属性不会生效。
excludeProperty
类型: String[]
默认值: {}
指定在映射时需要排除的属性名。这些属性将不会被包含在生成的 SQL 语句中。
一般来说大部分时间只用到value属性
@TableId
该注解用于标记实体类中的主键字段。如果主键字段名为 id,可以省略这个注解。
value
类型: String
默认值: ""
指定数据库表的主键字段名。如果不设置,MyBatis-Plus 将使用实体类中的字段名作为数据库表的主键字段名。
type
类型: Enum
默认值: IdType.NONE
指定主键的生成策略。
IdType 枚举类型定义
IdType.AUTO:使用数据库自增 ID 作为主键。IdType.NONE:无特定生成策略,如果全局配置中有 IdType 相关的配置,则会跟随全局配置。IdType.INPUT:在插入数据前,由用户自行设置主键值。IdType.ASSIGN_ID:自动分配ID,适用于Long、Integer、String类型的主键。默认使用雪花算法通过IdentifierGenerator的nextId实现。@since 3.3.0IdType.ASSIGN_UUID:自动分配UUID,适用于String类型的主键。默认实现为IdentifierGenerator的nextUUID方法。@since 3.3.0
一般用雪花id,比较安全
@TableField
该注解用于标记实体类中的非主键字段,它告诉 MyBatis-Plus 如何映射实体类字段到数据库表字段。如果实体类字段名遵循驼峰命名规则,并且与数据库表字段名一致,可以省略这个注解。
value
类型: String
默认值: ""
指定数据库中的字段名。如果你的实体类字段名与数据库字段名不同,使用这个属性来指定正确的数据库字段名。
exist
类型: boolean
默认值: true
指示这个字段是否存在于数据库表中。如果设置为 false,MyBatis-Plus 在生成 SQL 时会忽略这个字段。
condition
类型: String
默认值: ""
在执行实体查询(EntityQuery)时,指定字段的条件表达式。这允许你自定义字段在 WHERE 子句中的比较方式。如果该项有值则按设置的值为准,无值则默认为全局的 %s=#{%s} 为准。
fill
类型: Enum
默认值: FieldFill.DEFAULT
字段自动填充策略。该属性用于指定在执行数据库操作(如插入、更新)时,如何自动填充字段的值。通过使用 FieldFill 枚举,可以灵活地控制字段的填充行为。
FieldFill枚举类型定义
-
FieldFill.DEFAULT:默认不进行填充,依赖于数据库的默认值或手动设置。 -
FieldFill.INSERT:在插入操作时自动填充字段值。 -
FieldFill.UPDATE:在更新操作时自动填充字段值。 -
FieldFill.INSERT_UPDATE:在插入和更新操作时都会自动填充字段值。
一般用在字段填充
@TableLogic
该注解用于标记实体类中的字段作为逻辑删除字段。逻辑删除是一种数据管理策略,它不是真正地从数据库中删除记录,而是在记录中标记该记录为已删除状态。通过使用@TableLogic注解,MyBatis-Plus 可以在查询、更新和删除操作中自动处理逻辑删除字段的值。
@TableLogic(value = "0", delval = "1") // 逻辑删除字段
deleted字段被标记为逻辑删除字段。@TableLogic注解的value属性指定了逻辑未删除的值(在这个例子中是0),而delval属性指定了逻辑删除的值(在这个例子中是1)
当执行查询操作时,MyBatis-Plus 会自动过滤掉标记为逻辑删除的记录,只返回未删除的记录。在执行更新操作时,如果更新操作会导致逻辑删除字段的值变为逻辑删除值,MyBatis-Plus 会自动将该记录标记为已删除。在执行删除操作时,MyBatis-Plus 会自动将逻辑删除字段的值更新为逻辑删除值,而不是物理删除记录。
使用@TableLogic注解可以实现数据的逻辑删除,有助于维护数据的完整性和可追溯性,同时避免了物理删除操作可能带来的数据丢失风险。开发者无需手动编写逻辑删除的代码,MyBatis-Plus 会自动处理这一过程。
常用配置
mybatis-plus:
# 配置mybatis-plus的mapper.xml文件位置,默认值:classpath*:/mapper/**/*.xml
mapper-locations: classpath*:/mapper/**/*.xml
# 配置mybatis-plus的entity别名,配置之后,就可以在mapper.xml中使用别名,而不需要使用全类名,不需要再写全路径名
type-aliases-package: com.example.demo.entity
# 配置mybatis-plus的配置文件
global-config:
# 数据库配置
db-config:
#id雪花生成
id-type: assign_id
#逻辑删除字段
logic-delete-field: del_flag
#字段策略, not_empty: 不是空就更新, always: 永远更新, never: 默认, ignored: 忽略, not_null: 不是null就更新
update-strategy: not_null
#逻辑删除字段值
logic-delete-value: 2
#逻辑未删除字段值
logic-not-delete-value: 0
# 配置mybatis-plus的日志
configuration:
# 打印sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#是否开启下划线和驼峰映射
map-underscore-to-camel-case: true
#懒加载
lazy-loading-enabled: true
#是否开启二级缓存
cache-enabled: false
这边是Mybatisplus的全局配置,如果实体类没有注解的话,就按照这个去执行,如果有,就按照实体类上的注解去执行,注解优先级>全局配置
很多都是默认的配置,按照需要去找对应的配置即可
条件构造器
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
在 MyBatis-Plus 中,Wrapper 类是构建查询和更新条件的核心工具。以下是主要的 Wrapper 类及其功能:
-
AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。
-
QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用
and和or逻辑。 -
UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
-
LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。
-
LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。
package com.jha.springcloudlearn;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jha.springcloudlearn.entity.BaseEntity;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.UserMapper;
import com.jha.springcloudlearn.service.impl.UserServiceImp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import java.util.List;
@SpringBootTest
class SpringCloudLearnApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
}
//基于QueryWrapper的查询
@Test
void testSelectByQueryWrapper() {
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//查询条件添加,查询创建时间在2025-12-08 03:19:17之后的用户,并且名字包含a,查询字段为id,name,pwd
userQueryWrapper.select("id","name","pwd").like("name","a").ge("create_time","2025-12-08 03:19:17");
List<User> users = userMapper.selectList(userQueryWrapper);
System.out.println( users);
}
//基于LambdaQueryWrapper的查询
@Test
void testSelectByLambdaQueryWrapper() {
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
//查询条件添加,查询创建时间在2025-12-08 03:19:17之后的用户,并且名字包含a,查询字段为id,name,pwd
userQueryWrapper.select(User::getId,User::getName,User::getPwd).like(User::getName,"a").ge(BaseEntity::getCreateTime,"2025-12-08 03:19:17");
List<User> users = userMapper.selectList(userQueryWrapper);
System.out.println( users);
}
//基于QueryWrapper的修改
@Test
void testUpdateByQueryWrapper() {
User user = new User();
user.setPwd("231"); // 只设置需要更新的字段
user.setRemark("批量修改");
QueryWrapper<User> updateWrapper = new QueryWrapper<User>();
QueryWrapper<User> eq = updateWrapper.like("name", "jh");
int update = userMapper.update(user, eq);
}
//基于LambdaQueryWrapper的修改
@Test
void testUpdateByLambdaQueryWrapper() {
User user = new User();
user.setPwd("233211"); // 只设置需要更新的字段
user.setRemark("批量修改");
LambdaQueryWrapper<User> updateWrapper = new LambdaQueryWrapper<User>();
LambdaQueryWrapper<User> eq = updateWrapper.like(User::getName, "jh");
int update = userMapper.update(user, eq);
}
@Test
void testDeleteByQueryWrapper() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "测试");
int delete = userMapper.delete(queryWrapper);
}
//基于UpdateWrapper的修改
@Test
void testUpdateByUpdateWrapper() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
//设置密码为密码+10000,remark为220871,名字包含jh
UpdateWrapper<User> set = updateWrapper.like("name", "jh").set("remark", "220871")
.setSql("pwd=pwd+10000");
int update = userMapper.update(null, set);
}
}
QueryWrapper和LambdaQueryWrapper的主要区别在于,一个是硬编码,一个不是
常用的几个方法:
allEq(全等于)
allEq 方法是 MyBatis-Plus 中用于构建查询条件的方法之一,它允许我们通过一个 Map 来设置多个字段的相等条件。
方法签名
allEq(Map<String, Object> params)
allEq(Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, Map<String, Object> params, boolean null2IsNull)
// 设置所有字段的相等条件,通过filter过滤器决定哪些字段应该被包含,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(BiPredicate<String, Object> filter, Map<String, Object> params)
allEq(BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
参数说明
params:一个Map,其中key是数据库字段名,value是对应的字段值。null2IsNull:如果设置为true,当Map中的value为null时,会调用isNull方法;如果设置为false,则会忽略value为null的键值对。filter:一个BiPredicate,用于过滤哪些字段应该被包含在查询条件中。condition:一个布尔值,用于控制是否应用这些条件。
//基于QueryWrapper的查询,allEq
@Test
void testAllEq() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
Map<String, Object> params = new HashMap<>();
params.put("id", "1997868875736465410");
params.put("name", "w2uhu");
params.put("pwd", "220871");
queryWrapper.allEq(params);
// 查询所有字段,全条件匹配
List<User> users = userMapper.selectList(null, queryWrapper);
System.out.println(users);
System.out.println("======================");
QueryWrapper<User> queryWrapper2 = new QueryWrapper<User>();
// 查询条件添加,键包含a才用作条件
queryWrapper2.allEq((field, value) -> field.contains("a"),params);
List<User> users2 = userMapper.selectList(null, queryWrapper2);
}
可以过滤器来动态设置条件
eq(单等于)
eq 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的相等条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的相等条件
eq(R column, Object val)
// 根据条件设置指定字段的相等条件
eq(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个相等条件。
ne(不相等)
ne 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的不相等条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的不相等条件
ne(R column, Object val)
// 根据条件设置指定字段的不相等条件
ne(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个不相等条件。
gt(大于)
gt 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的大于条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的大于条件
gt(R column, Object val)
// 根据条件设置指定字段的大于条件
gt(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个大于条件。
ge(大于等于)
ge 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的大于等于条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的大于等于条件
ge(R column, Object val)
// 根据条件设置指定字段的大于等于条件
ge(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个大于等于条件。
lt(小于)
lt 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的小于条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的小于条件
lt(R column, Object val)
// 根据条件设置指定字段的小于条件
lt(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个小于是条件。
le(小于等于)
le 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的小于等于条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的小于等于条件
le(R column, Object val)
// 根据条件设置指定字段的小于等于条件
le(boolean condition, R column, Object val)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val:与字段名对应的值。condition:一个布尔值,用于控制是否应用这个小于是条件。
between
between 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的 BETWEEN 条件。
使用范围
QueryWrapperLambdaQueryWrapperUpdateWrapperLambdaUpdateWrapper
方法签名
// 设置指定字段的 BETWEEN 条件
between(R column, Object val1, Object val2)
// 根据条件设置指定字段的 BETWEEN 条件
between(boolean condition, R column, Object val1, Object val2)
参数说明
column:数据库字段名或使用Lambda表达式的字段名。val1:与字段名对应的第一个值,表示 BETWEEN 条件的起始值。val2:与字段名对应的第二个值,表示 BETWEEN 条件的结束值。condition:一个布尔值,用于控制是否应用这个 BETWEEN 条件。
自定义SQL
可以利用Mybatisplus的Wrapper来构建复杂的where条件,然后自己定义SQL语句中剩下的部分
添加mapper,用于处理自定义SQL
/**
* 自定义SQL
* @param queryWrapper, 必须使用@Param("ew"),必须命名为ew
* @param count
* @return
*
*/
Integer updateBySQL(@Param("ew") QueryWrapper<User> queryWrapper,@Param("count") Integer count)
mapper.xml中添加
<update id="updateBySQL">
UPDATE user SET pwd = pwd+#{count} ${ew.customSqlSegment};
</update>
测试方法
@Test
void testSQL(){
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
List<String> ids = new ArrayList<>();
ids.add("1997868875736465410");
ids.add("1997875395392012290");
queryWrapper.in("id", ids);
Integer count=100000;
//把where条件在QueryWrapper中写好,然后传给updateBySQL方法(自定义SQL方法,在里面写select查询,除去where条件)
Integer num= userMapper.updateBySQL(queryWrapper,count);
System.out.println("更新数量:"+num);
}
持久层接口(IService)
IService接口是 MyBatis-Plus 提供的一个通用 Service 层接口,它封装了常见的 CRUD 操作,包括插入、删除、查询和分页等。通过继承 IService 接口,可以快速实现对数据库的基本操作,同时保持代码的简洁性和可维护性。
IService 接口中的方法命名遵循了一定的规范,如 get 用于查询单行,remove 用于删除,list 用于查询集合,page 用于分页查询,这样可以避免与 Mapper 层的方法混淆。
想要使用的话,我们的接口需要去继承IService接口,实现类如果直接实现我们的自定义接口的话,就会存在一个问题,我们需要实现所有的接口,而IService有非常多的接口,这是不现实的,于是Mybatisplus为我们提供了一个IService的实现类,ServiceImp,这个接口就实现了IService接口的方法,我们只需要在我们的实现类实现我们的接口的同时去继承ServiceImp就可以得到IService的所有方法了。
使用示例
新增MyUserMapper.java
package com.jha.springcloudlearn.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jha.springcloudlearn.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MyUserMapper extends BaseMapper<User> {
}
新增IMyUserService
package com.jha.springcloudlearn.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jha.springcloudlearn.entity.User;
public interface IMyUserService extends IService<User> {
}
新增MyUserServiceImp
package com.jha.springcloudlearn.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.MyUserMapper;
import com.jha.springcloudlearn.service.IMyUserService;
import org.springframework.stereotype.Service;
@Service
public class MyUserServiceImp extends ServiceImpl<MyUserMapper, User> implements IMyUserService {
}
添加测试类测试
package com.jha.springcloudlearn.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.service.IMyUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MyUserServiceImpTest {
@Autowired
private IMyUserService myUserService;
//测试IService的方法
@Test
void selectByQueryWrapper() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","测试");
User one = myUserService.getOne(queryWrapper);
System.out.println(one);
}
@Test
void selectByLambdaQueryWrapper() {
List<User> list = myUserService.list();
for (User user : list) {
System.out.println( user);
}
}
@Test
void testAdd() {
User user = new User();
user.setName("测试");
user.setPwd("123456");
boolean save = myUserService.save(user);
System.out.println(save);
}
}
IService中的lambdaQuery和lambdaUpdate方法
用于条件查询,当某个条件不成立的时候,不添加对应的条件
@Test
void testLambdaQuery() {
UserBo userBo = new UserBo();
userBo.setName("测试");
userBo.setPwd("123456");
//userBo.setId(1997855873826029570L);
//查询条件有:姓名,密码,id
List<User> list = myUserService.lambdaQuery().like(userBo.getName() != null, User::getName, userBo.getName())
.eq(userBo.getId() != null, User::getId, userBo.getId())
.eq(userBo.getPwd() != null, User::getPwd, userBo.getPwd())
.list();
for (User user : list) {
System.out.println( user);
}
}
@Test
void testLambdaUpdate() {
UserBo userBo = new UserBo();
userBo.setName("测试");
userBo.setPwd("123456");
userBo.setId(1998231604640882689L);
Long newPwd=Long.parseLong(userBo.getPwd()) -200000L;
myUserService.lambdaUpdate().eq(User::getId, userBo.getId())
.set(newPwd >=0,User::getPwd, newPwd)
.set(newPwd <=0,User::getPwd, "0")
.set(newPwd <=0, User::getRemark, "密码不够减")
.update();
}
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
配置文件中的jdbc连接,改成这个,添加重写批处理语句支持rewriteBatchedStatements=true
DB静态工具
为了编码循环依赖,而设计的,DB中包含了IService中所有的方法,只不过里面是静态的,直接调用即可,调用时需要传入类型
示例测试
@Test
void testSelectByQueryWrapper() {
// 查询单个用户
User user = Db.lambdaQuery(User.class)
.eq(User::getId, 1998231604640882689L)
.one();
System.out.println("单个用户: " + user);
System.out.println("======================");
// 查询用户列表
List<User> list = Db.lambdaQuery(User.class)
.like(User::getName, "测试")
.list();
System.out.println("用户列表: ");
for (User user1 : list) {
System.out.println(user1);
}
}
枚举处理器
在日常开发中,有很多东西需要使用到枚举,如状态,就拿删除状态来说,使用枚举来进行表示
我们添加枚举类
DelEnums
package com.jha.springcloudlearn.entity.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
@Getter
public enum DelEnums {
Nomal(0,"正常"),
Del(2,"删除");
//枚举值
@EnumValue //数据库保存的枚举值
private Integer value;
@JsonValue //枚举对应返回什么就加上这个注解
private String desc;
DelEnums(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
}
然后配置文件添加
server:
port: 8081
#mybatis:
# # 指定别名设置的包为所有entity
# type-aliases-package: com.jha.springcloudlearn.entity
# configuration:
# map-underscore-to-camel-case: true # 驼峰命名规范
# mapper-locations: classpath:/mapper/*.xml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
username: root
password: 220717
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
# 配置mybatis-plus的mapper.xml文件位置,默认值:classpath*:/mapper/**/*.xml
mapper-locations: classpath*:/mapper/**/*.xml
# 配置mybatis-plus的entity别名,配置之后,就可以在mapper.xml中使用别名,而不需要使用全类名,不需要再写全路径名
type-aliases-package: com.example.demo.entity
# 配置mybatis-plus的配置文件
global-config:
# 数据库配置
db-config:
#id雪花生成
id-type: assign_id
#逻辑删除字段
logic-delete-field: del_flag
#字段策略, not_empty: 不是空就更新, always: 永远更新, never: 默认, ignored: 忽略, not_null: 不是null就更新
#update-strategy: not_null
#逻辑删除字段名
logic-delete-feild-name: del_flag
#逻辑删除字段值
logic-delete-value: 2
#逻辑未删除字段值
logic-not-delete-value: 0
# 配置mybatis-plus的日志
configuration:
# 打印sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#是否开启下划线和驼峰映射
map-underscore-to-camel-case: true
#懒加载
lazy-loading-enabled: true
#是否开启二级缓存
cache-enabled: false
#枚举类型处理器
default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler
default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler
就是表示添加枚举处理器
分页处理
Mybatisplus本身带有分页插件,只需要手动添加一下就可以了,创建一个MybatisPlusConfig类
在新建之前,我们需要知道我们的Mybatisplus的版本是不是在v3.5.9 之上,因为从这个版本开始,PaginationInnerInterceptor 就被分离出去了,需要额外添加依赖
mybatis-plus-jsqlparser
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
<version>3.5.12</version>
</dependency>
package com.jha.springcloudlearn.config;
import com.baomidou.mybatisplus.annotation.DbType;
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;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(getPaginationInnerInterceptor());
return interceptor;
}
public PaginationInnerInterceptor getPaginationInnerInterceptor() {
PaginationInnerInterceptor mybatisPlusInterceptor = new PaginationInnerInterceptor();
//设置数据库类型、 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
mybatisPlusInterceptor.setDbType(DbType.MYSQL);
//溢出总页数后是否进行处理,分页合理化
mybatisPlusInterceptor.setOverflow(true);
//单页分页条数限制
mybatisPlusInterceptor.setMaxLimit(1000L);
return mybatisPlusInterceptor;
}
}
这样就表示引入了分页插件
然后我们可以在测试类中测试一下
@Test
void testPage (){
Page<User> page=Page.of(1, 3);
page.addOrder(OrderItem.desc("create_time"));
Page<User> page1 = myUserService.page(page);
page1.getRecords().forEach(System.out::println);
}
这是直接调用page方法来做查询,用来测试分页是否启用了的,实际开发中,一般不这么做
如下示例:
我们需要先封装PageQuery(存在分页的条件,如页码,每页大小,以及创建Page对象的方法等),TableDataInfo(用来返回分页的结果对象的)
PageQuery
package com.jha.springcloudlearn.entity;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import java.io.Serializable;
@Data
public class PageQuery implements Serializable {
private Integer pageNum;
private Integer pageSize;
private String sortColumn;
private String isAsc;
public <T> Page<T> build(){
return new Page<>(pageNum,pageSize);
}
}
TableDataInfo
package com.jha.springcloudlearn.entity;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data;
import java.util.List;
@Data
public class TableDataInfo<T> {
private int code;
private String msg;
private long total;
private List<T> rows;
public static <T> TableDataInfo<T> build(IPage<T> page) {
TableDataInfo<T> rsp = new TableDataInfo<>();
rsp.setCode(200);
rsp.setMsg("查询成功");
rsp.setRows(page.getRecords());
rsp.setTotal(page.getTotal());
return rsp;
}
}
添加控制层方法
@GetMapping("/pageList")
public Page<UserVo> pageList(UserBo userBo, PageQuery pageQuery) {
return iUserService.pageList(userBo, pageQuery);
}
IUserService
public abstract Page<UserVo> pageList(UserBo user, PageQuery query);
UserServiceImp
@Override
public Page<UserVo> pageList(UserBo user, PageQuery query) {
Page<UserVo> list = userMapper.pageList(user, query.build());
return list;
}
Mapper
Page<UserVo> pageList(@Param("ew")UserBo bo,Page<User> page);
Mapper.xml
<select id="pageList" resultMap="userResultMap">
SELECT * FROM user
</select>
这里不要加;不然会导致后面的分页条件加不上去报错
4万+

被折叠的 条评论
为什么被折叠?



