文章目录
使用泛型、设计模式和mybatis-plus封装简单CURD的操作
使用泛型、模板模式、默认实现类、本地缓存等设计思想在mybatis-plus肩膀上实现简单crud的代码复用。
1、规约
- 表字段名规约:id/create_time/update_time/is_deleted
- 公共字段类实体:
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.util.Date;
@Data
public class BaseEntity {
@TableId(type = IdType.AUTO)
private Integer id;
private Date createTime;
private Date updateTime;
private String isDeleted;
}
2、实现
UML图如下:
1. 基础crud接口
public interface BaseService<T> {
int insert(T t) throws NoSuchMethodException;
int update(T t) throws NoSuchMethodException;
T selectById(Integer id) throws NoSuchMethodException;
/**
* 逻辑删除
*/
int deleteLogic(Integer id) throws NoSuchMethodException;
/**
* 物理删除
*/
int delete(Integer id) throws NoSuchMethodException;
2. 基础实现类,实现基础CRUD接口
public class BaseServiceImpl<T> implements BaseService<T> {
@Override
int insert(T t) throws NoSuchMethodException{
throw new NoSuchMethodException();
}
@Override
int update(T t) throws NoSuchMethodException{
throw new NoSuchMethodException();
}
@Override
public T selectById(Integer id) throws NoSuchMethodException {
throw new NoSuchMethodException();
}
@Override
public int deleteLogic(Integer id) throws NoSuchMethodException {
throw new NoSuchMethodException();
}
@Override
public int delete(Integer id) throws NoSuchMethodException {
throw new NoSuchMethodException();
}
protected void setInsertTimeParams(T t) {
if (t instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) t;
Date now = new Date();
baseEntity.setCreateTime(now);
baseEntity.setUpdateTime(now);
}
}
protected void setUpdateTimeParams(T t) {
if (t instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) t;
baseEntity.setUpdateTime(new Date());
}
}
}
3. 抽象类,继承基础实现类
public abstract class AbstractServiceImpl<T> extends BaseServiceImpl<T> {
private static Map<String, String> mapperNameCache = new HashMap<>();
@Resource
private Map<String, BaseMapper<T>> baseMapperMap;
// 设置新增记录的业务信息方法
protected abstract void setInsertParams(T t);
// 设置修改记录的业务信息方法
protected abstract void setUpdateParams(T t);
@Override
public int insert(T t) throws NoSuchMethodException {
BaseMapper<T> baseMapper = getBaseMapper();
if (Objects.isNull(t)) {
throw new BizException("新增或修改的信息不能为空!");
}
if (!(t instanceof BaseEntity)) {
throw new NoSuchMethodException();
}
BaseEntity baseEntity = (BaseEntity) t;
// 新增时,设置业务信息
setInsertParams(t);
setInsertTimeParams(t);
return baseMapper.insert(t);
}
@Override
public int update(T t) throws NoSuchMethodException {
BaseMapper<T> baseMapper = getBaseMapper();
if (Objects.isNull(t)) {
throw new BizException("新增或修改的信息不能为空!");
}
if (!(t instanceof BaseEntity)) {
throw new NoSuchMethodException();
}
BaseEntity baseEntity = (BaseEntity) t;
if (Objects.isNull(baseEntity.getId())) {
throw new BizException("记录id不能为空!");
}
T entityFromBb = selectById(baseEntity.getId());
if (Objects.isNull(entityFromBb)) {
throw new BizException("该记录已删除,修改失败!");
}
// 修改时,设置业务
setUpdateParams(t);
setUpdateTimeParams(t);
BeanUtil.copyPropertiesIgnoreNull(t, entityFromBb);
return baseMapper.updateById(entityFromBb);
}
@Override
public T selectById(Integer id) {
BaseMapper<T> baseMapper = getBaseMapper();
QueryWrapper<T> wrapper = new QueryWrapper<T>()
.eq("is_deleted", WhetherEnum.NO.getCode())
.eq("id", id);
return baseMapper.selectOne(wrapper);
}
@Override
public int deleteLogic(Integer id) throws NoSuchMethodException {
BaseMapper<T> baseMapper = getBaseMapper();
if (Objects.isNull(id)) {
throw new BizException("删除传入的id不能为空!");
}
T t = selectById(id);
if (!(t instanceof BaseEntity)) {
throw new NoSuchMethodException();
}
BaseEntity entity = (BaseEntity) t;
entity.setIsDeleted(WhetherEnum.YES.getCode());
setUpdateTimeParams(t);
return baseMapper.updateById(t);
}
@Override
public int delete(Integer id) {
BaseMapper<T> baseMapper = getBaseMapper();
return baseMapper.deleteById(id);
}
/**
* 获取mapper对象(使用缓存)
*
* @return
*/
private BaseMapper<T> getBaseMapper() {
// 使用泛型工具类获取T的具体类型
String className = GenericUtil.getGenericType(this.getClass());
String classNameGet = mapperNameCache.get(className);
if (Objects.nonNull(classNameGet)) {
return baseMapperMap.get(classNameGet);
}
int index = className.lastIndexOf(".") + 1;
String simpleName = className.substring(index);
StringBuilder mapperNameAppender = new StringBuilder();
if (simpleName.length() == 1) {
mapperNameAppender.append(simpleName.toLowerCase());
} else {
mapperNameAppender.append(simpleName.substring(0, 1).toLowerCase());
mapperNameAppender.append(simpleName.substring(1));
}
mapperNameAppender.append("Mapper");
String mapperName = mapperNameAppender.toString();
mapperNameCache.put(className, mapperName);
return baseMapperMap.get(mapperName);
}
}
4. 默认实现类,继承抽象类
public class DefaultServiceImpl<T> extends AbstractServiceImpl<T> {
@Override
protected void setInsertParams(T t) {
}
@Override
protected void setUpdateParams(T t) {
}
}
5. 业务实现类,继承默认实现类,选择性重写父类方法
@Service
public class BaseInfoServiceImpl extends DefaultServiceImpl<BaseInfo> implements BaseInfoService {
@Override
protected void setInsertParams(BaseInfo baseInfo) {
// 生成id
baseInfo.setId(UUIDUtil.generate());
}
}
6. 泛型工具类
/**
* 泛型相关工具
*/
public class GenericUtil {
private GenericUtil() {}
/**
* 获取泛型的具体类型
*
* @param clazz
* @return
*/
public static String getGenericType(Class<?> clazz) {
Type type = clazz.getGenericSuperclass();
if (!(type instanceof ParameterizedType)) {
throw new BizException("无法获取mapper,请检查是否提供泛型!");
}
// 强制类型转换
ParameterizedType pType = (ParameterizedType) type;
// 取得泛型类型的泛型参数
return pType.getActualTypeArguments()[0].getTypeName();
}
}