基于MyBatisPlus对Mapper、Service、Controller封装

本文介绍了在使用Mybatis-Plus后,如何重构业务逻辑以支持并发,包括引入bizService层处理复杂业务,Mapper接口保持通用,Service层简化查询并可能进行接口数据缓存,以及Controller的扩展基础接口。
摘要由CSDN通过智能技术生成

在引入mybatis-plus之后发现了虽然在基础的增删改查上会容易很多。但是,设计并发逻辑得时候,就需要重写save方法,原来的新增就无法使用,所以做了如下修改
1、添加bizService层,作为业务服务层,将主要复杂得业务分配到该模块得实现类中;
2、Mapper层只提供了接口,尽量在Mapper的接口做到通用适配;
3、把Service层作为简单得业务查询,封装常用的查询,甚至可以在这里做到接口数据缓存;
4、Controller在继承之后直接带增删改基础接口。

在这里插入图片描述
代码部分:
BaseMapper.java

/**
 * 封装的 Mapper 方法
 *
 * @author SERVER-ZJ 2022/7/7 11:13
 */
public interface BaseMapper<T extends BaseEntity, Po extends T, Do extends T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {

    /**
     * 根据条件 获取数据分页信息
     *
     * @param pageDo   分页信息参数
     * @param pagingDo 分页条件参数
     * @return 数据分页信息
     */
    Page<Po> pagingPoByDo(Page<Do> pageDo, @Param("conditionDo") Do pagingDo);

    /**
     * 根据条件 获取数据列表
     *
     * @param listDo 请求条件参数
     * @return 数据列表
     */
    List<Po> listPoByDo(@Param("conditionDo") Do listDo);

    /**
     * 根据id 获取 多表查询的 po 对象
     *
     * @param id 数据id
     * @return 多表查询的 po 对象
     */
    Po getPoById(@Param("id") Long id);
}

Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.internetCafes.spms.web.study.mapper.file.StudyFileCatalogAssoMapper">
    <sql id="selectPo"></sql>

    <sql id="conditionDo">
        <where><if test="conditionDo != null"></if></where>
    </sql>

    <select id="pagingPoByDo" resultType="com.internetCafes.spms.web.study.model.file.podo.StudyFileCatalogAssoPo">
        <include refid="selectPo"/>
        <include refid="conditionDo"/>
    </select>

    <select id="listPoByDo" resultType="com.internetCafes.spms.web.study.model.file.podo.StudyFileCatalogAssoPo">
        <include refid="selectPo"/>
        <include refid="conditionDo"/>
        ORDER BY xsfca.id DESC
    </select>

    <select id="getPoById" resultType="com.internetCafes.spms.web.study.model.file.podo.StudyFileCatalogAssoPo">
        <include refid="selectPo"/>
        WHERE xsfca.del_flag = 0 AND xsfca.id = #{id}
        ORDER BY xsfca.id DESC LIMIT 0,1
    </select>
</mapper>

BaseService.java

/**
 * 封装的service基础接口
 *
 * @author SERVER-ZJ 2022/7/7 11:51
 */
public interface BaseService<T extends BaseEntity, Po extends T, Do extends T> extends IService<T> {

    /**
     * 根据实体类进行删除
     *
     * @param entity 实体类信息
     * @return 根据摸个信息删除信息
     */
    boolean removeByEntity(@NotNull Do entity);

    /**
     * 批量保存信息
     *
     * @param reqList 请求列表
     * @param entity  实体类信息
     * @param <Req>   请求类型
     * @return true/false
     */
    <Req extends T> boolean saveBatch(List<Req> reqList, Do entity);

    /**
     * 获取当前业务中 模块编码
     *
     * @return 模块编码
     */
    String getModuleCode();

    /**
     * 批量新增修改,适用于扩展信息字段,根据id是否为空判断是新增或者删除
     *
     * @param doList       请求列表
     * @param queryWrapper 字段以及字段值键值对
     * @return true/false
     */
    <Req extends T> boolean saveOrUpdateBatchWithQueryWrapper(List<Req> doList, QueryWrapper<T> queryWrapper);

