mybatis-plus在实际开发中的应用 悠悠 2024-03-16 18:26 19阅读 0赞 #### 文章目录 #### * 前言 * 一、实体类的注解 * 二、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是我们的实体类),也支持我们对其进行自定义修改加入我们需要的查询条件,默认的查询条件如下: ![在这里插入图片描述][687702d151804ac4b78a63d12ee50c40.png] ![在这里插入图片描述][e1aecc4fec3b4b959ea3372457b760d1.png] mybatis-plus帮我们自动实现了分页的查询条件,当然在实际的开发中只有一个分页条件是远远不够的,下边是我的自定义查询条件: ![在这里插入图片描述][2a40a12fdb294fbb813d7072ee4ede79.png] ## 三、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的一些总结 [687702d151804ac4b78a63d12ee50c40.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/6373720ad52c433aa3794323f53b5e7d.png [e1aecc4fec3b4b959ea3372457b760d1.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/c77a4e98ddef45418b01b7f58b024610.png [2a40a12fdb294fbb813d7072ee4ede79.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/15/99edce27d0424647abf5b7222f7662c5.png
相关 Java反射API在实际开发中的应用实例 Java反射API是Java提供的一种能力,可以让你在运行时获取类的信息(如方法、属性等),并操作这些信息。 以下是一个在实际开发中使用Java反射API的实例: 假设我们 谁借莪1个温暖的怀抱¢/ 2024年09月18日 01:36/ 0 赞/ 5 阅读
相关 Java泛型在实际开发中的应用案例 Java泛型是一种强大的工具,它允许我们编写可以处理多种数据类型的代码。以下是一些实际开发中使用Java泛型的常见案例: 1. 集合类:如ArrayList<T>、Linke 野性酷女/ 2024年09月11日 01:42/ 0 赞/ 27 阅读
相关 Java的反射机制在实际开发中有哪些应用? Java的反射机制是一种强大的工具,它允许我们在运行时动态地获取和修改对象的信息。以下是反射机制在实际开发中的常见应用: 1. 动态加载类:通过反射,可以在运行时决定加载哪个 今天药忘吃喽~/ 2024年09月04日 09:42/ 0 赞/ 17 阅读
相关 mybatis-plus在实际开发中的应用 我们在项目中使用Mybatis-Plus,这是一个基于Mybatis的优秀ORM框架,它提供了许多方便的工具和封装,可以大量地减轻我们的开发负担。下面我会分享一些我的经验和教训 分手后的思念是犯贱/ 2024年03月16日 19:45/ 0 赞/ 5 阅读
相关 mybatis-plus在实际开发中的应用 文章目录 前言 一、实体类的注解 二、Req查询条件 三、Controller接口 四、Service接口 五、Service接口实现 悠悠/ 2024年03月16日 18:26/ 0 赞/ 20 阅读
相关 前端工程化-Git SubModule在实际开发中的应用 背景 在前端日常开发中,我们经常Git来做代码版本管理工具,使用方式基本是one To one。即一个项目对应一个Git仓库的形式,那么当我们的代码中碰到了业务级别的需要 快来打我*/ 2022年12月13日 01:40/ 0 赞/ 109 阅读
相关 Optional在SpringBoot中的实际应用 第一步:实体类 @Data @ToString public class User { private Integer id; 左手的ㄟ右手/ 2022年09月05日 04:18/ 0 赞/ 257 阅读
相关 设计模式在实际开发中的应用 我相信有些人学了设计模式,依然不知道设计模式的应用场景,感觉我们日常开发中,仅仅写些逻辑,调下接口,连接下数据库就完事儿了。感觉设计模式都被框架运用的淋淋尽致,似乎没有我们可发 拼搏现实的明天。/ 2022年04月18日 00:46/ 0 赞/ 272 阅读
相关 实际开发中闭包的应用 闭包的实际应用,主要是用来封装变量。即把变量隐藏起来,不让外面拿到和修改。 function isFirstLoad() { var _list = 傷城~/ 2021年11月09日 07:22/ 0 赞/ 255 阅读
还没有评论,来说两句吧...