文章目录

目标:
- 代码生成
- 静态工具
- 逻辑删除
- 每局处理器
- JSON处理器
1.代码生成
这个自己试试叭!
2.静态工具

跟IService的很像,但是IService中的方法都是非静态的,所以我们要自定义接口并且继承它,继承它的过程中还要指定泛型,泛型就是实体类的类型,为什么要执行实体类的类型?因为要通过反射获取字节码得到表信息才能增删改查。而Db都是静态的。类上是没有泛型的或者说静态的方法是没有办法读取到泛型的,因此Db上是没有泛型的,那么如何去做增删改查呢?所以你发现它的方法都需要我们传递一个额外的参数-字节码。
查地址的时候要注入user,查user的时候要注入地址,出现了循环依赖,那么我们就可以通过这个静态工具来解决。
AddressVO
java
@Data
@ApiModel(description = "收货地址VO")
public class AddressVO{
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("用户ID")
private Long userId;
@ApiModelProperty("省")
private String province;
@ApiModelProperty("市")
private String city;
@ApiModelProperty("县/区")
private String town;
@ApiModelProperty("手机")
private String mobile;
@ApiModelProperty("详细地址")
private String street;
@ApiModelProperty("联系人")
private String contact;
@ApiModelProperty("是否是默认 1默认 0否")
private Boolean isDefault;
@ApiModelProperty("备注")
private String notes;
}
UserVO
java
@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;
private List<AddressVO> addresses;
}
出现循环依赖可以使用静态工具
java
public UserVO queryUserAndAddressById(Long id) {
//1.查询用户
User user = this.getById(id);
if(user==null || user.getStatus()!=1){
throw new RuntimeException("用户状态异常");
}
//2.查询地址
List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
//3.封装返回值
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
if(addresses!=null && addresses.size()>0){
userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
}
return userVO;
}
第二题
java
@ApiOperation("根据id批量查询用户接口")
@PostMapping("/users")
public List<UserVO> queryUser(@RequestParam("ids") List<Long> ids){
return userService.queryUserAndAddressByIds(ids);
}
java
public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
//1.查询用户
List<User> users = listByIds(ids);
if(users==null || users.size()!=ids.size()){
throw new RuntimeException("用户状态异常");
}
//2.查询地址
//2.1 获取用户id集合
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
//2.2 查询地址
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
//2.3 转换Address的PO为VO
List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
//2.4 梳理地址集合,分类整理,相同用户的地址放在一起 分组
Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);
if(CollUtil.isNotEmpty(addressVOList)){
addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
}
//3.封装返回值
List<UserVO>list = new ArrayList<>(users.size());
for (User user : users) {
//3.1 转换User的PO为VO
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
list.add(userVO);
userVO.setAddresses(addressMap.get(user.getId()));
}
return list;
}
3.逻辑删除
有一些数据是非常重要的,不能直接删除
我配完之后写了一个测试类测试一下:
java
@SpringBootTest
class IAddressServiceTest {
@Autowired
private IAddressService addressService;
@Test
void testLogicDelete(){
addressService.removeById(60L);
Address address = addressService.getById(60L);
System.out.println(address);
}
}
4.枚举处理器

这里我们会涉及到枚举类型跟int类型之间的转换问题,其实也不仅仅是这一个;类型,我们java中所有的数据类型都要跟数据库的类型做转换,可能我们平时都没有主动转换过,但是我们没有做过并不代表没有,我们所认为的岁月静好,只不过是有人在替我们负重前行,底层都是由mybatis
帮我们完成,mybatis
如何实现类型转换呢?
我们这里使用MybatisEnum TypeHandler,分两步使用,我们得告诉mp那个属性是对应数据库的字段,用注解@EnumValue
第二步:让它生效
记得VO也要改,但是返回就会以枚举项返回,我们的数据往前端返回是由SpringMVC处理的,SpringMVC处理JSON用的是Jackson,它提供了一个注解来表明返回枚举中那个值进行返回@JsonValue
5.JSON处理器
但是mybatis没有能力帮我们做userInfo跟JSON数据类型的转换,所以我们只能自己来
我们使用JacksonTypeHandler实现类
没有全局配置,只能一个个配.现在这里面出现了对象嵌套,User中又出现了info
往往就需要去定义resultMap,但是我们又不想定义

准备实体:
插件功能

