mybatis-plus在实际开发中的应用

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录


前言

最近的项目是使用mybatis-plus作为持久层框架前面也记录过mybatis-plus的基本使用此次记录一下本次项目中的一些使用要点


一、实体类的注解

基本的导入依赖和代码自动生成器可以去看以前的文章本次不再赘述。
以项目中的一个实体类为例

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;

import java.util.Date;

import com.baomidou.mybatisplus.annotation.TableId;

import java.io.Serializable;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("co_activity")
@ApiModel(value = "Activity对象", description = "绿色活动")
public class Activity implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;

    @ApiModelProperty(value = "关联EMP活动ID")
    private String empId;

    @ApiModelProperty(value = "活动小图")
    private String image;

    @ApiModelProperty(value = "活动名称")
    private String name;

    @ApiModelProperty(value = "活动副标题")
    private String subTitle;

    @ApiModelProperty(value = "活动日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date activityDate;

    @ApiModelProperty(value = "活动城市")
    private String city;

    @ApiModelProperty(value = "排序")
    private Integer sort;

    @ApiModelProperty(value = "签到奖励能量")
    private Integer sigInEnergy;

    @ApiModelProperty(value = "预约奖励能量")
    private Integer reservationEnergy;

    @ApiModelProperty(value = "关联绿色场景")
    private String sceneRuleId;

    @ApiModelProperty(value = "推荐1:是0否")
    private Integer recommend;

    @ApiModelProperty(value = "删除标记")
    private Integer delFlag;


}

实体类上mybatis-plus的注解有两个

  • @TableName(“co_activity”)指定表名
  • @TableId(value = “id”, type = IdType.ASSIGN_ID) 指定主键

实体类还应该实现序列化接口方便后续对数据进行流操作
其余的注解是lombok注解和swagger文档注解

二、Req查询条件

req查询条件是mybatis-plus封装自己为我们封装的查询条件需要我们继承一个BaseRequest< T >类其中T是我们的实体类也支持我们对其进行自定义修改加入我们需要的查询条件默认的查询条件如下
在这里插入图片描述
在这里插入图片描述
mybatis-plus帮我们自动实现了分页的查询条件当然在实际的开发中只有一个分页条件是远远不够的下边是我的自定义查询条件
在这里插入图片描述

三、Controller接口

这里我以一个条件查询的方法演示

@Api(tags = "绿色活动")
@RestController
@RequestMapping("/activity")
@Slf4j
public class ActivityController {

    @Resource
    private IActivityService iActivityService;
    
    @ApiOperation("分页查询")
    @PostMapping("/admin/page")
    public Result page(@RequestBody ActivityReq req) {
        log.info("分页查询活动列表:{}", JSON.toJSONString(req));
        Map<String, Object> page = iActivityService.pageQuery(req);
        log.info("分页查询活动列表到的数据:{}", JSON.toJSONString(page));
        return Result.ok(page);
    }
}    

也就是说我们后端接口接收的查询条件就是req它以json的数据格式进行传输
传入的数据格式如下

{
    "id":"",
    "empId":"",
    "activityName":"",
    "city":"",
    "sceneRuleId":""
}

四、Service接口

service接口需要我们去实现一个mybatis-plus的接口IService< T >

public interface IActivityService extends IService<Activity> {

    /**
     * 分页查询
     *
     * @param req 查询条件
     * @return map
     */

    Map<String, Object> pageQuery(ActivityReq req);
}

其中实现了一些基础的CRUD方法如果只是简单不带业务逻辑的基本功能mybatis-plus都给我们进行了封装拿来即用此处不再展示

五、Service接口实现类

这里除了我们需要去实现一个我们自定义的接口外还需要我们去继承一个mybatis-plus的类ServiceImpl<Mapper, Model> 代码如下

