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

文章目录

  • 前言
  • 一、实体类的注解
  • 二、Req查询条件
  • 三、Controller接口
  • 四、Service接口
  • 五、Service接口实现类
  • 六、Mapper接口
  • 七、枚举的使用
  • 总结


前言

最近的项目是使用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在实际开发中的应用_第1张图片
mybatis-plus帮我们自动实现了分页的查询条件,当然在实际的开发中只有一个分页条件是远远不够的,下边是我的自定义查询条件:
mybatis-plus在实际开发中的应用_第2张图片

三、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 代码如下:

@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的一些总结

你可能感兴趣的:(mybatis-plus,mybatis,java,开发语言)