在引入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));
}
}