@Service
@Slf4j
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> 
implements IActivityService {
	@Autowired
    private ActivityMapper activityMapper;
	
	 @Override
    public Map<String, Object> pageQuery(ActivityReq req) {
        log.info("分页查询活动列表到的数据:{}", JSON.toJSONString(req));
        List<SceneRule> sceneRules = sceneRuleMapper.selectList(new QueryWrapper<>());
        Map<String, String> sceneRuleMap = new HashMap<>(sceneRules.size());
        for (SceneRule sceneRule : sceneRules) {
            sceneRuleMap.put(sceneRule.getId(), sceneRule.getName());
        }
        QueryWrapper<Activity> queryWrapper = new QueryWrapper<>();
        /*活动id模糊查询*/
        queryWrapper.like(StringUtils.isNotBlank(req.getId()), "id", req.getId());
        /*emp活动id模糊查询*/
        queryWrapper.like(StringUtils.isNotBlank(req.getEmpId()), "emp_id", req.getEmpId());
        /*活动名称模糊查询*/
        queryWrapper.like(StringUtils.isNotBlank(req.getActivityName()), "name", req.getActivityName());
        /*城市*/
        CityEnum eumByCode = CityEnum.getEumByCode(req.getCityCode());
        if (eumByCode != null) {
            String city = eumByCode.getDesc();
            queryWrapper.eq("city", city);
        }
        /*未删除的*/
        queryWrapper.eq("del_flag", DelFlagEnum.NO_DEL.getCode());
        /*不查全国的*/
        queryWrapper.ne("city", CityEnum.QUANGUO.getDesc());
        /*场景*/
        queryWrapper.eq(StringUtils.isNotBlank(req.getSceneRuleId()), "scene_rule_id", req.getSceneRuleId());
        /*日期降序*/
        queryWrapper.orderByDesc("activity_date");
        IPage<Activity> page = baseMapper.selectPage(req.getPage(), queryWrapper);
        List<Activity> activityList = page.getRecords();
        List<String> empIds = new ArrayList<>(activityList.size());
        for (Activity activity : activityList) {
            if (StringUtils.isNotBlank(activity.getEmpId()) && !empIds.contains(activity.getEmpId())) {
                empIds.add(activity.getEmpId());
            }
        }
        List<EmpVo> empVoList = empVoList(empIds);
        Map<String, EmpVo> empVoMap = new HashMap<>(empVoList.size());
        for (EmpVo empVo : empVoList) {
            empVoMap.put(empVo.getEventId(), empVo);
        }
        /*将结果封装为VO返回前端*/
        List<ActivityVo> list = page.getRecords().stream().map(activity -> {
            ActivityVo vo = new ActivityVo();
            BeanUtils.copyProperties(activity, vo);
            if (sceneRuleMap.get(activity.getSceneRuleId()) == null) {
                vo.setSceneRuleName("无");
            } else {
                vo.setSceneRuleName(sceneRuleMap.get(activity.getSceneRuleId()));
            }
            EmpVo empVo = empVoMap.get(activity.getEmpId());
            if (empVo != null) {
                String image = null;
                vo.setName(empVo.getTitle());
                vo.setSubTitle(empVo.getType());
                vo.setActivityDate(empVo.getHoldingEndTime());
                vo.setCityName(empVo.getCity());
                if ("0".equals(empVo.getEventScene())) {
                    image = empVo.getAppCoverImage();
                } else if ("1".equals(empVo.getEventScene())) {
                    List<String> eventImageList = empVo.getEventImageList();
                    if (CollectionUtils.isNotEmpty(eventImageList)) {
                        image = eventImageList.get(0);
                    }
                }
                vo.setImage(image);
            }
            log.info("vo封装结束");
            return vo;
        }).collect(Collectors.toList());

        Map<String, Object> map = new HashMap<>(3);
        map.put("total", page.getTotal());
        map.put("list", list);
        map.put("page", page.getCurrent());
        return map;
    }
}

此处需要注意的是我们需要使用一个StringUtils.isNotBlank(查询条件) 方法去判断我们的查询条件是否为空不为空再进行拼接其次这里还使用了一个stream流去处理查询出来的结果因为mybatis-plus只支持单表查询但是对于复杂的显示来说我们不得不去另外一张表中取数据所以这里对查询结果使用stream流进行数据处理将我们需要的数据进行处理然后返回

六、Mapper接口

有些时候我们自带的查询方法极有可能不满足我们的业务需求所以我们需要使用mybatis的xml映射文件去编写sql和mybatis基本一致需要注意的是我们的mapper也要继承一个类BaseMapper< T > 其中封装了一些基本的持久层的CRUD方法供我们使用

@Repository
public interface ActivityMapper extends BaseMapper<Activity> {
    /**
     * 获取已经关联的empId
     * @return
     */
    List<String> getEmpIds();
}

七、枚举的使用

开发规范中不允许魔法值的出现所以在真实的开发中需要我们使用枚举去完成一些类目的判断下面以城市为例

@Getter
@AllArgsConstructor
public enum CityEnum {

    BEIJING("110000", "北京市"),
    SHANGHAI("310000", "上海市"),
    GUANGZHOU("440100", "广州市"),
    SHENZHEN("440300", "深圳市"),
    HANGZHOU("330100", "杭州市"),
    FOSHAN("440600", "佛山市"),
    QUANGUO("000000", "全国");

    private String code;
    private String desc;

    public static CityEnum getEumByCode(String code) {
        if (code == null) {
            return null;
        }

        for (CityEnum type : CityEnum.values()) {
            if (type.getCode().equals(code)) {
                return type;
            }
        }
        return null;
    }
}

以上就是一个城市的枚举类

在使用的时候如下

/*城市*/
 CityEnum eumByCode = CityEnum.getEumByCode(req.getCityCode());
 if (eumByCode != null) {
     String city = eumByCode.getDesc();
     queryWrapper.eq("city", city);
 }

这样就避免的魔法值的出现
常用的枚举还有逻辑删除

@Getter
@AllArgsConstructor
public enum DelFlagEnum {
    NO_DEL(0, "未删除"),
    DEL(1, "已删除");
    private Integer code;
    private String desc;
}

我们也可以在VO类中添加枚举处理例如我们需要在活动VO中获取城市名假设model中是没有城市名的只存了一个code码

    public String setCityName() {
        String name = "";
        CityEnum eumByCode = CityEnum.getEumByCode(this.city);
        if (eumByCode != null) {
            name = eumByCode.getDesc();
        }
        return name;
    }

可以在VO中添加上边的代码


总结

以上就是最近在使用mybatis-plus的一些总结

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6