基礎框架一:“零程式碼”實現單表增刪改查、唯一性校驗、列舉型別翻譯
概述
在日常開發中,有很多模組如基礎資訊都是單表的增刪改查,如果每個單表都要自己編寫增刪改查程式碼,無疑增加了很多不必要的開發成本。本文通過對增刪改查進行封裝,通過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 "";
}
以上只是工作中使用的一部分,如果有問題或者建議歡迎各位老鐵指出
程式碼倉庫地址連結