在Mybatis里有一个叫TypeHandler的类型处理器,我们常见的PO当中的这些成员变量的数据类型,它都有对应的处理器,因此它就能自动实现这些Java数据类型与数据库类型的相互转换。
它里面还有一个叫EnumOrdinalTypeHandler的枚举处理器,但是它不能帮我们把这个枚举跟数据库里面的int做转换。MybatisPlus对这些类型处理器做了扩展,加入了几个类型处理器,其中有一个叫MybatisEnumTypeHandler是Mybatis枚举的一个类型处理器,还有一个叫AbstractJsonTypeHandler顾名思义就是JSON类型的处理器。也就是说这两个处理器,一个用来处理枚举类型,一个用来处理JSON类型的。
要使用MybatisEnumTypeHandler枚举类型处理器分两步。
1.首先将来我们要把这个枚举转成int存到数据库,所以要告诉mp哪个是对应的数据库里面的这个int。我们要把这个成员变量标记出来,mp提供了一个注解@EnumValue,把它加到枚举对应数据库字段的值上面。那么将来它就知道了原来枚举中的这个value的值和数据库对应的,它就会拿这两个往数据库里面去写,查询的时候就反过来操作。
2.让MybatisEnumTypeHandler枚举处理器生效。
java">package com.itheima.mp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Override
public void deductBalance(Long id, Integer money) {
//1.查询用户
User user = getById(id);
//2.校验用户状态
if(user == null || user.getStatus() == UserStatus.FROZEN){
throw new RuntimeException("用户状态异常!");
}
//3.校验余额是否充足
if(user.getBalance() < money){
throw new RuntimeException("用户余额不足!");
}
//4.扣减余额update tb_user set balance = balance - ?
int remainBalance = user.getBalance()-money;
lambdaUpdate()
.set(User::getBalance,remainBalance)
.set(remainBalance == 0,User::getStatus,UserStatus.FROZEN)
.eq(User::getId,id)
.eq(User::getBalance,user.getBalance())//乐观锁
.update();
}
@Override
public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {
return lambdaQuery()
.like(name != null,User::getUsername,name)
.eq(status != null,User::getStatus,status)
.gt(minBalance != null,User::getBalance,minBalance)
.lt(maxBalance != null,User::getBalance,maxBalance)
.list();
}
@Override
public UserVO queryUserAndAddressById(Long id) {
//1.查询用户
User user = getById(id);
if(user == null || user.getStatus() == UserStatus.NORMAL){
throw new RuntimeException("用户状态异常!");
}
//2.查询地址
List<Address> addresses = Db.lambdaQuery(Address.class)
.eq(Address::getUserId, id).list();
//3.封装VO
//3.1.转User的PO为VO
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
//3.2.转地址VO
if (CollUtil.isNotEmpty(addresses)){
userVO.setAddress(BeanUtil.copyToList(addresses, AddressVO.class));
}
return userVO;
}
@Override
public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
//1.查询用户
List<User> users = listByIds(ids);
if (CollUtil.isEmpty(users)){
return Collections.emptyList();
}
//2.查询地址
//2.1.获取用户id集合
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
//2.2.根据用户id查询地址
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
//2.3.转换地址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.转换VO返回
List<UserVO> list = new ArrayList<>(users.size());
for (User user : users) {
//3.1.转化User的PO为VO
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
list.add(vo);
//3.2.转换地址VO
vo.setAddress(addressMap.get(user.getId()));
}
return list;
}
}
枚举默认在做JSON数据格式处理的时候,就会以英文名返回,就是枚举项的名字。那如果说你想让它以value返回,也就是1和2返回,或者是以desc这个中文返回,那么你就需要告诉我们程序,我们这个程序的数据往前端返回由Spring MVC处理,Spring MVC 底层它在处理JSON的时候用到一个Jackson包,Jackson它提供一些注解用来标记这个枚举里面的值到底把谁进行返回。