1、特性
无侵入
:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小
:启动即会自动注入基本
CURD
,性能基本无损耗,直接面向对象操作
强大的
CRUD
操作
:内置通用
Mapper
、通用
Service
,仅仅通过少量配置即可实现单表大
部分
CRUD
操作,更有强大的条件构造器,满足各类使用需求
支持
Lambda
形式调用
:通过
Lambda
表达式,方便的编写各类查询条件,无需再担心字
段写错
支持主键自动生成
:支持多达
4
种主键策略(内含分布式唯一
ID
生成器
- Sequence
),可
自由配置,完美解决主键问题
支持
ActiveRecord
模式
:支持
ActiveRecord
形式调用,实体类只需继承
Model
类即可进
行强大的
CRUD
操作
支持自定义全局通用操作
:支持全局通用方法注入(
Write once, use anywhere
)
内置代码生成器
:采用代码或者
Maven
插件可快速生成
Mapper
、
Model
、
Service
、
Controller
层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件
:基于
MyBatis
物理分页,开发者无需关心具体操作,配置好插件之后,写分
页等同于普通
List
查询
分页插件支持多种数据库
:支持
MySQL
、
MariaDB
、
Oracle
、
DB2
、
H2
、
HSQL
、
SQLite
、
Postgre
、
SQLServer
等多种数据库
内置性能分析插件
:可输出
SQL
语句以及其执行时间,建议开发测试时启用该功能,能快
速揪出慢查询
内置全局拦截插件
:提供全表
delete
、
update
操作智能分析阻断,也可自定义拦截规
则,预防误操作
2、操作
1、创建一个User用户表用于测试
# Host: localhost (Version 5.7.23-log)
# Date: 2023-12-10 14:21:50
# Generator: MySQL-Front 6.0 (Build 2.20)
#
# Structure for table "tb_user"
#
CREATE TABLE `tb_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL COMMENT '用户名',
`password` varchar(32) DEFAULT NULL COMMENT '密码',
`role` varchar(10) DEFAULT NULL COMMENT '角色:0:管理员 1:普通用户',
`sex` int(11) DEFAULT NULL COMMENT '性别,0:女 1:男',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`createTime` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
#
# Data for table "tb_user"
#
INSERT INTO `tb_user` VALUES (1,'admin','123456','0',1,25,'2022-10-23 00:12:36'),(6,'张曼玉','123456','1',1,18,'2022-10-23 00:12:44'),(14,'a3','122','1',1,313,'2023-10-17 21:31:48'),(15,'aaa','123456','1',1,111,'2023-11-13 20:26:10'),(17,'aaa','weqe','1',0,NULL,'2023-11-20 18:33:09');
2、新建maven工程
3、导入依赖
<dependencies>
<!-- MyBatisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3307/mybatis?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
4、配置application.properties
5、插件lombok下载
Lombok
提供的常用注解:
@Getter/@Setter
:用在类或属性上,用在类上可以作用于这个类的所有属性,写在属性 上只作用于属性名,再也不用自己手写setter
和
getter
方法了
@ToString
:用在类上,可以自动覆写
toString
方法,当然还可以加其他参数,例如
@ToString(exclude=”id”)
排除
id
属性,或者
@ToString(callSuper=true, includeFieldNames=true)调用父类的
toString
方法,包含所有属
@EqualsAndHashCode
:用在类上,自动生成
equals
方法和
hashCode
方法
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
:用 在类上,自动生成无参构造和使用所有参数的构造函数以及把所有@NonNull
属性作为参数的构造函数
@RequiredArgsConstructor
主要是对当前类中带有
final
的属性进行属性注入
@Data
:注解在类上,相当于同时使用了
@ToString
、
@EqualsAndHashCode
、
@Getter
、
@Setter
和
@RequiredArgsConstrutor
这些注解,对于
POJO
类
十分有用
@Value
:用在类上,是
@Data
的不可变形式,相当于为属性添加
final
声明,只提供
getter方法,而不提供setter
方法
@Slf4j
: 自动创建
Slf4j
日志对象
log
,用于记录系统日志信息
6、创建实体类
package com.cqh.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data //@Data : 注解在类上,提供类的get、set、equals、hashCode、canEqual、toString、无参构造方法,没有有参构造方法。
@AllArgsConstructor // 全部参数构造方法
@NoArgsConstructor //无参数构造方法
@TableName("tb_user")
public class User {
@TableId
private int id;
private String username;
private String password;
private String role;
private int sex;
private int age;
@TableField(value = "createTime")
private Date createTime;
}
7、创建userMapper接口
8、完善启动类
为了能够让
SpringBoot
扫描并且识别此组件,我们需要在
SpringBoot
启动类上开启
Mapper
接口
扫描功能,添加
@MapperScan()
注解
package com.cqh;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.cqh.mapper")
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}
9、测试
查询所有
package com.cqh;
import com.cqh.entity.User;
import com.cqh.mapper.UserMapper;
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;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
//查询全部用户
//此方法需要我们传递Wrapper对象,此对象是条件构造器,我们现在要查询全部用户先不用,所以传null即可
@Test
public void test01(){
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println("user = " + user);
}
}
}
为了方便查看配置日志
# 配置日志
mybatis-plus.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl
添加user
//插入数据
@Test
public void test02(){
User user1 = new User();
user1.setUsername("xiaoMin");
user1.setPassword("123456");
user1.setAge(11);
user1.setRole("0");
user1.setSex(1);
int insert = userMapper.insert(user1);
System.out.println("insert = " + insert);
}
删除功能
BaseMapper
中提供了
5
个删除方法
//用于删除数据库中的记录。它接受一个类型为
Serializable
的参数
id
,表示要删除的记录的唯一标识符。
根据Map删除对应数据
//根据map删除
@Test
public void deleteTest(){
Map<String,Object> map = new HashMap<>();
map.put("username","xiaoMin");
map.put("age",11);
int num = userMapper.deleteByMap(map);
System.out.println(num);
}
根据多个id进行批量删除
//根据多个id进行批量删除
@Test
public void deleteTest2(){
ArrayList<Integer> ids = new ArrayList<>();
ids.add(15);
ids.add(17);
int num = userMapper.deleteBatchIds(ids);
System.out.println(num);
}
多条件删除
//根据多个条件进行删除
@Test
public void deleteTest3(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("username","a3");
userQueryWrapper.eq("sex",1);
int num = userMapper.delete(userQueryWrapper);
System.out.println(num);
}
修改功能
修改方法BaseMapper中提供了两个
根据id修改
//根据id修改
@Test
public void updateTest(){
User user = new User();
user.setId(6);
user.setUsername("李四");
int num = userMapper.updateById(user);
System.out.println(num);
}
查询功能
下图中的两个方法,分别是通过单个
id
查询数据,和
id
集合来查询数据,
此方法为根据Map中传递的条件进行查询
//根据Map中传递的条件进行查询
@Test
public void selectTest(){
Map<String,Object> map = new HashMap<>();
map.put("id",6);
map.put("username","李四");
List<User> users = userMapper.selectByMap(map);
users.forEach(user -> System.out.println(user));
}
此方法Wrapper条件构造器传递参数为null表示查询全部数据
注意:所有的CRUD方法中只要涉及到Wrapper条件构造器的如果不需要使用都可以传入为
null,但是要注意一般查询可以传入,但是修改和删除一般不可以,因为如果删除和修改没有条
件会导致影响全部数据
新增功能
//插入数据
@Test
public void test02(){
User user1 = new User();
user1.setUsername("xiaoMin");
user1.setPassword("123456");
user1.setAge(11);
user1.setRole("0");
user1.setSex(1);
int insert = userMapper.insert(user1);
System.out.println("insert = " + insert);
}
有一个问题就是没有主键返回
其实这里
MyBatis-Plus
是通过雪花算法来进行自动生成的
id
,但是要
注意:
我们的主键必须叫
id,并且必须是包装类型,否则不生效
常见主键生成策略
数据库自增长序列或字段:最常见的方式。利用数据库,全数据库唯一。
UUID
:常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。
Redis
生成
ID
:当使用数据库来生成
ID
性能不够要求的时候,我们可以尝试使用
Redis
来生成ID。这主要依赖于
Redis
是单线程的,所以也可以用生成全局唯一的
ID
。
Twitter
的
snowflake(
雪花
)
算法:
snowflake
是
Twitter
开源的分布式
ID
生成算法,结果是一个long
型的
ID
。
zookeeper
生成唯一
ID
:
zookeeper
主要通过其
znode
数据版本来生成序列号,可以生成
32位和64
位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。
雪花算法
snowflake
是
Twitter
开源的分布式
ID
生成算法,结果是一个
long
型的
ID
。
其核心思想是:使用
41bit
作为毫秒数,
10bit
作为机器的
ID
(
5
个
bit
是数据中心,
5
个
bit
的机器
ID
),
12bit
作为毫秒内的流水号(意味着每个节点在每毫秒可以产生
4096
个
ID
),最后还有
一个符号位,永远是
0
其中
MyBatis-Plus
中提供的一个注解
@TableId
(注意:表一定要是主键自增 )
修改User实体类
现在主键返回了
自定义CRUD
MyBatis-Plus
的
BaseMapper
本身提供了很多通用的
CRUD
方法,但是由于我们的业务问题有的
时候必须要自定义一些方法
MyBatis-Plus
是在
MyBatis
的基础之上只做增强不做修改的即可,所以如果想要实
现自定义的方法,具体操作其实和
MyBatis
没有什么区别
配置
如果我们需要进行复杂映射就可能会涉及到映射文件
mapper.xml
那么这个文件位置的配置,我
们可以在
properties
配置文件中进行配置
# 指定mapper文件位置
mybatis-plus.mapper-locations = classpath*:/mapper/**/*.xml
测试
注解方式
编写mapper
package com.cqh.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cqh.entity.User;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper extends BaseMapper<User> {
/**
* 根据name查询数据
* @param username
* @return
*/
@Select("select * from tb_user where username=#{username}")
List<User> selectByName(String username);
}
编写测试方法
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.cqh.mapper.UserMapper">
<select id="selectByName" resultType="com.cqh.entity.User">
select * from tb_user where username=#{username}
</select>
</mapper>
测试一下
IService接口
通用
Service CRUD
封装
IService (opens new window)
接口,进一步封装
CRUD
采用
get 查询单行 remove
删除
list
查询集合
page
分页
前缀命名方式区分
Mapper
层避免混
淆,
泛型
T
为任意实体对象
建议如果存在自定义通用
Service
方法的可能,请创建自己的
IBaseService
继承
Mybatis
-
Plus
提供的基类
对象
Wrapper
为 条件构造器
使用参考:
MybatisPlus入门-CSDN博客
分页插件
Page:
该类继承了
IPage
类,实现了
简 单 分 页 模 型
如果你要实现自己的分页模型可以继承
Page
类或者实现
IPage
类
创建config开启分页
package com.cqh.config;
/**
* @author cqh
* @date 2023/12/10
* @Description
*/
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//开启扫描,注意包名不要写错(有了MyBatisPlus的配置类,我们就可以把所有的相关配置都写在这里)
@MapperScan("com.qf.mybatisplusdemo.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new
MybatisPlusInterceptor();
//分页插件
mybatisPlusInterceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
分页测试
@Test
public void PaginationInnerInterceptorTest(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
Page<User> page = new Page<>(1,3);
//条件构造器Wrapper目前没有就写null
userMapper.selectPage(page,null);
}
Page对象常用方法
@Test
public void PaginationInnerInterceptorTest2(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
Page<User> page = new Page<>(2,3);
//条件构造器Wrapper目前没有就写null
userMapper.selectPage(page,null);
//获取记录
List<User> users = page.getRecords();
users.forEach(user -> System.out.println(user));
System.out.println(page.getPages()); //获取总页数
System.out.println(page.getTotal()); //获取总数据量
System.out.println(page.hasNext());//是否有下一页
System.out.println(page.hasPrevious());//是否有上一页
}
逻辑删除
在企业中对于删除,一般情况下是不会真正的把数据删除掉的,而是会进行 逻辑删除
所以大家会发现一些系统,管理员可以看到已经删除的用户信息,实际上这就是一种逻辑删除,
也就是根据数据表中的类似于:
deleted
的属性来标记用户删除,而并非真正删除。
逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
就是将删除delete语句改成了修改语句一般是专门一个字段用来做为是否被删除的判断
条件构造器
MyBatis-Plus
提供了强大的条件构造器。通过条件构造器可以写一些复杂的
SQL
语句,从而提高
开发效率。
查询
mybatisPlus
源码可以看到,条件构造器
wrapper
继承情况
Wrapper
:条件构造器,最顶端的一个类
AbstractWrapper:用于
sql
语句条件的封装,主要是封装
where
条件
QueryWrapper:查询条件封装(一般删除的条件也使用QueryWrapper
)
UpdateWrapper:更新条件封装
AbstractLambdaWrapper:具有Lambda
语法的条件封装
LambdaQueryWrapper:具有Lambda语法查询条件封装
LambdaUpdateWrapper:具有Lambda语法更新条件封装
所有的条件使用方法,在官网中有很详细的介绍
具体地址:
https://www.baomidou.com/pages/10c804/#abstractwrapper
QueryWrapper
我这里 查询username不为空的用户,并且年龄大于10岁
比较用的.ge() 这是大于等于
还有许多比较方法
// 查询名字为chen的用户
// 查询年龄18~25岁之间的用户
// 查询年龄大于等于25岁的用户
// 模糊查询:查询名字不包含a的用户,反之like就是包含
//模糊查询:包含左侧或者右侧具体内容
子查询
lambda表达式执行条件
在
QueryWrapper
中有
and
或者
or
这样的方法,要注意的是默认都是通过
and
来进行连接条件,
但是如果主动调用
or
方法,将会改变,还有一点如果
and
或者
or
表达式时中出现
lambda
表达式,
将会改变条件的优先级,先来执行
lambda
表达式的条件
condition
我们在写项目的时候,所有的条件都是由用户进行传递的,那么有的时候就无法避免参数出现空
值
null
的情况,所以我们应该要做一些判断,其实很多方法都提供了
boolean condition
这个参
数,表示该条件
是否
加入最后生成的
sql
中,也就是可以通过它来进行判断
QueryWrapper执行修改和删除操作
//修改用户id为24的username为jack
UpdateWrapper
继承自
AbstractWrapper
,
自身的内部属性
entity
也用于生成
where
条件
可以通过
set
方法来进行修改
//修改年龄大于等于10,并且username为xiao的用户role为 0
LambdaQueryWrapper&LambdaUpdateWrapper
它们两个的主要目的是为了防止我们在编写的时候,字段名称编写错误,我们可以直接通过
Lambda
的方式来直接获取指定字段对应的实体类对应的名称
LambdaQueryWrapper
查询
LambdaUpdateWrapper
修改
//修改年龄大于10,并且name为xiao的用户role为 1
我的所有测试代码
package com.cqh;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cqh.entity.User;
import com.cqh.mapper.UserMapper;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
//查询全部
@Test
public void test01(){
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println("user = " + user);
}
}
//插入数据
@Test
public void test02(){
User user1 = new User();
user1.setUsername("chen1");
user1.setPassword("123456");
user1.setAge(18);
user1.setRole("1");
user1.setSex(1);
int insert = userMapper.insert(user1);
System.out.println("insert = " + insert);
System.out.println("id = " + user1.getId());
}
//根据map删除
@Test
public void deleteTest(){
Map<String,Object> map = new HashMap<>();
map.put("username","xiaoMin");
map.put("age",11);
int num = userMapper.deleteByMap(map);
System.out.println(num);
}
//根据多个id进行批量删除
@Test
public void deleteTest2(){
ArrayList<Integer> ids = new ArrayList<>();
ids.add(15);
ids.add(17);
int num = userMapper.deleteBatchIds(ids);
System.out.println(num);
}
//根据多个条件进行删除
@Test
public void deleteTest3(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("username","a3");
userQueryWrapper.eq("sex",1);
int num = userMapper.delete(userQueryWrapper);
System.out.println(num);
}
//根据id修改
@Test
public void updateTest(){
User user = new User();
user.setId(6);
user.setUsername("李四");
int num = userMapper.updateById(user);
System.out.println(num);
}
//根据Map中传递的条件进行查询
@Test
public void selectTest(){
Map<String,Object> map = new HashMap<>();
map.put("id",6);
map.put("username","李四");
List<User> users = userMapper.selectByMap(map);
users.forEach(user -> System.out.println(user));
}
@Test
public void selectByNameTest(){
List<User> users = userMapper.selectByName("李四");
users.forEach(user -> System.out.println(user));
}
@Test
public void PaginationInnerInterceptorTest(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
Page<User> page = new Page<>(1,3);
//条件构造器Wrapper目前没有就写null
userMapper.selectPage(page,null);
}
@Test
public void PaginationInnerInterceptorTest2(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
Page<User> page = new Page<>(2,3);
//条件构造器Wrapper目前没有就写null
userMapper.selectPage(page,null);
//获取记录
List<User> users = page.getRecords();
users.forEach(user -> System.out.println(user));
System.out.println(page.getPages()); //获取总页数
System.out.println(page.getTotal()); //获取总数据量
System.out.println(page.hasNext());//是否有下一页
System.out.println(page.hasPrevious());//是否有上一页
}
// 查询username不为空的用户,并且年龄大于10岁
@Test
public void selectTest1(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.isNotNull("username")
.ge("age",10);
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
// 查询名字为chen的用户
@Test
public void selectTest2(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username","chen");
User user = userMapper.selectOne(wrapper);//类似于map传入条件
System.out.println(user);
}
// 查询年龄18~25岁之间的用户
@Test
public void selectTest3(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",18,25);
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
// 查询年龄大于等于25岁的用户
@Test
public void selectTest4(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age",25);
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
// 模糊查询:查询名字不包含a的用户,反之like就是包含
@Test
public void selectTest5(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.notLike("username","a");
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
//模糊查询:包含左侧或者右侧具体内容
@Test
public void selectTest6(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 模糊查询:查询名字不包含qf的用户,反之like就是包含
// likeLeft和likeRight
// 左右就是 %在左或者在右
// 以下就是 a% 相当于以a开头的名字
wrapper.likeRight("username","a");
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
//通过子查询,查询id等于6的用户信息,此方法也可以进行表关联查询
@Test
public void selectTest7(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id","select id from tb_user where id=6");
userMapper.selectObjs(wrapper).forEach(System.out::println);
}
// 查询用户名中包含a并且年龄大于29或者crateTime为空的用户
@Test
public void selectTest8(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("username","a")
.and(w->w.gt("age",26).or().isNull("createTime"));
userMapper.selectList(wrapper).forEach(System.out::println);
}
// 模糊查询:查询名字包含a的用户,并且按照age升序排序,注意参数不能为空
@Test
public void selectTest9(){
//假设用户传递参数
String username = "a";
Integer age = 1;
//先判断条件是否符合,符合才会组合到SQL语句中
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(username),"username",username)
.orderByAsc(age != null,"age");
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
//修改用户id为24的username为jack
@Test
public void updateTest1(){
// QueryWrapper<User> wrapper = new QueryWrapper<>();
// wrapper.eq("id",24);
User user = new User();
user.setUsername("jack");
// userMapper.update(user,wrapper);
userMapper.update(user,new QueryWrapper<User>().eq("id",24));
}
//删除username为jack的用户
@Test
public void deleteTest1(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username","jack");
userMapper.delete(wrapper);
}
//修改年龄大于10,并且username为xiao的用户role为 0
@Test
public void updateTest2(){
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.gt("age",10)
.eq("username","xiao")
.set("role","0");
//无需传递user对象,直接赋值为null
userMapper.update(null,wrapper);
}
@Test
public void selectTest10(){
//假设用户传递参数
String username = "a";
Integer age = null;
//LambdaQueryWrapper就是为了防止我们写错字段,可以直接通过Lambda的方式来直接获取指定字段对应的实体类对应的名称
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(username),User::getUsername,username)
.orderByAsc(age != null,User::getAge);
userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
}
//修改年龄大于10,并且name为xiao的用户role为 1
@Test
public void updateTest3(){
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.gt(User::getAge,10)
.eq(User::getUsername,"xiao")
.set(User::getRole,"1");
//无需传递user对象,直接赋值为null
userMapper.update(null,wrapper);
}
}