    /**
     * 批量新增修改,适用于扩展信息字段,根据id是否为空判断是新增或者删除
     *
     * @param doList 请求列表
     * @param entity 字段以及字段值键值对
     * @return true/false
     */
    <Req extends T> boolean saveOrUpdateBatch(List<Req> doList, Do entity);

    /**
     * 根据条件 获取数据分页信息
     *
     * @param pageDo   分页信息参数
     * @param pagingDo 分页条件参数
     * @return 数据分页信息
     */
    Page<Po> pagingPoByDo(Page<Do> pageDo, Do pagingDo);

    /**
     * 根据条件 获取数据列表
     *
     * @param listDo 请求条件参数
     * @return 数据列表
     */
    List<Po> listPoByDo(Do listDo);

    /**
     * 根据id 获取 多表查询的 po 对象
     *
     * @param id id
     * @return 多表查询的 po 对象
     */
    Po getPoById(Long id);

    /**
     * 根据 id 获取单表对象 如果为空抛出异常
     *
     * @param id id
     * @return 对象信息
     */
    Po getPoByIdNotNull(Long id);

    /**
     * 根据 id 获取单表对象 如果为空抛出异常
     *
     * @param id id
     * @return 对象信息
     */
    T getByIdNotNull(Long id);

    /**
     * 审批通过后后置工作 默认没有业务
     *
     * @param id 数据id
     */
    default void afterAuditPass(Long id) {
    }
}

BaseService.java

/**
 * 封装的service基础接口
 *
 * @author SERVER-ZJ 2022/7/7 11:51
 */
public interface BaseService<T extends BaseEntity, Po extends T, Do extends T> extends IService<T> {

    /**
     * 根据实体类进行删除
     *
     * @param entity 实体类信息
     * @return 根据摸个信息删除信息
     */
    boolean removeByEntity(@NotNull Do entity);

    /**
     * 批量保存信息
     *
     * @param reqList 请求列表
     * @param entity  实体类信息
     * @param <Req>   请求类型
     * @return true/false
     */
    <Req extends T> boolean saveBatch(List<Req> reqList, Do entity);

    /**
     * 获取当前业务中 模块编码
     *
     * @return 模块编码
     */
    String getModuleCode();

    /**
     * 批量新增修改,适用于扩展信息字段,根据id是否为空判断是新增或者删除
     *
     * @param doList       请求列表
     * @param queryWrapper 字段以及字段值键值对
     * @return true/false
     */
    <Req extends T> boolean saveOrUpdateBatchWithQueryWrapper(List<Req> doList, QueryWrapper<T> queryWrapper);

    /**
     * 批量新增修改,适用于扩展信息字段,根据id是否为空判断是新增或者删除
     *
     * @param doList 请求列表
     * @param entity 字段以及字段值键值对
     * @return true/false
     */
    <Req extends T> boolean saveOrUpdateBatch(List<Req> doList, Do entity);

    /**
     * 根据条件 获取数据分页信息
     *
     * @param pageDo   分页信息参数
     * @param pagingDo 分页条件参数
     * @return 数据分页信息
     */
    Page<Po> pagingPoByDo(Page<Do> pageDo, Do pagingDo);

    /**
     * 根据条件 获取数据列表
     *
     * @param listDo 请求条件参数
     * @return 数据列表
     */
    List<Po> listPoByDo(Do listDo);

    /**
     * 根据id 获取 多表查询的 po 对象
     *
     * @param id id
     * @return 多表查询的 po 对象
     */
    Po getPoById(Long id);

    /**
     * 根据 id 获取单表对象 如果为空抛出异常
     *
     * @param id id
     * @return 对象信息
     */
    Po getPoByIdNotNull(Long id);

