概述
在日常开发中,有很多模块如基础信息都是单表的增删改查,如果每个单表都要自己编写增删改查代码,无疑增加了很多不必要的开发成本。本文通过对增删改查进行封装,通过EasyCode生成模块代码,无需编写任何代码,即可实现单表增删改查、唯一性校验、数据字典翻译。
模块介绍
本文主要分为以下几个模块
- Controller :封装对外暴露的增删改查restful接口
- Service ,封装具体的增删改查逻辑,包括唯一性校验、增删改操作前后的个性操作
- Mapper ,继承Mybatisplus的BaseMapper接口
- DTO ,返回给前端的实体,包含字段校验、枚举翻译等
在介绍之前先看下一个完整的案例,熟悉下使用方式(下面案例代码均可由EasyCode生成)
以用户模块为例:
UserController
注:对外暴露用户的增删改查接口
@RestController
@RequestMapping("user")
public class UserController extends YaoBaseController<UserParam, UserEntity, UserDTO> {
@Autowired
private UserService userService;
@Override
public YaoBaseService<UserParam, UserEntity> getService() {
return userService;
}
@Override
public UserDTO getDTO() {
return new UserDTO();
}
@Override
public UserEntity getEntity() {
return new UserEntity();
}
}
UserDTO
注:用户字段校验,枚举翻译( @Formatter)等
/**
* 用户DTO
* @author YAO
* @since 2020-06-13
*/
public class UserDTO extends YaoBaseDTO implements Serializable {
/**
* 用户名
*/
@NotNull
private String username;
/**
* 别名即真实姓名
*/
private String nickname;
/**
* 是否有效,将 1:翻译成有效,0:翻译成无效
*/
@Formatter(dictCode = "enabled", targetField = "enabledStr")
private Integer enabled;
private String enabledStr;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getEnabled() {
return enabled;
}
public void setEnabled(Integer enabled) {
this.enabled = enabled;
}
public String getEnabledStr() {
return enabledStr;
}
public void setEnabledStr(String enabledStr) {
this.enabledStr = enabledStr;
}
}
UserParam
注:只要username非空,自动查询指定username对应的用户,无需编写其他代码
/**
* 用户请求参数
* @author Yao
* @since 2020-07-02
*/
public class UserParam extends PageParam {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
UserService
/**
* 用户service
* @author YAO
* @since 2020-06-13
*/
public interface UserService extends YaoBaseService<UserParam, UserEntity> {
}
UserServiceImpl
/**
* 用户service的实现类
*
* @author YAO
* @since 2020-06-13
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public YaoBaseMapper<UserEntity> getMapper() {
return userMapper;
}
}
UserMapper
/**
* 用户数据库操作
* @author YAO
* @since 2020-06-13
*/
@Mapper
public interface UserMapper extends YaoBaseMapper<UserEntity> {
}
UserEntity
/**
* 用户实体
* @author YAO
* @since 2020-06-13
*/
@TableName("user")
public class UserEntity extends YaoBaseEntity implements Serializable {
/**
* 用户名
*/
private String username;
/**
* 别名即真实姓名
*/
private String nickname;
/**
* 是否有效
*/
private Integer enabled;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getEnabled() {
return enabled;
}
public void setEnabled(Integer enabled) {
this.enabled = enabled;
}
}
下面是各模块上层的代码封装:
1、Controller
自定义YaoBaseController,使用方式继承该类
自带增删改查restful接口,其中查询会对DTO中被 @Formatter 注解的字段进行翻译,如:“0,1” 翻译成“男、女",支持 JSR-303对字段进行校验
package com.jing.yao.component.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jing.yao.annotation.ExcelFileName;
import com.jing.yao.annotation.Permission;
import com.jing.yao.bean.ResponseBean;
import com.jing.yao.component.dto.YaoBaseDTO;
import com.jing.yao.component.entity.YaoBaseEntity;
import com.jing.yao.component.params.page.PageParam;
import com.jing.yao.component.service.YaoBaseService;
import com.jing.yao.constant.ErrorCode;
import com.jing.yao.excel.ExcelUtil;
import com.jing.yao.exception.BusinessExceptionBuilder;
import com.jing.yao.holder.UserContentHolder;
import com.jing.yao.utils.YaoBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.jing.yao.bean.ResponseBean.builder;
import static com.jing.yao.component.constants.ResponseCode.ENTITY_NOT_FOUND;
import static com.jing.yao.component.constants.ResponseCode.FAIL_CODE;
/**
* 基础controller
*
* @author Yao
* @since 2020-06-13
*/
public abstract class YaoBaseController<P extends PageParam, T extends YaoBaseEntity, D extends YaoBaseDTO> {
/**
* 记录日志
*/
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 获取实际服务类
*
* @return
*/
public abstract YaoBaseService<P, T> getService();
/**
* 获取当前Controller数据库实体Entity
*
* @return
*/
public abstract T getEntity();
/**
* 获取当前Controller数据传输DTO
*
* @return
*/
public abstract D getDTO();
/**
* 分页模板
*
* @param param
* @return
*/
@GetMapping("/pageList")
public ResponseBean pageList(P param) {
IPage iPage = getService().page(param);
List<T> records = iPage.getRecords();
List<D> list = records.stream().map(entity -> {
D dto = getDTO();
YaoBeanUtils.copyAndFormatter(entity, dto);
return dto;
}).collect(Collectors.toList());
Page<D> pageDto = new Page<>();
pageDto.setCurrent(iPage.getCurrent());
pageDto.setRecords(list);
pageDto.setPages(iPage.getPages());
pageDto.setTotal(iPage.getTotal());
pageDto.setSize(iPage.getSize());
return successBean(pageDto);
}
/**
* 根据ID查询相关记录
*
* @param id
* @return
*/
@GetMapping("/{id}")
public ResponseBean selectById(@PathVariable("id") Long id) {
logger.info("{}根据ID查询服务开始,id为:{}", this.getClass().getSimpleName(), id);
T result = getService().selectOneById(id);
if (result == null) {
throw BusinessExceptionBuilder.build(ErrorCode.DETAIL_ID_NOT_EXIST);
}
ResponseBean responseBean = successBean(result);
logger.info("{}根据ID查询结束,结果:{}", this.getClass().getSimpleName(), toJSONString(responseBean));
return responseBean;
}
/**
* 转换为JSON字符串
*
* @param object
* @return
*/
private String toJSONString(Object object) {
ObjectMapper mapper = new ObjectMapper();
String result = "";
try {
result = mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
}
return result;
}
/**
* 插入
*
* @param dto
* @return
* @throws Exception
*/
@PostMapping
@Permission(value = "add")
public ResponseBean insert(@Valid @RequestBody D dto) {
logger.info("{}新增服务开始,参数:{}", this.getClass().getSimpleName(), toJSONString(dto));
ResponseBean responseBean = successBean();
boolean insert;
T entity = getEntity();
try {
//dto转为数据库实体
BeanUtils.copyProperties(dto, entity);
//新增前校验
insert = getService().insert(entity);
} catch (DuplicateKeyException exception) {
exception.printStackTrace();
return builder().code(FAIL_CODE).build();
}
//当插入记录小于1时,表示插入失败
if (!insert) {
responseBean = builder().code(FAIL_CODE).content(insert).build();
}
logger.info("{}新增服务结束,结果:{}", this.getClass().getSimpleName(), toJSONString(responseBean));
return responseBean;
}
/**
* 根据ID修改对应记录
*
* @param dto
* @return
* @throws Exception
*/
@PutMapping
@Permission(value = "edit")
public ResponseBean updateById(@Valid @RequestBody D dto) {
String username = UserContentHolder.getContext().getUsername();
logger.info("{}更新服务开始,更新人:{},参数:{}", this.getClass().getSimpleName(), username, toJSONString(dto));
T entity = getEntity();
//dto转换entity
BeanUtils.copyProperties(dto, entity);
ResponseBean responseBean = null;
boolean count;
try {
count = getService().update(entity);
} catch (DuplicateKeyException exception) {
return builder().code(FAIL_CODE).build();
}
//当更新记录小于1时,表示更新失败
if (!count) {
responseBean = builder().code(FAIL_CODE).content(count).build();
}
logger.info("{}更新服务结束,结果:{}", this.getClass().getSimpleName(), toJSONString(responseBean));
return successBean(count);
}
/**
* 根据ID删除指定记录,这里被删除的记录会进入删除记录表
*
* @param id
* @return
*/
@DeleteMapping("/{id}")
@Permission(value = "del")
public ResponseBean deleteById(@PathVariable("id") Long id) {
logger.info("{}删除服务开始,参数ID:{}", this.getClass().getSimpleName(), id);
boolean deleteCount = getService().removeById(id);
ResponseBean responseBean = successBean(deleteCount);
//当删除记录小于1时,表示更新失败
if (!deleteCount) {
responseBean = builder().code(FAIL_CODE).build();
}
logger.info("{}删除服务结束,结果:{}", this.getClass().getSimpleName(), toJSONString(responseBean));
return responseBean;
}
/**
* 构建成功响应实例
*
* @return
*/
public ResponseBean successBean() {
return builder().build();
}
/**
* 构建成功响应实例
*
* @param data
* @return
*/
public ResponseBean successBean(Object data) {
return builder().content(data).build();
}
}
2、Service
自定义YaoBaseService,使用方式继承该类
主要提供以下功能
(1)封装基础的增删改查功能
(2)当查询有查询条件时,只需请求对应的Param对象中属性有值即可,无需写再写查询代码
自定义的参数对象继承 YaoBaseParams,并定义自己的属性即可。当然,如果想自定义查询条件只需重写 com.anji.plus.component.service.YaoBaseService#getWrapper即可
/**
* 基础查询参数
* @author Yao
* @since 2020-06-13
*/
public class YaoBaseParams {
}
(3)前置后置处理器 processBeforeOperation、 processAfterOperation。当Insert、Update、Delete 执行前后需要增加些逻辑时,需重写前置后置处理器。比如:删除之前想校验数据是否能删除、保存更新后想操作下缓存(Redis)等
Demo:
@Override
public void processBeforeOperation(BmsApplyManagement entity, BaseOperationEnum operationEnum) throws BusinessException {
switch (operationEnum) {
case INSERT:
break;
case UPDATE:
break;
case DELETE:
break;
default:
}
}
package com.jing.yao.component.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.jing.yao.annotation.UnionUnique;
import com.jing.yao.annotation.Unique;
import com.jing.yao.component.constants.BaseOperationEnum;
import com.jing.yao.component.constants.BmsConstants;
import com.jing.yao.component.dto.Query;
import com.jing.yao.component.dto.QueryEnum;
import com.jing.yao.component.entity.YaoBaseEntity;
import com.jing.yao.component.mapper.YaoBaseMapper;
import com.jing.yao.component.params.page.PageParam;
import com.jing.yao.exception.BusinessException;
import com.jing.yao.exception.BusinessExceptionBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import static com.jing.yao.component.constants.ResponseCode.ENTITY_NOT_FOUND;
/**
* 基础service
* @author Yao
* @since 2020-06-13
*/
public interface YaoBaseService<P extends PageParam,T extends YaoBaseEntity> {
/**
* 获取直接操作数据库接口
* @return
*/
YaoBaseMapper<T> getMapper();
/**
* 根据id查询记录
* @param id
* @return
*/
default T selectOneById(Long id) {
return getMapper().selectById(id);
}
/**
* 排序
* @param pageParam
* @return
*/
default IPage<T> page(P pageParam) {
Page<T> page = new Page<>();
page.setCurrent(pageParam.getPageNumber());
page.setSize(pageParam.getPageSize());
//设置排序
if(StringUtils.equals(BmsConstants.ASC,pageParam.getOrder()) && StringUtils.isNotBlank(pageParam.getOrder())){
page.addOrder(OrderItem.asc(pageParam.getSort()));
} else if(StringUtils.equals(BmsConstants.DESC,pageParam.getOrder()) && StringUtils.isNotBlank(pageParam.getOrder())){
page.addOrder(OrderItem.desc(pageParam.getSort()));
} else {
page.addOrder(OrderItem.desc("update_time"));
}
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8:00"));
return getMapper().selectPage(page, getWrapper(pageParam));
}
/**
* 抽象查询条件
* @param param 查询条件
* @return
*/
default Wrapper<T> getWrapper(P param) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
//条件的值
Field[] fields = param.getClass().getDeclaredFields();
Arrays.stream(fields).forEach(field -> {
try {
boolean flag = false;
field.setAccessible(true);
if(field.get(param) instanceof String) {
flag = StringUtils.isNoneBlank((String)field.get(param));
} else {
flag = field.get(param) != null;
}
//判断是否是模糊查询
if(field.isAnnotationPresent(Query.class) && field.getAnnotation(Query.class).value() == QueryEnum.LIKE) {
queryWrapper.like(flag, com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(field.getName()), field.get(param));
} else {
queryWrapper.eq(flag, com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(field.getName()), field.get(param));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return queryWrapper;
}
/**
* 操作前处理
* @param entity 前端传递的对象
* @param operationEnum 操作类型
* @throws BusinessException 阻止程序继续执行或回滚事务
*/
default void processBeforeOperation(T entity, BaseOperationEnum operationEnum) throws BusinessException{
}
/**
* 操作后续处理
* @param entity
* @param operationEnum 操作类型
* @throws BusinessException 阻止程序继续执行或回滚事务
*/
default void processAfterOperation(T entity, BaseOperationEnum operationEnum) throws BusinessException {
}
/**
* 插入数据
* @param entity
* @throws BusinessException 业务异常
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean insert(T entity) throws BusinessException {
//保存前处理
processBeforeOperation(entity, BaseOperationEnum.INSERT);
checkUniqueField(entity);
Integer result = getMapper().insert(entity);
processAfterOperation(entity, BaseOperationEnum.INSERT);
return result != null && result >= 1;
}
/**
* 校验唯一
* @param entity
*/
default void checkUniqueField(T entity) {
//获取所有属性
Field[] fields = entity.getClass().getDeclaredFields();
//判断单一索引
for (Field field : fields) {
if (field.isAnnotationPresent(Unique.class)) {
Unique unique = field.getDeclaredAnnotation(Unique.class);
QueryWrapper<T> wrapper = Wrappers.query();
Integer integer = 0;
try {
Object value = getFieldValue(entity, field);
if (entity.getId() != null) {
wrapper.ne("id", entity.getId());
}
wrapper.eq(unique.column(), value);
integer = getMapper().selectCount(wrapper);
} catch (Exception e) {
continue;
}
if (integer > 0) {
throw BusinessExceptionBuilder.build(unique.code());
}
}
}
//判断联合索引
QueryWrapper<T> unionWrapper = Wrappers.query();
if (entity.getId() != null) {
unionWrapper.ne("id", entity.getId());
}
Integer integer = 0;
boolean flag = false;
for (Field field : fields) {
if (field.isAnnotationPresent(UnionUnique.class)) {
UnionUnique unionUnique = field.getDeclaredAnnotation(UnionUnique.class);
try {
Object value = getFieldValue(entity, field);
unionWrapper.eq(unionUnique.column(), value);
flag = true;
} catch (Exception e) {
continue;
}
}
}
if (flag) {
integer = getMapper().selectCount(unionWrapper);
if (integer > 0) {
throw BusinessExceptionBuilder.build(entity.getClass().getAnnotation(UnionUnique.class).code());
}
}
}
/**
* 获取属性值
* @param entity
* @param field
* @return
* @throws IntrospectionException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
default Object getFieldValue(T entity, Field field) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), entity.getClass());
Method readMethod = propertyDescriptor.getReadMethod();
return readMethod.invoke(entity);
}
/**
* 编辑数据
* @param entity
* @throws BusinessException 业务异常
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean update(T entity) throws BusinessException {
//编辑前处理
processBeforeOperation(entity, BaseOperationEnum.UPDATE);
Integer result = getMapper().updateById(entity);
processAfterOperation(entity, BaseOperationEnum.UPDATE);
return result != null && result >= 1;
}
/**
* 根据指定字段查询对应的值
* @param column
* @param value
* @return
*/
default List<T> list(String column, String value) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(column, value);
return getMapper().selectList(queryWrapper);
}
/**
* 根据指定条件查询对应的记录
* @param wrapper
* @return
*/
default List<T> list(Wrapper<T> wrapper) {
return getMapper().selectList(wrapper);
}
/**
* 根据ID查询记录
* @param id
* @return
*/
default T getById(Serializable id) {
return getMapper().selectById(id);
}
/**
* 删除
* @param id
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean removeById(Serializable id) {
T t = getById(id);
if(t == null) {
throw BusinessExceptionBuilder.build(ENTITY_NOT_FOUND);
}
processBeforeOperation(t,BaseOperationEnum.DELETE);
boolean result = SqlHelper.retBool(getMapper().deleteById(id));
processAfterOperation(t,BaseOperationEnum.DELETE);
return result;
}
/**
* 删除
* @param lambdaQueryWrapper
*/
@Transactional(rollbackFor = Exception.class)
default void delete(LambdaQueryWrapper<T> lambdaQueryWrapper) {
getMapper().delete(lambdaQueryWrapper);
}
/**
* 批量删除
* @param idList
* @return
*/
@Transactional(rollbackFor = Exception.class)
default boolean removeByIds(Collection<? extends Serializable> idList) {
return SqlHelper.retBool(getMapper().deleteBatchIds(idList));
}
/**
* 查询所有
* @return
*/
default List<T> findAll() {
return getMapper().selectList(Wrappers.emptyWrapper());
}
/**
* @Description 导出
* @author wangxiaoliang
* @date 2020-07-15 14:11
*/
default List<T> exportList(P param, HttpServletResponse response) {
Wrapper<T> wrapper = getWrapper(param);
List<T> managementList = getMapper().selectList(wrapper);
return managementList;
}
/**
* 根据指定字段更新值
* @param id
* @param column
* @param value
*/
default void updateColumn(Long id, String column, Object value) {
Map<String,Object> params = new HashMap<>();
params.put(column, value);
getMapper().updateFieldsById(params, id);
}
}
3、Mapper
自定义YaoBaseMapper,项目中的Mapper只要实现该接口即可
/**
* mybatis基础接口
* @author Yao
* @since 2020-06-23
*/
public interface YaoBaseMapper<T extends YaoBaseEntity> extends BaseMapper<T> {
/**
* 批量插入
*
* @param list
* @return
*/
int insertBatch(@Param("list") List<T> list);
/**
* 根据ID 更新指定字段
* @param map 指定字段和值
* @param id id
* @return
*/
int updateFieldsById(@Param("map") Map<String, Object> map, @Param("id") Long id);
}
数据库对应实体YaoBaseEntity,使用方式继承即可
package com.jing.yao.component.entity;
import com.baomidou.mybatisplus.annotation.*;
import java.util.Date;
/**
* 基础数据库实体
* @author Yao
* @since 2020-06-13
*/
public class YaoBaseEntity {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 版本号
* @Version:乐观锁,,需要添加mybatis plus插件optimisticLockerInterceptor
*/
@TableField(fill = FieldFill.INSERT_UPDATE, update="%s+1")
@Version
private Integer version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
4、DTO
自定义YaoBaseDTO,项目中所有跟前端交互的对象都需要转换为DTO(不必纠结DTO作为传输对象,返回给前端适不适合),DTO包含了字段校验、翻译等。项目中的DTO需要继承该类。该对象配合注解 @Formatter可实现字段的翻译
YaoBaseDTO:
package com.jing.yao.component.dto;
import java.util.Date;
/**
* 基础传输对象
* @author Yao
* @since 2020-06-13
*/
public class YaoBaseDTO {
private Long id;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改人
*/
private String updateBy;
/**
* 修改时间
*/
private Date updateTime;
/**
* 版本号
*/
private Integer version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
@Formatter
package com.jing.yao.annotation;
import java.lang.annotation.*;
/**
* 翻译
* @author Yao
* @since 2020-07-14
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Formatter {
/**
* 对应的数据字典,用被注解字段的值取该字典中取值
* @return
*/
String dictCode() default "";
/**
* 字典翻译后,把翻译后的值赋值到该字段
* @return
*/
String targetField() default "";
/**
* 指定缓存Key,不用数据字典,直接从对应的可以取值
* 但是对应Key在Redis的存储必须是Hash类型
*/
String key() default "";
}
以上只是工作中使用的一部分,如果有问题或者建议欢迎各位老铁指出
代码仓库地址链接