springboot结合Mybatis-plus实现单表增删改查整理
一、单Controller实现CRUD
思路:
- mybatis-plus在业务层已经实现了单表的增删改查,只需要在此基础上使用泛型话处理,即可实现单表的增删改查处理
- 通过ServiceEnums实现主体参数的封装,然后通过在Controller中通过一系列处理实现参数处理以及业务调用即实现统一处理
- 此类处理的重点在泛型编程,只有处理好泛型编程,即可处理好单表的增删改查
1、创建BaseController实现业务表的增删改查
/**
* 适用于单表的增删改查
*/
@RestController
@RequestMapping("/v1/mission")
public class BaseController {
@Autowired
private Validator validator;
@Autowired
private ObjectMapper mapper;
/**
* 查询分页
* @param serviceName 业务名称
* @param paramMap 查询参数
* @return 分页结果
* @throws JsonProcessingException
*/
@GetMapping("/{serviceName}/page")
public MyPage<Object> queryPage(@PathVariable("serviceName") String serviceName,
@RequestParam HashMap paramMap) throws JsonProcessingException {
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
Long pageNo = Optional.ofNullable(MapUtil.getLong(paramMap,"pageNo")).orElse(0L);
Long pageSize = Optional.ofNullable(MapUtil.getLong(paramMap,"pageSize")).orElse(10L);
IPage iPage = new Page(pageNo,pageSize);
//携带查询参数
if(CollUtil.isNotEmpty(paramMap)){
Object entity = mapper.readValue(mapper.writeValueAsString(paramMap),serviceEnum.getDomainDO());
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(entity);
service.page(iPage,queryWrapper);
}else {
//无查询参数
service.page(iPage);
}
//使用convert直接更替
page.convert(e->BeanUtils.map(e,serviceEnum.getDomainVO()));
//List<Object> domainDTOList = iPage.getRecords();
//iPage.setRecords(BeanUtils.mapAsList(domainDTOList,serviceEnum.getDomainVO()));
//IPage<Object> convert = this.page(page).convert(scheduleSectionConverter::convertDo2Vo);
return MyPage.of(iPage);
}
/**
* 查询集合
* @param serviceName 服务名称
* @param querMap 查询参数Map
* @return 返回查询结果
*/
@GetMapping(value = "/{serviceName}/list")
public R<List<?>> queryList(@PathVariable("serviceName") String serviceName,
@RequestParam HashMap querMap) throws JsonProcessingException {
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper();
if(CollUtil.isNotEmpty(querMap)){
Object domainDO = mapper.readValue(mapper.writeValueAsString(querMap),serviceEnum.getDomainDO());
queryWrapper.setEntity(domainDO);
}
//一页限制30个
queryWrapper.last("limit 50");
List<Object> resultList = service.list(queryWrapper);
List<?> resultVOList = BeanUtils.mapAsList(resultList, serviceEnum.getDomainVO());
return R.success(resultVOList);
}
/**
* 通过ID查询对象
* @param serviceName 业务名称
* @param id 参数ID
* @return 查询结果
*/
@GetMapping(value = "/{serviceName}/get/{id}")
public R<Object> getById(@PathVariable("serviceName") String serviceName,
@PathVariable("id") Serializable id) {
MissionErrorEnums.ARGUMENT_MUST_NOT_NULL.assertNotNull(id);
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
Object domainDO = service.getById(id);
Object domainDTO = BeanUtils.map(domainDO, serviceEnum.getDomainVO());
return R.success(domainDTO);
}
/**
* 新增数据
* @param serviceName 业务名称
* @param jsonParam json参数
* @return 操作结果
*/
@PutMapping("/{serviceName}/save")
public R<Boolean> save(@PathVariable("serviceName") String serviceName,
@RequestBody String jsonParam) {
MissionErrorEnums.ARGUMENT_MUST_NOT_NULL.assertNotEmpty(jsonParam);
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
Object domainDO = this.validateAndConvert2DO(jsonParam,serviceEnum);
return R.success(service.save(domainDO));
}
/**
* 更新数据
* @param serviceName 业务名称
* @param jsonParam json参数
* @return 操作结果
*/
@PostMapping("/{serviceName}/update")
public R<Boolean> update(@PathVariable("serviceName") String serviceName,
@RequestBody String jsonParam) {
MissionErrorEnums.ARGUMENT_MUST_NOT_NULL.assertNotEmpty(jsonParam);
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
Object domainDO = this.validateAndConvert2DO(jsonParam,serviceEnum);
return R.success(service.updateById(domainDO));
}
/**
* 批量删除
* @param serviceName 服务名称
* @param ids 待删除ID集合
* @return 返回结果
*/
@DeleteMapping("/{serviceName}/batchDel")
public R<Boolean> batchDel(@PathVariable("serviceName") String serviceName,
@RequestBody List<Integer> ids) {
MissionErrorEnums.ARGUMENT_MUST_NOT_NULL.assertNotEmpty(ids);
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
return R.success(service.removeByIds(ids));
}
/**
* 根据ID删除
* @param serviceName 服务名称
* @param id 待删除ID
* @return 返回结果
*/
@DeleteMapping("/{serviceName}/del/{id}")
public R<Boolean> delById(@PathVariable("serviceName") String serviceName,
@PathVariable("id") Serializable id) {
MissionErrorEnums.ARGUMENT_MUST_NOT_NULL.assertNotNull(id);
ServiceEnums serviceEnum = ServiceEnums.getServiceName(serviceName);
IService service = SpringUtil.getBean(serviceEnum.getServicename());
return R.success(service.removeById(id));
}
/**
* 校验并转成DO对象
* @param jsonParam
* @param serviceEnum
* @return
*/
private Object validateAndConvert2DO(String jsonParam, ServiceEnums serviceEnum) {
//读取JSON字符串
Object domainDTO = null;
try {
domainDTO = mapper.readValue(jsonParam,serviceEnum.getDomainDTO());
} catch (JsonProcessingException e) {
ArgumentExceptionEnum.VALID_ERROR.assertFail("无法解析json参数");
}
//校验参数是否正确
Set<ConstraintViolation<Object>> validates = validator.validate(domainDTO);
if(CollUtil.isNotEmpty(validates)){
ConstraintViolation<Object> next = validates.iterator().next();
ArgumentExceptionEnum.VALID_ERROR.assertFail(next.getMessage());
}
//将DTO参数转成DO对象
Object domainDo = BeanUtils.map(domainDTO,serviceEnum.getDomainDO());
return domainDo;
}
}
2、业务枚举
- 该类作为统筹类
- 如果觉得比较麻烦可以采用反射的方式,不过反射方式稍微显得麻烦
@Getter
@AllArgsConstructor
public enum ServiceEnums{
//投票对象
TASKINFO("taskInfo","taskInfoServiceImpl",
TaskInfoDTO.class, TaskInfoDO.class, TaskInfoVO.class),
TASK_ITEM("taskItem","taskItemServiceImpl",
TaskItemDTO.class, TaskItemDO.class, TaskItemVO.class),
USER_ACCOUNT("userAccount","userAccountServiceImpl",
UserAccountDTO.class, UserAccountDO.class, UserAccountVO.class),
USER_INFO("userInfo","userInfoServiceImpl",
UserInfoDTO.class, UserInfoDO.class, UserInfoVO.class),
USER_TASK("userTask","userTaskServiceImpl",
UserTaskDTO.class, UserTaskDO.class, UserTaskVO.class),
WITHDRAWAL_APPLY("withdrawalApply","withdrawalApplyServiceImpl",
WithdrawalApplyDTO.class, WithdrawalApplyDO.class, WithdrawalApplyVO.class),
WITHDRAWAL_RECORD("withdrawalRecord","withdrawalRecordServiceImpl",
WithdrawalRecordDTO.class, WithdrawalRecordDO.class, WithdrawalRecordVO.class),
;
/**
* 服务模块名
*/
private String service;
/**
* 服务名称
*/
private String servicename;
/**
* 领域对象名称
*/
private Class<?> domainDTO;
/**
* 数据操作对象
*/
private Class<?> domainDO;
/**
* 值对象
*/
private Class<?> domainVO;
public static ServiceEnums getServiceName(String service){
ServiceEnums[] values = ServiceEnums.values();
for (ServiceEnums serviceEnum:values){
if(serviceEnum.getService().equals(service)){
return serviceEnum;
}
}
MissionErrorEnums.SERVICE_NAME_NOT_DEFINE.assertFail(service);
return null;
}
}
二、Mybatis-plus抽象简化连表查询
思路:
- 连表查询的关键在于查询条件的构建,因此第一步是在查询条件上下功夫
1、创建WrapperHelper工具类
public class WrapperHelper {
public static <T> T queryOne( DoubleArg doubleArg){
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(doubleArg.getFunction(),doubleArg.getValue());
queryWrapper.eq(doubleArg.getFunction2(),doubleArg.getValue2());
queryWrapper.last("limit 1");
IService service = SpringUtil.getBean(doubleArg.getIService().getClass());
T one = (T)service.getOne(queryWrapper);
return one;
}
public static <T> T queryOne(SingleArg singleArg){
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(singleArg.getFunction(),singleArg.getValue());
queryWrapper.last("limit 1");
IService service = SpringUtil.getBean(singleArg.getIService().getClass());
T one = (T)service.getOne(queryWrapper);
return one;
}
public static <T> T queryOne(IService clazz, SFunction sFunction,Object value){
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(sFunction,value);
queryWrapper.last("limit 1");
IService service = SpringUtil.getBean(clazz.getClass());
return (T)service.getOne(queryWrapper);
}
public static <T> List<T> queryList(IService clazz, SFunction sFunction, Object value){
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(sFunction,value);
IService service = SpringUtil.getBean(clazz.getClass());
return (List<T>)service.list(queryWrapper);
}
public static <T> List<T> queryList(DoubleArg doubleArg){
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(doubleArg.getFunction(),doubleArg.getValue());
queryWrapper.eq(doubleArg.getFunction2(),doubleArg.getValue2());
IService service = SpringUtil.getBean(doubleArg.getIService().getClass());
return service.list(queryWrapper);
}
public static <T> List<T> queryInList(IService clazz, SFunction sFunction, Object value) {
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(sFunction,value);
IService service = SpringUtil.getBean(clazz.getClass());
return service.list(queryWrapper);
}
public static <T>Page<T> queryPage(PageArg pageArg){
Page page = new Page(pageArg.getPageNo(),pageArg.getPageSize());
IService service = SpringUtil.getBean(pageArg.getIService().getClass());
LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(pageArg.getFunction(),pageArg.getValue());
if(null != pageArg.getOrderColumn()){
queryWrapper.orderByDesc(pageArg.getOrderColumn());
}
queryWrapper.orderByDesc();
service.page(page);
return page;
}
}
2、查询条件封装
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SingleArg<T>{
/**对应Service*/
private IService<T> iService;
/**调用字段*/
private SFunction<T,?> function;
/**参数值*/
private Object value;
}
//==============================
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DoubleArg<T> extends SingleArg{
private SFunction<T,?> function2;
private Object value2;
public DoubleArg(IService service, SFunction<T,?> function, Object value, SFunction<T,?> function2, Object value2){
super(service,function,value);
this.function2 =function2;
this.value2 = value2;
}
}
3、关键表外键整理
public class TableFiledFunctions {
//UserAccount外键user_id
public static final SFunction<UserAccountDO,?> userAccount_UserId = UserAccountDO::getUserId;
//TaskInfo外键itemId
public static final SFunction<TaskInfoDO,?> taskInfo_itemId = TaskInfoDO::getItemId;
}
4、一对一连表查询
//封装1对1的参数
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDetailVO {
private UserInfoDO userInfoDO;
private UserAccountDO userAccountDO;
}
//实现查询
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfoDO> implements UserInfoService {
@Resource
private UserAccountService userAccountService;
@Override
public UserDetailVO getUserDetail(Long userId){
//第一种方式:直接传递参数
UserAccountDO userAccountDO = WrapperHelper.queryOne(userAccountService,
TableFiledFunctions.userAccount_UserId,userId);
//第二种方式
SFunction<UserAccountDO,?> userAccount_UserId = UserAccountDO::getUserId;
SingleArg singleArg = new SingleArg(userAccountService,userAccount_UserId,userId);
UserAccountDO userAccountDO2 = WrapperHelper.queryOne(singleArg);
//最后封装成返回
return new UserDetailVO(getById(userId),userAccountDO);
}
}
5、一对多连表查询
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TaskItemDetailVO {
private TaskItemDO taskItemDO;
private List<TaskInfoDO> taskInfoDOList;
}
@Slf4j
@Service
public class TaskItemServiceImpl extends ServiceImpl<TaskItemMapper, TaskItemDO> implements TaskItemService {
@Lazy
@Resource
private TaskInfoService taskInfoService;
@Override
public TaskItemDetailVO getTaskItemDetailVO(Integer taskItemId) {
List<TaskInfoDO> taskInfoList = WrapperHelper.queryList(taskInfoService, TableFiledFunctions.taskInfo_itemId,taskItemId);
return new TaskItemDetailVO(getById(taskItemId), taskInfoList);
}
}
6、多对多连表查询
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserTaskListVO {
/**
* 用户信息
*/
private UserInfoDO userInfo;
/**
* 用户的任务信息
*/
private List<UserTaskDetailVO> userTaskList;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserTaskDetailVO {
/**
* 用户任务信息
*/
private UserTaskDO userTaskDO;
/**
* 任务明细信息
*/
private TaskInfoDO taskInfoDO;
}
@Slf4j
@Service
public class UserTaskServiceImpl extends ServiceImpl<UserTaskMapper, UserTaskDO> implements UserTaskService {
@Resource
private UserInfoService userInfoService;
@Resource
private TaskInfoService taskInfoService;
@Override
public UserTaskListVO getUserTaskList(UserTaskQueryDTO userTaskQueryDTO) {
//查询用户信息
UserInfoDO userInfo = userInfoService.getById(userTaskQueryDTO.getUserId());
//分页查询用户任务信息
Page page = new Page(userTaskQueryDTO.getPageNo(),userTaskQueryDTO.getPageSize());
this.page(page);
List<UserTaskDO> records = page.getRecords();
//查询任务集合
List<Integer> userTaskIds = records.stream().map(UserTaskDO::getTaskId).collect(Collectors.toList());
List<TaskInfoDO> taskInfoDOS = taskInfoService.listByIds(userTaskIds);
Map<Integer, TaskInfoDO> taskInfoMap = taskInfoDOS.stream().
collect(Collectors.toMap(TaskInfoDO::getId, e -> e));
List<UserTaskDetailVO> detailList = Lists.newArrayListWithCapacity(records.size());
records.forEach(e->{
detailList.add(new UserTaskDetailVO(e,taskInfoMap.get(e.getTaskId())));
});
//查询任务详情
page.setRecords(detailList);
return new UserTaskListVO(userInfo,page);
}
}