    /**
     * 根据 id 获取单表对象 如果为空抛出异常
     *
     * @param id id
     * @return 对象信息
     */
    T getByIdNotNull(Long id);

    /**
     * 审批通过后后置工作 默认没有业务
     *
     * @param id 数据id
     */
    default void afterAuditPass(Long id) {
    }
}

BizBaseService.java

/**
 * 业务bizService层抽离接口
 *
 * @author SERVER-ZJ 2022/6/21 14:48
 */
public interface BaseBizService<T extends BaseEntity, Res extends T, Req extends T> {

    /**
     * 根据id 获取详细信息
     *
     * @param id id
     * @return 详细信息
     */
    Res getById(Long id);

    /**
     * 列表
     *
     * @param req 请求参数
     * @return 数据列表
     */
    List<Res> list(Req req);

    /**
     * 分页
     *
     * @param req 请求参数
     * @return 分页信息
     */
    PageItemVO<Res> paging(PageItemDTO<Req> req);

    /**
     * 保存信息
     *
     * @param req 请求信息
     * @return 请求信息
     */
    Res save(Req req);

    /**
     * 修改信息
     *
     * @param req 请求信息
     * @return 请求信息
     */
    Res update(Req req);

    /**
     * 根据id逻辑删除
     *
     * @param idList id列表
     * @return true/false
     */
    boolean removeByIdList(List<Long> idList);

    /**
     * 根据id列表物理删除
     *  需要重写delete方法
     * @param idList id列表
     * @return true/false
     */
    boolean deleteByIdList(List<Long> idList);
}

BIzServiceImpl.java

/**
 * 业务service层抽离接口默认实现
 *
 * @author SERVER-ZJ 2022/7/7 14:11
 */
