这里是知识名字
这个知识重要吗?有什么用?
MyBatis-plus 简介
简介
MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为
简化开发、提高效率而生。
支持数据库
任何能使用MyBatis进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下
框架结构
代码及文档地址
- 官方地址:http://mp.baomidou.com
- 代码发布地址:
Github: https://github.com/baomidou/mybatis-plus
Gitee: https://gitee.com/baomidou/mybatis-plus - 文档发布地址:https://baomidou.com/pages/24112f
使用MyBatis-Plus
1、开发环境
IDE:idea 2019.2
JDK:JDK8+
构建工具:maven 3.5.4
MySQL版本:MySQL 5.7
Spring:5.3.1
MyBatis-Plus:3.4.3.4
2、创建数据库及表
CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
use `mybatis_plus`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
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, 'Billie', 24, 'test5@baomidou.com');
3、创建 Maven 工程
(1)打包方式:jar
(2)导入依赖
<properties>
<spring.version>5.3.1</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- lombok用来简化实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--MyBatis-Plus的核心依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.3.4</version>
</dependency>
</dependencies>
4、Spring 整合 MyBatis
(1)创建对应的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
(2)在resources
下创建 mybatis-comfig.xml
(3)创建 Mapper
接口以及对应的 映射文件。
(4)在resources
下创建创建数据库连接配置文件 database.properties
(5)创建 Spring 配置文件,在resources
下创建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 引入jdbc.properties -->
<context:property-placeholder location="classpath:database.properties" />
<!-- 配置Druid数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置用于创建SqlSessionFactory的工厂bean -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 设置MyBatis配置文件的路径(可以不设置) -->
<property name="configLocation" value="classpath:mybatis-config.xml">
</property>
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 设置类型别名所对应的包 -->
<property name="typeAliasesPackage" value="com.wuqiyong.pojo">
</property>
<!--
设置映射文件的路径
若映射文件所在路径和mapper接口所在路径一致,则不需要设置
-->
<!--
<property name="mapperLocations" value="classpath:mapper/*.xml">
</property>
-->
</bean>
<!--
配置mapper接口的扫描配置
由mybatis-spring提供,可以将指定包下所有的mapper接口创建动态代理
并将这些动态代理作为IOC容器的bean管理
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.wuqiyong.mapper"></property>
</bean>
</beans>
(6)添加日志功能,在resources
下创建logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 logs为当前项目的logs目录 还可以设置为../logs -->
<property name="LOG_HOME" value="logs" />
<!--控制台日志, 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符
宽度,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}
- %msg%n</pattern>
</encoder>
</appender>
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
此时 mybatis 的环境就搭建成功了
(7)进行测试
1.IOC容器进行测试
public class UserMapperTest {
@Test
public void getUserList() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper bean = context.getBean(UserMapper.class);
for (User user : bean.getUserList()) {
System.out.println(user);
}
}
}
2.使用注解方式加载配置文件进行测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserMapperTest {
@Autowired
private UserMapper mapper;
@Test
public void getUserList() {
for (User user : mapper.getUserList()) {
System.out.println(user);
}
}
}
@RunWith(SpringJUnit4ClassRunner.class)
在 Spring 的环境中进行测试@ContextConfiguration("classpath:applicationContext.xml")
指定配置文件
5、使用 MyBatis-Plus
(1)修改 applicationContext.xml
<!-- 此处使用的是MybatisSqlSessionFactoryBean -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 引入jdbc.properties -->
<context:property-placeholder location="classpath:database.properties" />
<!-- 配置Druid数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 此处使用的是MybatisSqlSessionFactoryBean -->
<bean
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<!-- 设置MyBatis配置文件的路径(可以不设置) -->
<property name="configLocation" value="classpath:mybatis-config.xml">
</property>
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 设置类型别名所对应的包 -->
<property name="typeAliasesPackage" value="com.wuqiyong.pojo"></property>
<!--
设置映射文件的路径
若映射文件所在路径和mapper接口所在路径一致,则不需要设置
-->
<!--
<property name="mapperLocations" value="classpath:mapper/*.xml">
</property>
-->
</bean>
</beans>
MybatisSqlSessionFactoryBean
是在SqlSessionFactoryBean
的基础上进行了增强。- 当映射文件的位置和
Mapper
接口的位置相同时,可以不设置映射文件的路径,当不同时,使用<property name="mapperLocations" value="classpath:mapper/*.xml"> </property>
进行设置
这样我们认为是路径相同的。
(2)使用 MP 方式创建 Mapper 接口
public interface UserMapper extends BaseMapper<User> {
}
extends BaseMapper<User>
:BaseMapper
是MyBatis-Plus
提供的基础mapper
接口,泛型为所操作的实体类型,其中包含CRUD
的各个方法,我们的mapper
继承了BaseMapper
之后,就可以直接使用BaseMapper
所提供的各种方法,而不需要编写映射文件以及SQL语句,大大的提高了开发效率。
(3)进行测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserMapperTest {
@Autowired
UserMapper userMapper;
@Test
public void test() {
System.out.println(userMapper.selectById(1));
}
}
在Spring整合MyBatis中加入了MyBatis-Plus后,我们就可以使用MyBatis-Plus
所提供的BaseMapper
实现CRUD,并不需要编写映射文件以及SQL语句但是若要自定义SQL语句,仍然可以编写映射文件而不造成任何影响因为MyBatis-Plus只做增强,而不做修改。
(4)CRUD
增加
@Test
public void insert() {
User user = new User(null, "阿宝", 11, "没有邮箱");
userMapper.insert(user);
}
- 使用
雪花算法
生成 ID。 - 会自动将 ID 赋值给实体类。
INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
删除
deleteById(通过ID删除一行)
@Test
public void deleteById() {
// DELETE FROM user WHERE id=?
userMapper.deleteById(1524547162032087041L);
}
deleteByMap(通过条件删除一行)
@Test
public void deleteByMap() {
// DELETE FROM user WHERE name = ? AND id = ?
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", 4);
map.put("name", "Sandy");
userMapper.deleteByMap(map);
}
- Key:字段名
- Value:需要匹配的值
deleteBatchIds(通过ID批量删除)
@Test
public void deleteBatchIds() {
// Preparing: DELETE FROM user WHERE id IN ( ? , ? )
List<? extends Number> list = Arrays.asList(1524547513900695554L, 5);
userMapper.deleteBatchIds(list);
}
- 传入参数是
ID
的集合
修改
@Test
public void updateById() {
// UPDATE user SET name=?, age=?, email=? WHERE id=?
// UPDATE user SET name=? WHERE id=?
User user = new User(3L, "Tomm", 28, "tom.com");
userMapper.updateById(user);
}
- 当实体类属性为
null
时,不会对这一字段进行修改。
查询
@Test
public void select() {
userMapper.selectById(1L);
userMapper.selectBatchIds(Arrays.asList(1L, 2L));
Map<String, Object> map = new HashMap<>();
map.put("id", 1L);
userMapper.selectByMap(map);
userMapper.selectList(null);
}
自定义方法
(5)通用 Service
mybatis-plus
还提供了通用的 Service
通用 Service CRUD
封装 IService
接口,进一步封装 CRUD
get
查询单行remove
删除list
查询集合page
分页
泛型 T 为任意实体对象
建议如果存在自定义通用 Service
方法的可能,请创建自己的 IBaseService
继承
Mybatis-Plus
提供的基类。
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>
M
当前自己编写的Mapper
T
当前操作的实体类对象
但是提供的方法在实际工作中是不够使用的,于是需要自定义 Service
去继承提供的 ServiceImpl
。
此时使用 User
进举例。
(1)创建 UserService
接口 继承 IService
public interface UserService extends IService<User> {
}
(2)创建 UserServiceImpl
继承 ServiceImpl
实现 UserService
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
(3)使用通用的 Service
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserServiceImplTest {
@Autowired
private UserService userService;
@Test
public void getCount() {
// SELECT COUNT( * ) FROM user
System.out.println(userService.count());
}
@Test
public void testSaveBatch() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setName("阿宝" + i);
user.setAge(20 + i);
users.add(user);
}
userService.saveBatch(users);
}
}
- 批量添加使用一条语句不现实,于是 MP 将批量添加放在通用 Service 中。
userService.saveOrUpdate()
根据实体类 ID 判断是增加还是修改,有 ID 修改,没有 ID 新增
常用注解
使用MyBatis-Plus实现基本的CRUD时,没有指定要操作的表,只是在Mapper
接口继承BaseMapper
时,设置了泛型User
,而操作的表为user
表。
由此得出结论,MyBatis-Plus
操作的表由BaseMapper
的泛型决定,即实体类型决定,即 默认操作的表名和实体类型的类名一致
当实体类名和表名不一致时,可以使用如下方法进行解决。
@TableName(解决实体类名和数据库表名不一致)
@TableName
是用来解决实体类名和表名不一致的情况,设置实体类对应的表名。
此时的表名为 t_user
@TableName("t_user")
public class User {}
GlobalConfig(解决实体类名和数据库表名不一致)
在 Srping 配置文件中添加以下配置文件
是将数据库表名前缀 t_
去除,然后再进行映射。
<bean class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml">
</property>
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="自己的实体类包路径名"></property>
<!-- 设置MyBatis-Plus的全局配置 -->
<property name="globalConfig" ref="globalConfig"></property>
</bean>
<bean id="globalConfig"
class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<!-- 设置实体类所对应的表的前缀 -->
<property name="tablePrefix" value="t_"></property>
</bean>
</property>
</bean>
-
MybatisSqlSessionFactoryBean
如果以及定义了这个Bean
那么在当前Bean
中添加property name="globalConfig" ref="globalConfig"></property>
再定义globalConfig
即可。 -
因为定义了两个
Bean
class
都是MybatisSqlSessionFactoryBean
导致错误。 -
要学会看错误信息。
@TableId
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认基于雪花算法的策略生成 id。
当数据库表主键名不是 ID 时,可以使用 @TableId
将它标识为主键。
Value
若实体类中主键对应的属性为 id,而表中表示主键的字段为 uid,可以使用@TableId(value = "uid")
标识,进行映射。type
type属性用来定义主键策略。IdType.ASSIGN_ID (默认)
基于雪花算法生成 ID ,与数据库ID是否自增无关。IdType.AUTO
使用数据库的自增策略,注意,该类型请确保数据库设置了id自增,否则无效。
配置全局
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<!-- 设置实体类所对应的表的前缀 -->
<property name="tablePrefix" value="t_"></property>
<!-- 设置全局主键策略 -->
<property name="idType" value="AUTO"></property>
</bean>
</property>
</bean>
雪花算法
背景
需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量。
数据库的扩展方式主要包括:业务分库、主从复制,数据库分表。
数据库分表
将不同业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但如果业务
继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈。例如,淘宝的几亿用户数据,
如果全部存放在一台数据库服务器的一张表中,肯定是无法满足性能要求的,此时就需要对单表数据进
行拆分。
单表数据拆分有两种方式:垂直分表和水平分表。示意图如下:
垂直分表
垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。
即将经常查询的属性使用一张表,查询时效率更快。
水平分表
水平分表适合表行数特别大的表,有的公司要求单表行数超过 5000 万就必须进行分表,这个数字可以
作为参考,但并不是绝对标准,关键还是要看表的访问性能。对于一些比较复杂的表,可能超过 1000
万就要分表了;而对于一些简单的表,即使存储数据超过 1 亿行,也可以不分表。
但不管怎样,当看到表的数据量达到千万级别时,作为架构师就要警觉起来,因为这很可能是架构的性
能瓶颈或者隐患。
水平分表相比垂直分表,会引入更多的复杂性,例如要求全局唯一的数据id该如何处理
-
主键自增
(1)以最常见的用户 ID 为例,可以按照 1000000 的范围大小进行分段,1 ~ 999999 放到表 1中,
1000000 ~ 1999999 放到表2中,以此类推。(2)复杂点:分段大小的选取。分段太小会导致切分后子表数量过多,增加维护复杂度;分段太大可能会
导致单表依然存在性能问题,一般建议分段大小在 100 万至 2000 万之间,具体需要根据业务选取合适
的分段大小。(3)优点:可以随着数据的增加平滑地扩充新的表。例如,现在的用户是 100 万,如果增加到 1000 万,
只需要增加新的表就可以了,原有的数据不需要动。(4)缺点:分布不均匀。假如按照 1000 万来进行分表,有可能某个分段实际存储的数据量只有 1 条,而另外一个分段实际存储的数据量有 1000 万条。
-
取模
(1)同样以用户 ID 为例,假如我们一开始就规划了 10 个数据库表,可以简单地用 user_id % 10 的值来
表示数据所属的数据库表编号,ID 为 985 的用户放到编号为 5 的子表中,ID 为 10086 的用户放到编号
为 6 的子表中。(2)复杂点:初始表数量的确定。表数量太多维护比较麻烦,表数量太少又可能导致单表性能存在问题。
(3)优点:表分布比较均匀。
(4)缺点:扩充新的表很麻烦,所有数据都要重分布。
雪花算法的思想
雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。
(1)核心思想:
长度共64bit(一个long型)。
首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负
数是1,所以id一般是正数,最高位是0。
41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。
(2)优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
@TableField (解决属性名和字段名不同的问题)
MyBatis-Plus 中有默认配置将驼峰命名规则映射到数据库命名规则。
当实体类属性名和字段名不相同并且也不满足驼峰→下划线的规则。
就使用 @TableField
指定属性对应的字段名,从而解决属性名和字段名不能进行映射的情况。
@TableLogic (逻辑删除)
-
物理删除:
真实删除
,将对应数据从数据库中删除,之后查询不到此条被删除的数据 -
逻辑删除:
假删除
,将对应数据中代表是否被删除字段的状态修改为被删除状态
,之后在数据库
中仍旧能看到此条数据记录。 -
使用场景:可以进行数据恢复。
-
使用了
@TableLogic
那么查询会自动判断是否已经逻辑删除。
(1)实体类以及数据库中添加表示删除的属性/字段
(2)实体类属性上使用 @TableLogic
标识
此时就实现了逻辑删除,再次执行删除操作时就进行的是逻辑删除会将 is_deleted = 1
,此时再进行查询时,是查询不到已经逻辑删除的数据的。
wapper介绍
Wrapper : 条件构造抽象类,最顶端父类
- AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
- QueryWrapper : 查询条件封装
- UpdateWrapper : Update 条件封装
- AbstractLambdaWrapper : 使用Lambda 语法
- LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
- LambdaUpdateWrapper : Lambda 更新封装Wrapper
使用QueryWrapper
QueryWrapper查询
QueryWrapper 添加查询条件
@Test
public void test1() {
// 查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// SELECT id,name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
// Parameters: %a%(String), 20(Integer), 30(Integer)
queryWrapper.like("name", "a").between("age", 20, 30).isNotNull("email");
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
column
是数据库中字段名。like
会自动添加%
QueryWrapper 只查询指定字段
@Test
public void test1() {
// 查询用户信息的 name 和 age 字段
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name", "age");
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
QueryWrapper 实现子查询
@Test
public void test1() {
// 查询 ID 小于 10 的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id", "select id from t_user where id <= 10");
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
QueryWrapper 排序
@Test
public void test1() {
// 按年龄降序查询用户,如果年龄相同则按id升序排列
// select * from t_user order by age desc, id asc;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age").orderByAsc("id");
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
QueryWrapper 删除
@Test
public void test1() {
//删除email为空的用户
// delete from t_user where (email is null);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
userMapper.delete(queryWrapper);
}
QueryWrapper 更新,以及运算优先级问题
@Test
public void test1() {
// 用法1 : 修改内容 修改条件
// 用法2 : 修改内容(null) 修改条件
// 两个条件之间默认使用 and
//将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
// select * from t_user where (age > 20 and name like %a%) or (email is null)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 20)
.like("name", "a")
.or()
.isNull("email");
User user = new User();
user.setName("阿宝");
userMapper.update(user, queryWrapper);
}
@Test
public void test1() {
//将用户名中包含有a 并且(年龄大于20或邮箱为null)的用户信息修改
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// lambda 表达式内的逻辑优先运算
// 即先运算 gt("age", 19).or().isNull("email")
queryWrapper.like("name", "a")
.and(x -> x.gt("age", 19).or().isNull("email"));
User user = new User();
user.setName("阿宝阿宝");
userMapper.update(user, queryWrapper);
}
userUpdateWrapper
updateWrapper.set()
第一个参数:要修改的字段,第二个参数:修改的值。- 当设置了修改字段以后,就不用再传入实体类声明修改属性了,于是第一个参数为
null
@Test
public void test1() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "阿宝");
updateWrapper.set("email", "阿宝没有邮箱");
userMapper.update(null, updateWrapper);
}
condition 用户传入参数进行组装
(1)声明数据属性
(2)判断数据属性是否正确
(3)拼接进入 Wapper
@Test
public void test1() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
String name = "";
Integer ageBegin = 20;
Integer ageEnd = 30;
if (StringUtils.isNotBlank(name)) {
queryWrapper.like("name", name);
}
if (ageBegin != null) {
queryWrapper.gt("age", ageBegin);
}
if (ageEnd != null) {
queryWrapper.lt("age", ageEnd);
}
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
但是代码有些繁琐。
可以使用带condition
参数的重载方法构建查询条件,简化代码的编写。
condition
是一个布尔类型。
@Test
public void test1() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
String name = "";
Integer ageBegin = 20;
Integer ageEnd = 30;
queryWrapper.like(StringUtils.isNotBlank(name), "name", name)
.gt(ageBegin != null, "age", ageBegin)
.lt(ageEnd != null, "age", ageEnd);
for (User user : userMapper.selectList(queryWrapper)) {
System.out.println(user);
}
}
插件
(1)添加配置
<!--配置插件-->
<property name="plugins">
<array>
<ref bean="mybatisPlusInterceptor"></ref>
</array>
</property>
<!--配置MyBatis-Plus插件-->
<bean id="mybatisPlusInterceptor"
class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<ref bean="paginationInnerInterceptor"></ref>
</list>
</property>
</bean>
<!--配置MyBatis-Plus分页插件的bean-->
<bean id="paginationInnerInterceptor"
class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor">
<!--设置数据库类型-->
<property name="dbType" value="MYSQL"/>
</bean>
剩下都是基于 Stringboot 学到了再回来学
指导复习的问题
错误
- 定义
Bean
时,创建了两个Bean
引用一个类的情况。