MybatisPlus和代码自动生成器
MybatisPlus
MybatisPlus简介
MybatisPlus 是对Mybatis框架的增强,并没有改变Mytatis框架的内容,只是更加的方便开发,提高开发效率。在MybatisPlus中对单表查询的增删改查操作已经进行了封装,不需要我们再进行编写。对于多表之间的操作,还需要我们进行mapper和sql的编写,Wrapper可以看作是封装的一些条件,其中有一些sql语句的代码方式,放在下面。
官网:https://baomidou.com/,下面是其特性:
- 无侵入:只做增强不做改变,不会对现有工程产生影响
- 强大的 CRUD 操作:内置通用 Mapper,少量配置即可实现单表CRUD操作
- 支持 Lambda:编写查询条件无需担心字段写错
- 支持主键自动生成
- 内置分页插件
MybatisPlus基本配置
MybatisPlus起步依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
Yaml配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo
username: root
password: root
配置表名映射
@Tablename(“”)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("tbl_product")
public class Product {
@TableId(value = "id",type = IdType.ASSIGN_ID)
// @TableId(value = "id",type = IdType.AUTO)
private Long id;
private String pname;
private String brand;
private Double price;
private Integer num;
private Integer online;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date lastUpdateTime;
private Integer version;
private Integer deleted;
@TableField(exist = false)
private String desc;
}
Mapper继承BaseMapper<实体类> 接口
//@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
第一个MybatisPlus案例
自动生成yml和启动类—JBLSpringBootAppliacation插件
Service extends IService
为了简化service代码编写,mybatisPlus提供了通用 Service CRUD 封装IService接口
- 进一步封装 CRUD 采用
get 查询单行
remove 删除
list 查询集合
page 分页
前缀命名方式区分Mapper
层避免混淆
分类 | 方法 | 描述 |
---|---|---|
新增 | boolean save(T entity) | 新增,entity 实体对象 |
boolean saveOrUpdate(T entity) | id存在则更新记录,否插入一条记录 | |
boolean saveBatch(Collection entityList) | 插入(批量),默认一次可以保存1000条数据 | |
修改 | boolean updateById(T entity) | 根据 ID 修改 |
boolean update(T entity,Wrapper updateWrapper) | 根据 条件 修改 | |
查询 | T getById(Serializable id) | 根据 ID 查询 |
List listByIds(Collection idList) | 查询(根据ID 批量查询) | |
List list() | 查询所有 | |
List list(Wrapper queryWrapper) | 条件查询 | |
删除 | boolean removeById(Serializable id) | 根据 ID 删除 |
boolean removeByIds(Collection idList) | 删除(根据ID 批量删除) | |
boolean remove(Wrapper queryWrapper) | 根据条件删除 |
public interface ProductService extends IService<Product> {
}
ServiceImpl extends ServiceImpl<Mapper,Pojo> implents Service
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
}
Mapper extends BaseMapper
**BaseMapper<T>**:通用 CRUD 封装 `BaseMapper` 接口, 泛型 `T` 为任意实体对象
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
}
MyBatisPlus 提供了 Wrapper 条件构造器
接口,用于设置条件
- QueryWrapper LambdaQueryWrapper 设置查询、删除条件
- UpdateWrapper LambdaUpdateWrapper 设置修改条件
MP条件查询 API
AbstractWrapper提供了大量设置条件的方法
方法 | 说明 |
---|---|
eq (equals) | 等于= |
ne (not equals) | 不等与<> |
gt (greater than) | 大于> |
ge (greater equals) | 大于等于>= |
lt (less than) | 小于< |
le (less equals) | 小于等于<= |
between | between…and… |
like | 模糊查询 LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
or | or |
public interface ProductMapper extends BaseMapper<Product> {
}
Controller 封装Wrapper对象和查询条件
@Component
public class MyMateObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", new Date());
metaObject.setValue("lastUpdateTime", new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("lastUpdateTime", new Date());
}
}
利用PostMan测试通过
四个重要注解
@TableName(表名)
当数据库表对应的实体类类名一致的时候也可以省略,主要是为了数据表和实体类之间建立映射关系。
yml全局配置TableName前缀(关键字 table-prefix)
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
@TableId(value=“不一致可起名”,type= 3个常见主键自增属性 2 4 5 )
主要是为了设置数据表中主键字段的自增策略,常见的有三种 2 4 5
值 | 描述 |
---|---|
NONE | 默认值 相当于INPUT+ASSIGN_ID |
AUTO | 数据库主键自增 |
INPUT | 手动设置主键值 |
ASSIGN_ID | 主键对应的类型可以是数字类型或者数字类型的字符串 由java客户端,底层基于雪花算法,生成的唯一主键 |
ASSIGN_UUID | 生成的主键值包含数字和字母组成的字符串UUID 示例:b463ec84690de187e3f9ad9229327d15 |
yml全局配置TableId(关键字 id-type)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 标准注解
global-config:
db-config:
table-prefix: tbl_
id-type: auto
注解配置(冲突时注解为准)
当id字段和属性名不一致的时候也可以使用value字段进行映射
@TableId(value = "id",type = IdType.ASSIGN_ID)
private Long id;
@TableFiled(4个常见属性)
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
value | String | “” | 数据库字段名,如果同名可以省略 |
exist | boolean | true | 是否为数据库表字段,如果表中没有该字段必须设置为false,CRUD都不会包含该字段 |
fill | Enum | FieldFill.DEFAULT | 字段自动填充策略,默认不会自动填充值 |
value
进行实体类属性与数据库表字段的对应
select()
默认值是true,可以设置为false 指定某个字段在查询时不进行查询,例如 : 密码或敏感字段
exist()
当实体类的属性上有某个属性而数据库表字段中没有对应字段的时候设置可以为false
fill
官方示例代码:https://baomidou.com/pages/4c6bcf/
自动填充某些字段,例如 create_time 这样的字段,有几个常见的值 (2 4 常用)
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date lastUpdateTime;
自动填充配置类
package com.itheima.mp.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
this.strictInsertFill(metaObject, "lastUpdateTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "lastUpdateTime", Date.class, new Date()); // 起始版本 3.3.0(推荐)
}
}
@TableLogic(逻辑删除)
逻辑删除:为数据设置字段
标识该数据是否可用,默认状态是可用,删除时设置状态字段为不可用状态,数据依然保留在数据库中
-- 删除改成更新状态
UPDATE tbl_product SET deleted=1 WHERE id=? AND deleted=0
-- 查询需要添加一个逻辑删除条件
SELECT * FROM tbl_product WHERE deleted=0
表中添加逻辑删除字段
修改实体类
实体类中添加对应字段,通过 @TableLogic
注解标识这是逻辑删除字段
@TableLogic
private Integer deleted;
全局配置逻辑删除(关键字 logic )
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
table-prefix: tbl_
id-type: auto
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
分页查询插件
Mybatis内置了专门用于分页的插件,使用起来非常简单,它是基于拦截器原理实现分页的
官方示例代码:https://baomidou.com/pages/97710a/#paginationinnerinterceptor
添加分页插件拦截器
// MP配置类
@Configuration
public class MybatisPlusConfig {
// MyBatisPlust拦截器配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
分页测试
@Test
public void test() {
Page<Product> page = new Page<>(2,5); //分页参数
LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper();
productMapper.selectPage(page, wrapper);// 返回那个page
System.out.println(page.getTotal());
List<Product> records = page.getRecords();
records.forEach(System.out::println);
}
代码生成器
MybatisPlus插件
安装好插件后重启一个IDEA
配置数据源
代码生成
可以点击 check filed 选择是否要生成某个字段
Mapper添加查询补充练习
可以使用Lambda表达式
API
AbstractWrapper提供了大量设置条件的方法
方法 | 说明 |
---|---|
eq (equals) | 等于= |
ne (not equals) | 不等与<> |
gt (greater than) | 大于> |
ge (greater equals) | 大于等于>= |
lt (less than) | 小于< |
le (less equals) | 小于等于<= |
between | between…and… |
like | 模糊查询 LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
or | or |
基础查询
查询优化-简化判断(查询中有大量if判断,简化书写)
查询优化-lambda查询
查询优化-链式编程
设置查询字段
分组排序排序
课下作业
提示: 从 BaseMpper 提供的方法名称 + 返回值类型,判断是否能实现需求
练习1: 查询商品名称以 OPPO开头,价格 > 1500 ,并且是上架状态的商品,结果按价格降序排序 selectList(wrapper)
@Test
public void test() {
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.likeRight("pname", "OPPO")
.gt("price",1500D)
.eq("online","1")
.orderByDesc("price");
List<Product> products = productMapper.selectList(wrapper);
products.forEach(System.out::println);
}
练习2: 查询id包含 1,2,6,8 并且 pname 不为null, 且是上架状态 的商品信息 selectList(wrapper)
@Test
public void testDemo2() {
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.in("id", "1", "2", "6", "8")
.isNotNull("pname")
.eq("online","1");
List<Product> products = productMapper.selectList(wrapper);
products.forEach(System.out::println);
}
练习3: 查询id包含 1,2,6,8 的商品信息 selectBatchIds(Collection)
@Test
public void testDemo3() {
QueryWrapper<Product> wrapper = new QueryWrapper<>();
// wrapper.like("id",1)
// .or()
// .like("id",2)
// .or()
// .like("id",6)
// .or()
// .like("id",8);
List<Long> list = new ArrayList();
list.add(1L);
list.add(2L);
list.add(6L);
list.add(8L);
List<Product> products = productMapper.selectBatchIds(list);
products.forEach(System.out::println);
}
练习4: 统计价格 > 5000 的商品数量 selectCount(wrapper)
@Test
public void testDemo4() {
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.gt("price", 5000.0);
int sum = productMapper.selectCount(wrapper);
System.out.println(sum);
}
条件修改
条件删除
修改用updateWrapper 和 LambdaUpdateWrapper
查询和删除用queryWrapper或LambdaQueryWrapper