需求:字典实现类似mybatis-plus中@EnumValue的功能,假设枚举类中应用使用code,数据库存储对应的value

思路:Mybatis支持对Executor、StatementHandler、PameterHandler和ResultSetHandler进行拦截,也就是说会对这4种对象进行代理。mybatis-plus实际上也是通过mybatis提供的拦截功能进行封装,我们在对数据库进行insert\query\update操作时,利用mybatis提供的拦截器对字典做转换

@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<?>) {
handleParamMap((MapperMethod.ParamMap<?>) param);
return;
} else {
obj = param;
fields = param.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());
} }
} private void handleParamMap(MapperMethod.ParamMap<?> param) throws IllegalAccessException {
for (Object value : param.values()) {
transClassFieldToValue(value);
}
} }

返回结果转译

@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;
}

最后一步别忘了把自定义拦截器注册到mybaits-plus

    @Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(DictionaryInterceptor dictionaryInterceptor) {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(dictionaryInterceptor);
//...其他插件注册 return mybatisPlusInterceptor;
}
@TableName("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;
}
}

mybaits-plus实现自定义字典转换的更多相关文章

  1. 字典转换成NSString(NSJson)

    //字典转换成字符串 NSDictionary *dict = [NSMutableDictionary dictionary]; NSData *data = [NSJSONSerializatio ...

  2. 数据分析:基于Python的自定义文件格式转换系统

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  3. 2、jeecg 笔记之 t:dictSelect 或 t:dgCol 自定义字典

    1.需求 先说一下需求场景吧,我们知道 jeecg 中提供了下拉,其中包含两种使用场景: 一种是直接通过 t:dictSelect 使用,再就是 t:dgCol  用于表头的列表工具条标签: 总之就是 ...

  4. python3 下列表与字典转换

    在写爬虫的时候,经常需要处理cookie,requests库里的cookie是dict,但是headers['cookie']却是一个key=value的字符串. 下面是几个用推导式实现的转换函数,供 ...

  5. mybatis自定义枚举转换类

    转载自:http://my.oschina.net/SEyanlei/blog/188919 mybatis提供了EnumTypeHandler和EnumOrdinalTypeHandler完成枚举类 ...

  6. MyBatis使用自定义TypeHandler转换类型的实现方法

    From: http://www.manongjc.com/article/15577.html 这篇文章主要介绍了MyBatis使用自定义TypeHandler转换类型的实现方法,本文介绍使用Typ ...

  7. MyBatis使用自定义TypeHandler转换类型

    MyBatis虽然有很好的SQL执行性能,但毕竟不是完整的ORM框架,不同的数据库之间SQL执行还是有差异. 笔者最近在升级 Oracle 驱动至 ojdbc 7 ,就发现了处理DATE类型存在问题. ...

  8. python2.7字典转换成json时中文字符串变成unicode的问题:

    参考:http://blog.csdn.net/u014431852/article/details/53058951 编码问题: python2.7字典转换成json时中文字符串变成unicode的 ...

  9. JS 自定义字典对象

    <script type="text/javascript" language="javascript"> //自定义字典对象 function D ...

  10. python爬虫cookies jar与字典转换

    #将CookieJar转为字典: cookies = requests.utils.dict_from_cookiejar(r.cookies) #将字典转为CookieJar: cookies = ...

随机推荐

  1. #二分,spfa#洛谷 1948 [USACO08JAN] Telephone Lines S

    题目 分析 二分答案,设高于答案的边权为1,否则为0 然后如果最短路答案\(\leq k\)那么这个答案符合要求 代码 #include <cstdio> #include <cct ...

  2. #动态规划,组合计数,树状数组,前缀和#F 简单计数题&K 最简单的题

    先膜两位出题人 F 简单计数题 题目 有\(n\)个活动,预约期有\(k\)天,第\(j\)天YC可以获得\(a_j(1\leq a_j\leq n)\)张预约券, 他会在\(n\)个活动中等概率选择 ...

  3. #整体二分 or 主席树#洛谷 7424 [THUPC2017] 天天爱射击

    题目 给定\(n\)条线段\(x_i,y_i,k_i\)和\(m\)个点(点有顺序), 对于每个点,问有多少条线段是第\(k_i\)次被该点经过. 分析(主席树) 将点按坐标排序建主席树那么就是一道静 ...

  4. OpenHarmony社区运营报告(2023年5月)

      本月快讯 ● 2023年6月11-13日,2023开放原子全球开源峰会即将在北京北人亦创国际会展中心盛大开幕.2023开放原子全球开源峰会上,OpenAtom OpenHarmony(以下简称&q ...

  5. 网络组件axios可以在OpenHarmony上使用了

    什么是axios 上古浏览器页面在向服务器请求数据时,因为返回的是整个页面的数据,页面都会强制刷新一下,这对于用户来讲并不是很友好.并且我们只是需要修改页面的部分数据,但是从服务器端发送的却是整个页面 ...

  6. C++ While 和 For 循环:流程控制全解析

    C++ Switch 语句 使用 switch 语句选择要执行的多个代码块之一. 语法 switch(expression) { case x: // 代码块 break; case y: // 代码 ...

  7. IDEA社区版,真香!

    IDEA(IntelliJ IDEA)是众多 Java 开发者的首选. 商业版的昂贵 IDEA 商业版(IntelliJ IDEA Ultimate)功能非常强大,能够满足 Java 开发的所有需求, ...

  8. RabbitMQ 01 概述

    什么是消息队列 进行大量的远程调用时,传统的Http方式容易造成阻塞,所以引入了消息队列的概念,即让消息排队,按照队列进行消费. 它能够将发送方发送的信息放入队列中,当新的消息入队时,会通知接收方进行 ...

  9. 历时 4 个月,CabloyJS 4.21震撼发布,应对大型项目开发

    引言 凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript 来写 | Atwood 定律 目前市面上出现的大多数与 NodeJS 相关的框架,基本都将 NodeJS 定位在工 ...

  10. CentOS 防火墙配置实战精要

    防火墙是服务器最重要的安全屏障,正确的操作对应用也是非常非常关键,本文参考了一些实战经验并经过实验验证,集众家之长做了简单的归纳整理,希望能帮助你更好地操作防火墙. 设置CentOS防火墙开放端口 在 ...