public class BaseBizServiceImpl<T extends BaseEntity, Res extends Po, Req extends Do, Po extends T, Do extends T, S extends BaseService<T, Po, Do>>
        implements BaseBizService<T, Res, Req> {

    /**
     * 排序order的前缀
     */
    protected List<OrderItem> orderPreList = new ArrayList<>();

    /** REQ 类信息 */
    protected Class<Req> reqClass = currentReqClass();

    /** RES 类信息 */
    protected Class<Res> resClass = currentResClass();

    protected Class<Res> currentResClass() {
        return (Class<Res>) ReflectionKit.getSuperClassGenericType(getClass(), 1);
    }

    protected Class<Req> currentReqClass() {
        return (Class<Req>) ReflectionKit.getSuperClassGenericType(getClass(), 2);
    }

    @Autowired
    private S baseService;

    public S getBaseService() {
        return baseService;
    }

    @Override
    public Res getById(Long id) {
        Po po = baseService.getPoById(id);
        Res res = BeanUtil.toBean(po, resClass);
        afterGetById(res);
        return res;
    }

    protected void afterGetById(Res res) {
    }

    @Override
    public List<Res> list(Req req) {
        beforeList(req);
        List<Po> poList = baseService.listPoByDo(req);
        List<Res> resList = BeanUtil.copyToList(poList, resClass);
        afterList(req, resList);
        return resList;
    }

    /**
     * 列表前置方法
     *
     * @param req 请求参数
     */
    protected void beforeList(Req req) {

    }

    /**
     * 列表后置方法
     *
     * @param req 请求参数
     */
    protected void afterList(Req req, List<Res> resLit) {
    }

    @Override
    public PageItemVO<Res> paging(PageItemDTO<Req> req) {
        beforePaging(req);
        Page<Do> pageDo = getPageDoByReq(req);
        Do pagingDo = getPagingDoByReq(req);
        Page<Po> pagingPo = baseService.pagingPoByDo(pageDo, pagingDo);
        PageItemVO<Res> pagingRes = PageItemUtils.toPageItemVO(pagingPo, resClass);

        afterPaging(req, pagingRes);
        return pagingRes;
    }

    /**
     * 分页前置方法
     *
     * @param req 请求参数
     */
    protected void beforePaging(PageItemDTO<Req> req) {
    }

    /**
     * 获取分页配置信息
     *
     * @param req 请求参数
     * @return 分页配置信息
     */
    protected Page<Do> getPageDoByReq(PageItemDTO<Req> req) {
        Page<Do> pageDo = new Page<>(req.getPageNum(), req.getPageSize());
        confPagingOrder(pageDo, req);
        return pageDo;
    }

    /**
     * 获取排序字段键值对
     */
    protected Map<String, String> getColumnMapByOrder() {
        return new HashMap<String, String>() {{
            this.put("id", "id");
        }};
    }

    /**
     * 获取默认排序列表
     *
     * @return 默认分页排序列表
     */
    protected List<OrderItem> getDefaultOrderList() {
        return new ArrayList<OrderItem>() {{
            add(OrderItem.desc("id"));
        }};
    }

    /**
     * 配置分页排序功能
     *
     * @param pageDo 分页请求
     * @param req    接口传的请求信息
     */
    protected void confPagingOrder(Page<Do> pageDo, PageItemDTO<Req> req) {
        if (StrUtil.isNotBlank(req.getOrderBy()) && getColumnMapByOrder().containsKey(req.getOrderBy())) {
            List<OrderItem> orderItemList = new ArrayList<>();

            String column = getColumnMapByOrder().get(req.getOrderBy());
            boolean asc = "asc".equals(req.getInOrder());

            OrderItem orderItem = new OrderItem();
            orderItem.setColumn(column);
            orderItem.setAsc(asc);
            orderItemList.add(orderItem);

            pageDo.setOrders(orderItemList);
        } else {
            pageDo.setOrders(getDefaultOrderList());
        }
    }

    /**
     * 获取分页请求条件参数
     *
     * @param req 请求参数
     * @return 分页请求条件参数
     */
    protected Do getPagingDoByReq(PageItemDTO<Req> req) {
        return req.getConditions();
    }

    /**
     * 分页后置方法
     *
     * @param req       分页请求
     * @param pagingRes 结果集
     */
    protected void afterPaging(PageItemDTO<Req> req, PageItemVO<Res> pagingRes) {
    }

    @Override
    @Transactional
    public Res save(Req req) {
        beforeSave(req);
        beforeSaveAndUpdate(req);
        baseService.save(req);
        afterSaveAndUpdate(req);
        afterSave(req);
        return BeanUtil.toBean(req, resClass);
    }

    /**
     * 新增和修改的前置准备业务逻辑
     *
     * @param req 请求参数
     */
    protected void afterSaveAndUpdate(Req req) {
    }

    /**
     * 新增后业务逻辑
     */
    protected void beforeSaveAndUpdate(Req req) {
    }

    /**
     * 新增前准备业务逻辑
     *
     * @param req 请求参数
     */
    protected void afterSave(Req req) {
    }

    /**
     * 新增后业务逻辑
     */
    protected void beforeSave(Req req) {
    }

    @Override
    @Transactional
    public Res update(Req req) {
        getBaseService().getByIdNotNull(req.getId());
        beforeUpdate(req);
        beforeSaveAndUpdate(req);
        baseService.updateById(req);
        afterSaveAndUpdate(req);
        afterUpdate(req);
        return BeanUtil.toBean(req, resClass);
    }

    /**
     * 修改前置方法
     *
     * @param req 请求参数
     */
    protected void beforeUpdate(Req req) {
    }

    /**
     * 修改后置方法
     *
     * @param req 请求参数
     */
    protected void afterUpdate(Req req) {
    }

    @Override
    @Transactional
    public boolean removeByIdList(List<Long> idList) {
        beforeRemove(idList);
        boolean result = baseService.removeByIds(idList);
        if (result) {
            afterRemove(idList);
        }
        return result;
    }

    /**
     * 删除前置方法
     *
     * @param idList id列表
     */
    protected void beforeRemove(List<Long> idList) {
    }

    /**
     * 删除前置方法
     *
     * @param idList id列表
     */
    protected void afterRemove(List<Long> idList) {
    }

    @Override
    @Deprecated
    @Transactional
    public boolean deleteByIdList(List<Long> idList) {
        return baseService.removeByIds(idList);
    }
}