最常见,我们一般可以用pageHelper,但是mp也提供了
这里分为两个小节
- 分页插件
- 通用分页实体
配置
java
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 MyBatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 这里可以添加多个插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(1000L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
测试类:
java
@Test
void testPageQuery(){
int pageNo = 1;
int pageSize = 2;
//1.准备分页条件
//1.1分页条件
Page<User>page = new Page<>(pageNo, pageSize);
//1.2排序条件
page.addOrder(OrderItem.desc("id"));
//2.执行分页查询
Page<User> result = userService.page(page);
//3.输出结果
result.getRecords().forEach(System.out::println);
System.out.println("总记录数:" + result.getTotal());
System.out.println("总页数:" + result.getPages());
System.out.println("当前页:" + result.getCurrent());
System.out.println("是否有前一页:" + result.hasPrevious());
System.out.println("是否有下一页:" + result.hasNext());
}


返回值:
通用分页实体
封装一个实体:
java
import lombok.Data;
@Data
public class PageQuery {
private Integer pageNo;
private Integer pageSize;
private String sortBy;
private Boolean isAsc;
}
java
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery extends PageQuery {
@ApiModelProperty("用户名关键字")
private String name;
@ApiModelProperty("用户状态:1-正常,2-冻结")
private Integer status;
@ApiModelProperty("余额最小值")
private Integer minBalance;
@ApiModelProperty("余额最大值")
private Integer maxBalance;
}
定义一个统一分页结果,我们说不定以后在微服务中也会使用到所以可以定义在dto包
java
@Data
public class PageDTO<T> {
private Long total;
private Long pages;
private List<T> list;
}
接口声明:
java
@ApiOperation("根据复杂条件分页查询用户接口")
@GetMapping("/page")
public PageDTO<UserVO> queryUsersPage(UserQuery query){
return userService.queryUsersPage(query);
}
java
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
//1.构建查询条件
String name = query.getName();
Integer status = query.getStatus();
Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
if(StrUtil.isNotBlank(query.getSortBy())){
page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
}else{
//默认排序
page.addOrder(new OrderItem("update_time" , false));
}
//2.分页查询
Page<User> p = lambdaQuery().
like(name != null, User::getUsername, name)
.eq(status != null, User::getStatus, status)
.page(page);
//3.转换PO为VO
PageDTO<UserVO> dto = new PageDTO<>();
dto.setTotal(p.getTotal());
dto.setPages(p.getPages());
List<User> records = p.getRecords();
if(CollUtil.isEmpty(records)){
dto.setList(new ArrayList<>());
return dto;
}
//3.1 转换User的PO为VO
dto.setList(BeanUtil.copyToList(records, UserVO.class));
//3.2 封装地址信息
//4.返回
return dto;
}

通用分页实体与MP转换
很多代码跟业务关系不大,比较通用

java
@Data
public class PageQuery {
private Integer pageNo = 1;
private Integer pageSize = 5;
private String sortBy;
private Boolean isAsc = true;
public <T> Page<T> toMpPage(OrderItem ...items){
Page<T> page = Page.of(pageNo, pageSize);
if(StrUtil.isNotBlank(sortBy)){
page.addOrder(new OrderItem(sortBy, isAsc));
}else if(items!= null && items.length > 0){
//默认排序
page.addOrder(items);
}
return page;
}
public <T> Page<T> toMpPage(String sortBy, Boolean isAsc){
return toMpPage(new OrderItem(sortBy, isAsc));
}
public <T> Page<T> toMpPageDefaultByCreatTime(){
return toMpPage(new OrderItem("create_time",false));
}
public <T> Page<T> toMpPageDefaultByUpdateTime(){
return toMpPage(new OrderItem("update_time",false));
}
}
java
import java.util.ArrayList;
import java.util.List;
@Data
public class PageDTO<T> {
private Long total;
private Long pages;
private List<T> list;
public static <PO,VO> PageDTO<VO> of(Page<PO> p,Class<VO> voClass){
PageDTO<VO> dto = new PageDTO<>();
dto.setTotal(p.getTotal());
dto.setPages(p.getPages());
List<PO> records = p.getRecords();
if(CollUtil.isEmpty(records)){
dto.setList(new ArrayList<>());
return dto;
}
//3.1 转换User的PO为VO
dto.setList(BeanUtil.copyToList(records, voClass));
//3.2 封装地址信息
//4.返回
return dto;
}
}
最终:
java
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
//1.构建查询条件
String name = query.getName();
Integer status = query.getStatus();
Page<User> page = query.toMpPage();
//2.分页查询
Page<User> p = lambdaQuery().
like(name != null, User::getUsername, name)
.eq(status != null, User::getStatus, status)
.page(page);
//3.转换PO为VO
return PageDTO.of(p, UserVO.class);
}
但是要记住Beanutil的使用要求User,UserVo的属性名要相同,如果不同需要自己完成转换,那能不能封装一个方法别的方法你帮我写好但是从PO到VO的转换我自己来写
java
public class PageDTO<T> {
private Long total;
private Long pages;
private List<T> list;
public static <PO,VO> PageDTO<VO> of(Page<PO> p, Function<PO,VO> converter){
PageDTO<VO> dto = new PageDTO<>();
dto.setTotal(p.getTotal());
dto.setPages(p.getPages());
List<PO> records = p.getRecords();
if(CollUtil.isEmpty(records)){
dto.setList(new ArrayList<>());
return dto;
}
//3.1 转换User的PO为VO
dto.setList(records.stream().map(converter).collect(Collectors.toList()));
//3.2 封装地址信息
//4.返回
return dto;
}
}
java
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
//1.构建查询条件
String name = query.getName();
Integer status = query.getStatus();
Page<User> page = query.toMpPage();
//2.分页查询
Page<User> p = lambdaQuery().
like(name != null, User::getUsername, name)
.eq(status != null, User::getStatus, status)
.page(page);
//3.转换PO为VO
return PageDTO.of(p, user->{
//1.拷贝基础属性
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
//2.处理特殊逻辑
vo.setUsername(vo.getUsername().substring(0,vo.getUsername().length()-2)+"**");
return vo;
});
}

完结啦~~