package com.coffee.common.crud; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.db.sql.Direction; import cn.hutool.db.sql.Order; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import com.coffee.common.bo.LoginUser; import com.coffee.common.entity.QueryParamEntity; import com.coffee.common.entity.param.Term; import com.coffee.common.exception.CustomException; import org.apache.ibatis.binding.MapperMethod; import org.springframework.data.domain.PageRequest; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.sql.SQLSyntaxErrorException; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Set; /** * @Author lifang * @Date 10:02 2022/3/14 * @Description PK为主键类型 * @Param * @return **/ public abstract class BaseService, E,PK extends Serializable> extends ServiceImpl { /** * 当使用缓存时使用该属性表示缓存名称 **/ private final String cacheBucket; public String getCacheBucketName(){ return cacheBucket; } public BaseService() { this.cacheBucket = this.getClass().getSimpleName(); } public BaseService(String cacheBucket) { this.cacheBucket = cacheBucket; } @Override @Transactional(rollbackFor = Exception.class) public boolean saveBatch(Collection entityList, int batchSize) { entityList.forEach(this::validateBeforeSave); if (super.saveBatch(entityList, batchSize)) { entityList.forEach(this::postSave); return true; } return false; } @Override @Transactional(rollbackFor = Exception.class) public boolean save(E entity) { if (super.save(entity)) { postSave(entity); return true; } return false; } /** * @Author lifang * @Date 10:05 2022/3/14 * @Description 在使用时请尽量将update操作和save操作分开 * @Param [entity] * @return boolean **/ @Override @Deprecated @Transactional(rollbackFor = Exception.class) public boolean saveOrUpdate(E entity) { if (null != entity) { TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass); Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); String keyProperty = tableInfo.getKeyProperty(); Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty()); if (StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal))) { if(save(entity)){ postSave(entity); return true; } return false; }else { if(updateById(entity)){ postUpdate(entity); return true; } return false; } } return false; } /** * @Author lifang * @Date 10:05 2022/3/14 * @Description 在使用时请尽量将update操作和save操作分开 * @Param [entity] * @return boolean **/ @Override @Transactional(rollbackFor = Exception.class) @Deprecated public boolean saveOrUpdateBatch(Collection entityList, int batchSize) { TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); String keyProperty = tableInfo.getKeyProperty(); Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> { Object idVal = tableInfo.getPropertyValue(entity, keyProperty); validateBeforeSave(entity); return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)); }, (sqlSession, entity) -> { MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); validateBeforeUpdate(entity); param.put(Constants.ENTITY, entity); if (sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param)==0) { postUpdate(entity); } }); } @Override public boolean removeById(Serializable id) { validateBeforeDelete((PK) id); if (super.removeById(id)) { postDelete((PK) id); return true; } return false; } @Override public boolean removeByIds(Collection list) { list.stream().map(id->(PK)id).forEach(this::validateBeforeDelete); if (super.removeByIds(list)) { list.stream().map(id->(PK)id).forEach(this::postDelete); return true; } return false; } @Override public boolean removeById(Serializable id, boolean useFill) { this.validateBeforeDelete((PK) id); if (super.removeById(id, useFill)) { postDelete((PK) id); return true; } return false; } @Override public boolean removeBatchByIds(Collection list, int batchSize) { list.stream().map(id->(PK)id).forEach(this::validateBeforeDelete); if (super.removeBatchByIds(list, batchSize)) { list.stream().map(id->(PK)id).forEach(this::postDelete); return true; } return false; } @Override public boolean removeBatchByIds(Collection list, int batchSize, boolean useFill) { list.stream().map(id->(PK)id).forEach(this::validateBeforeDelete); if (super.removeBatchByIds(list, batchSize, useFill)) { list.stream().map(id->(PK)id).forEach(this::postDelete); return true; } return false; } @Override @Transactional(rollbackFor = Exception.class) public boolean updateById(E entity) { validateBeforeUpdate(entity); if (super.updateById(entity)) { postUpdate(entity); return true; } return false; } @Override @Transactional(rollbackFor = Exception.class) public boolean updateBatchById(Collection entityList) { entityList.forEach(this::validateBeforeUpdate); if (super.updateBatchById(entityList)) { entityList.forEach(this::postUpdate); return true; } return false; } public IPage list(QueryParamEntity param) { //是否为分页查询 if(ObjectUtil.isNotNull(param.getPage())){ QueryWrapper wrapper = build(param); Page page = param.getPage(); // page.setCurrent(page.getCurrent()>0?page.getCurrent()-1:0); return this.page(page,wrapper); }else { try { List list = list(build(param)); Page page = Page.of(0,1,CollectionUtil.isEmpty(list)?0:list.size()); page.setRecords(list); return page; }catch (Exception e){ if(e instanceof BadSqlGrammarException){ throw new CustomException(e.getCause().getMessage()); } } return new Page<>(); } } public long count(QueryParamEntity param) { return this.count(build(param)); } public QueryWrapper build(QueryParamEntity param){ QueryWrapper queryWrapper = new QueryWrapper<>(); Set includes = param.getIncludes(); Set wheres = param.getWheres(); Set orders = param.getOrders(); if(CollectionUtil.isNotEmpty(includes)){ queryWrapper.select(includes.toArray(new String[includes.size()+1])); } if (CollectionUtil.isNotEmpty(wheres)) { wheres.forEach(term -> term.getType().build(queryWrapper,term)); } if(CollectionUtil.isNotEmpty(orders)){ orders.forEach(order -> { String field = order.getField(); String column = StrUtil.toUnderlineCase(field).toLowerCase(); Direction direction = order.getDirection(); if(Direction.ASC==direction){ queryWrapper.orderByAsc(column); }else { queryWrapper.orderByDesc(column); } }); } // else { // queryWrapper.orderByDesc("create_time"); // } if(StrUtil.isNotEmpty(param.getTenantId())&&!StrUtil.isNullOrUndefined(param.getTenantId())){ LoginUser loginUser = (LoginUser) StpUtil.getTokenSession().get(com.coffee.common.Constants.LOGIN_USER_KEY); //是否为系统用户 if(loginUser!=null&&Boolean.TRUE.equals(loginUser.getIsSys())){ queryWrapper.eq("tenant_id",param.getTenantId()); } } return queryWrapper; } /** * 保存成功后操作 */ public void postSave(E entity ){ } /** * 更新成功后操作 */ public void postUpdate(E entity){ } /** * 删除成功后操作 */ public void postDelete(PK id){ } /** * @Author lifang * @Date 10:00 2022/3/14 * @Description 保存数据前进行验证 * @Param [entity] * @return void **/ public abstract void validateBeforeSave(E entity) ; /** * @Author lifang * @Date 10:00 2022/3/14 * @Description 更新数据前进行验证 * @Param [entity] * @return void **/ public abstract void validateBeforeUpdate(E entity) ; /** * @Author lifang * @Date 10:02 2022/3/14 * @Description 删除数据前进行验证 * @Param [id] * @return void **/ public abstract void validateBeforeDelete(PK id) ; }