@TableName("t_dictionary")
@Data
public class Dictionary {
@Id
private Long id;
/**
* 编码,编码+类型唯一
*/
@NotBlank
private String code;
/**
* 字典值
*/
@NotBlank
private String value;
/**
* 类型
*/
@NotNull
private DictionaryType type;
/**
* 描述,用于展示
*/
@TableField(value = "`desc`")
private String desc;
}
public interface DictionaryService {
/**
* 获取分类下所有kv
*
* @param type 分类
* @return
*/
List<Dictionary> listByType(DictionaryType type);
/**
* code转换字典
*
* @param type 分类
* @param code 编码
* @return
*/
Dictionary getByCode(DictionaryType type, String code) throws NoSuchElementException;
/**
* value转换字典
*
* @param type 分类
* @param value 字典值
* @return
*/
Dictionary getByValue(DictionaryType type, String value);
public enum DictionaryType {
USER_ROLE("000001", "用户角色");
@EnumValue
final String code;
final String desc;
DictionaryType(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
这种实现方式有种问题,在进行insert\query\update操作后,entity内被标记的字段会被替换成对应的字典值,如果后续直接使用操作后返回的entity对象会出现异常
@Intercepts(
{
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type = StatementHandler.class, method = "getBoundSql", args = {}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
}
)
public class MybatisPlusInterceptor implements Interceptor {
//....
}
写入、查询时参数作转换
@Component
public class DictionaryInterceptor implements InnerInterceptor {
private final DictionaryService dictionaryService;
public DictionaryInterceptor(@Lazy DictionaryService dictionaryService) {
this.dictionaryService = dictionaryService;
}
/**
* {@link Executor#query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql)} 操作前置处理
* <p>
*
* @param executor Executor(可能是代理对象)
* @param ms MappedStatement
* @param parameter parameter
* @param rowBounds rowBounds
* @param resultHandler resultHandler
* @param boundSql boundSql
*/
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
try {
transClassFieldToValue(parameter);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* {@link Executor#update(MappedStatement, Object)} 操作前置处理
* <p>
*
* @param executor Executor(可能是代理对象)
* @param ms MappedStatement
* @param parameter parameter
*/
@Override
public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {
try {
transClassFieldToValue(parameter);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private void transClassFieldToValue(Object param) throws IllegalAccessException {
if (param == null) {
return;
}
Object obj;
Field[] fields;
if (param instanceof MapperMethod.ParamMap<?>) {
obj = ((MapperMethod.ParamMap<?>) param).getOrDefault(Constants.ENTITY, null);
if (obj == null) {
return;
}
} else {
obj = param;
}
fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Dictionary.class)) {
continue;
}
Dictionary annotation = field.getAnnotation(Dictionary.class);
field.setAccessible(true);
if (annotation != null && field.get(obj) != null) {
field.set(obj, dictionaryService.getByCode(annotation.dictionaryType(), (String) field.get(obj)).getValue());
}
}
}
}
最后一步别忘了把自定义拦截器注册到mybaits-plus
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(DictionaryInterceptor dictionaryInterceptor) {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(dictionaryInterceptor);
//...其他插件注册
return mybatisPlusInterceptor;
}
public class UserRoleHandler implements TypeHandler<String> {
@SneakyThrows
@Override
public void setParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException {
preparedStatement.setObject(i, transClassFieldToValue(s));
}
@SneakyThrows
@Override
public String getResult(ResultSet resultSet, String s) throws SQLException {
return transClassFieldToCode(s);
}
@SneakyThrows
@Override
public String getResult(ResultSet resultSet, int i) throws SQLException {
return transClassFieldToCode(resultSet.getString(i));
}
@SneakyThrows
@Override
public String getResult(CallableStatement callableStatement, int i) throws SQLException {
return transClassFieldToCode(callableStatement.getString(i));
}
private String transClassFieldToCode(String parameter) throws Exception {
DictionaryService dictionaryService = SpringUtil.getBean(DictionaryService.class);
return dictionaryService.getByValue(DictionaryType.USER_ROLE, parameter).getCode();
}
private String transClassFieldToValue(String param) throws IllegalAccessException {
DictionaryService dictionaryService = SpringUtil.getBean(DictionaryService.class);
return dictionaryService.getByCode(DictionaryType.USER_ROLE, param).getValue();
}
}
@Slf4j
@Component
@Intercepts({@Signature(
type = ResultSetHandler.class,
method = "handleResultSets",
args = {Statement.class})})
public class DictionaryResultInterceptor implements Interceptor {
private final DictionaryService dictionaryService;
public DictionaryResultInterceptor(@Lazy DictionaryService dictionaryService) {
this.dictionaryService = dictionaryService;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object result = invocation.proceed();
if (result instanceof List) {
for (Object line : (List) result) {
transClassFieldToCode(line);
}
} else {
transClassFieldToCode(result);
}
return result;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
private Object transClassFieldToCode(Object parameter) throws Exception {
Field[] fields = parameter.getClass().getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(Dictionary.class)) {
continue;
}
field.setAccessible(true);
Object value = field.get(parameter);
Dictionary annotation = field.getAnnotation(Dictionary.class);
if (value != null) {
field.set(parameter, dictionaryService.getByValue(annotation.dictionaryType(), (String) value).getCode());
}
}
return parameter;
}
本文来自博客园,作者:IAyue,转载请注明原文链接:https://www.cnblogs.com/zmj-pr/p/18176623