BaseController.java

/**
 * controller 基类
 *
 * @author SERVER-ZJ 2022/7/7 14:34
 */
@Model("基本数据")
public class BaseController<T extends BaseEntity, Res extends T, Req extends T, S extends BaseBizService<T, Res, Req>> {

    @Autowired
    private S baseBizService;

    private Class<T> baseClass;

    /**
     * 初始化方法,再controller创建的时候,默认给出baseClass
     */
    public BaseController() {
        ParameterizedType pz = (ParameterizedType) this.getClass().getGenericSuperclass();//子类必须明确泛型的具体类型
        this.baseClass = (Class<T>) pz.getActualTypeArguments()[0];
    }

    /**
     * 获取基类中继承的bizService
     */
    public S getBaseBizService() {
        return baseBizService;
    }

    /**
     * 基类导出接口
     */
    @RequiresPermissions(value = {":export"}, logical = Logical.OR)
    @PostMapping("/export")
    public void export(@RequestBody @Validated(ParamValid.ListGroup.class) Req req, HttpServletResponse response) {
        List<Res> resList = getBaseBizService().list(req);
        exportExcel(resList, response);
    }

    /**
     * 提供基本导出功能给子类修改表格标题和子表名称
     */
    protected void exportExcel(List<Res> resList, HttpServletResponse response) {
        ExcelUtils.exportExcel(resList, "数据信息", "数据信息", baseClass, "data.xls", response);
    }

    /**
     * 基类分页接口
     */
//    @RequiresPermissions(value = {":paging"}, logical = Logical.OR)
    @PostMapping("/paging")
    public RR<PageItemVO<Res>> paging(@RequestBody @Validated(ParamValid.PagingGroup.class) PageItemDTO<Req> req) {
        return RR.success(getBaseBizService().paging(req));
    }

    /**
     * 基类列表接口
     */
    @RequiresPermissions(value = {ShiroAnnotationResolver.OPEN_VALUE}, logical = Logical.OR)
    @PostMapping("/list")
    public RR<List<Res>> list(@RequestBody @Validated(ParamValid.ListGroup.class) Req req) {
        return RR.success(getBaseBizService().list(req));
    }

    /**
     * 基类详情接口
     */
    @RequiresPermissions(value = {":view"}, logical = Logical.OR)
    @GetMapping("/{id}")
    public RR<Res> getById(@PathVariable("id") Long id) {
        return RR.success(getBaseBizService().getById(id));
    }

    /**
     * 基类删除接口
     */
    @SysLog("删除 - MODEL_NAME 信息")
//    @RequiresPermissions(value = {":del"}, logical = Logical.OR)
    @DeleteMapping("/{idList}")
    public RR<Void> deleteByIdList(@PathVariable("idList") List<Long> idList) {
        return getBaseBizService().removeByIdList(idList) ? RR.success() : RR.fail();
    }

    /**
     * 基类修改接口
     */
    @SysLog("修改 - MODEL_NAME 信息")
//    @RequiresPermissions(value = {":edit"}, logical = Logical.OR)
    @PutMapping("")
    public RR<Res> update(@RequestBody @Validated(ParamValid.UpdateGroup.class) Req req) {
        return RR.success(getBaseBizService().update(req));
    }

    /**
     * 新增
     */
    @SysLog("新增 - MODEL_NAME 信息")
    @RequiresPermissions(value = {":add"}, logical = Logical.OR)
    @PostMapping("/save")
    public RR<Res> save(@RequestBody @Validated(ParamValid.SaveGroup.class) Req req) {
        return RR.success(getBaseBizService().save(req));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值