视频课程地址:黑马商城项目
上一节:MybatisPlus(二)核心功能02 — 自定义SQL
本节学习MybatisPlus(MP)的核心功能 — IService接口:
- IService接口基本用法
- IService开发基础业务接口
- IService开发复杂业务接口
- IService的lambda方法
- IService批量新增
一、IService 接口基本用法
1.1 IService接口
1.1.1 新增接口
save(T)
:保存一个实体类。saveBatch(Collection<T>)
:批量新增实体对象集合。saveBatch(Collection<T>, int)
:批量新增实体对象集合,按照第二个参数分批次新增。- 例如:集合中有90个实体对象,第二个参数为20,那么会分为5次进行保存,前4次每次20个,最后一次10个。
saveOrUpdateBatch(Collection<T>)
:批量新增或修改实体对象集合。- 传入的参数会判断是否存在id参数,如果有就会认为是更新操作;如果没有就是新增操作。
saveOrUpdateBatch(Collection<T>, int)
:分批次,批量新增或修改实体对象集合。效果同上。saveOrUpdate(T)
:新增或修改实体对象。saveOrUpdate(T, Wrapper<T>)
:新增或修改实体对象,第二个参数定义查询条件,不再是默认id。
1.1.2 删除接口
removeById(Serializable)
:根据ID删除数据。removeById(Serializable, boolean)
:根据ID删除数据。第二个参数是控制逻辑删除或者物理删除。- 第二个boolean参数:
true
:逻辑删除,更新配置的[逻辑删除字段]为[逻辑删除值];false
:物理删除。
- 第二个boolean参数:
removeById(T)
:识别实体对象的主键进行删除。removeByMap(Map<String, Object>)
:根据给定的条件映射来构建WHERE
子句删除数据。remove(Wrapper<T>)
:根据构造条件给定的WHERE
子句删除数据。removeByIds(Collection<?>)
:根据主键集合批量删除数据。(适合主键集合元素较少时使用,采用DELETE
+ID IN
)removeByIds(Collection<?>, boolean)
:根据主键集合批量删除数据。第二个参数控制true
(逻辑删除)/false
(物理删除)removeBatchByIds(Collection<?>)
:根据主键集合分批次批量删除数据。(适合主键集合元素较多时使用,采用DELETE
+ID=?
,会采用JDBC批处理方案)removeBatchByIds(Collection<?>, boolean)
:根据主键集合分批次批量删除数据。第二个参数效果同上。removeBatchByIds(Collection<?>, int)
:根据主键集合分批次批量删除数据。第二个元素控制每批次数量。removeBatchByIds(Collection<?>, int, boolean)
:根据主键集合分批次批量删除数据。第二个元素控制每批次数量。第三个参数控制true
(逻辑删除)/false
(物理删除)。
1.1.3 修改接口
- 前两个和最后一个就不说了,新增接口时已经介绍了
updateById(T)
:根据ID进行修改,实体对象只要非空就会修改。update(Wrapper<T>)
:根据构造条件进行修改,实体对象只要非空就会修改。update(T, Wrapper<T>)
:根据构造条件对实体对象进行修改。updateBatchById(Collection<T>)
:根据主键ID批量修改。updateBatchById(Collection<T>, int)
:根据主键ID分批次批量修改,第二个参数定义每批次数量。
1.1.4 查询接口(查一个)
getById(Serializable)
:根据主键ID查询。getOne(Wrapper<T>)
:根据构造条件查询。需要保证构造条件只能查到一个,否则会异常。getOne(Wrapper<T>, boolean)
:根据构造条件查询。第二个参数:控制异常抛出- 如果查询到不止一条数据,正常程序会抛出
TooManyResultsException
异常。 true
:会抛出异常;false
:不会抛出异常,会返回第一条记录。
- 如果查询到不止一条数据,正常程序会抛出
1.1.5 查询接口(查统计)
count()
:查询统计总数count(Wrapper<T>)
:根据构造条件查询统计总数
1.1.6 查询接口(查多个/列表)
listByIds(Collection<? extends Serializable>)
:根据ID集合查询。listByMap(Map<String, Object>)
:根据给定的条件映射作为WHERE
条件查询list(Wrapper<T>)
:根据构造条件查询list()
:查询所有数据
1.1.7 查询接口(分页查询)
page(E, Wrapper<T>)
:分页查询。E
:分页对象,通常需要实现IPage
接口,常用Page
类,查询结果也会封装到这个对象中。Wrapper<T>
:构造查询条件
page(E)
:没有查询条件,直接分页查询。
1.1.8 Lambda接口
基于这种Lambda的接口,可以直接使用链式编程方式,不用自己去 new
一个 Wrapper
。
建议:
如果是基于ID等的简单查询或更新就用前面的方法;
如果是复杂查询,那么可以使用lambda进行链式编程查询。
lambdaQuery()
:创建一个基于 Lambda 表达式的查询条件构造器LambdaQueryWrapper
lambdaQuery(T)
:创建基于 Lambda 表达式的查询条件构造器。构造器会根据实体对象中不为null
的属性自动生成等值查询条件。lambdaUpdate()
:创建一个基于 Lambda 表达式的更新条件构造器LambdaUpdateWrapper
。
1.2 IService的使用
继承和实现逻辑:
1.2.1 创建自定义Service接口
自定义接口继承IService
即可,需要给出 User
的泛型。
package com.itheima.mp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;
public interface IUserService extends IService<User> {
}
1.2.2 创建自定义Service实现类
自定义接口实现类,实现自定义接口UserService
,并继承ServiceImpl
类并给出两个泛型:UserMapper
和 User
。
ServiceImpl
通过UserMapper
调用它继承的BaseMapper
中的方法。
package com.itheima.mp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
1.2.3 测试 – 单个新增
package com.itheima.mp.service;
import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
@SpringBootTest
class IUserServiceTest {
@Autowired
private IUserService userService;
@Test
void testSaveUser() {
User user = new User();
user.setId(6L);
user.setUsername("李白");
user.setPassword("123456");
user.setPhone("18688990012");
user.setBalance(10086);
user.setInfo("{\"age\": 1324, \"intro\": \"诗词老师\", \"gender\": \"male\"}");
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userService.save(user);
}
}
这里测试了一个 save(Entity)
的接口方法。
运行结果:
成功添加数据。
1.2.4 测试 – 查询列表
@Test
void testQueryByIds() {
List<Long> idList = List.of(1L, 3L, 6L);
List<User> users = userService.listByIds(idList);
users.forEach(System.out::println);
}
运行结果:
1.3 总结
二、IService 开发基础业务接口
2.1 通过案例学习
本节只学习1-4项,第五项为第三节学习,为复杂业务接口。
2.2 引入依赖
因为我们需要实现Restful风格的接口,所以需要引入web依赖。
然后为了方便测试,我们使用swagger进行测试接口,然后需要引入swagger依赖。
pom.xml中加入如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
2.3 做swagger的配置
在application.yml文件中新增:
knife4j:
enable: true # 开启
openapi:
title: 用户管理接口文档
description: "用户管理接口文档"
email: 2451203736@qq.com
concat: 陶其
url: https://www.tqazy.com
version: v1.0.0
group:
default:
group-name: default
api-rule: package
api-rule-resources:
- com.itheima.mp.controller
顺便将mybatis的配置改成mybatis-plus的:
mybatis-plus:
type-aliases-package: com.tiheima.mp.domain.po
global-config:
db-config:
id-type: auto # ID自增
2.4 导入dto文件和vo文件
UserFormDTO.java
package com.itheima.mp.domain.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "用户表单实体")
public class UserFormDTO {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("注册手机号")
private String phone;
@ApiModelProperty("详细信息,JSON风格")
private String info;
@ApiModelProperty("账户余额")
private Integer balance;
}
UserVo
package com.itheima.mp.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "用户VO实体")
public class UserVO {
@ApiModelProperty("用户id")
private Long id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("详细信息")
private String info;
@ApiModelProperty("使用状态(1正常 2冻结)")
private Integer status;
@ApiModelProperty("账户余额")
private Integer balance;
}
2.5 创建并编写UserController
import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {
private final IUserService userService;
@ApiOperation("新增用户接口")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO) {
// 1. 把DTO拷贝到PO
User user = BeanUtil.copyProperties(userDTO, User.class);
// 2. 新增
userService.save(user);
}
@ApiOperation("删除用户接口")
@DeleteMapping("{id}")
public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id) {
userService.removeById(id, true);
}
@ApiOperation("根据id查询用户")
@GetMapping("{id}")
public UserVO getUserById (@ApiParam("用户id") @PathVariable("id") Long id) {
User user = userService.getById(id);
return BeanUtil.copyProperties(user, UserVO.class);
}
@ApiOperation("根据id批量查询")
@GetMapping
public List<UserVO> getAllUser(@ApiParam("用户id集合") @RequestParam("idList") List<Long> idList) {
List<User> users = userService.listByIds(idList);
return BeanUtil.copyToList(users, UserVO.class);
}
}
代码注解:
@RequiredArgsConstructor
: 配合private final IUserService userService;
中final
,可以实现必须的依赖通过构造函数注入,必须的依赖使用final
关键字修饰。比@Resources
更推荐使用,@Resources
是JavaEE的注解,更推荐Spring的注解。
未完待续。。。