mybaits-plus实现自定义字典转换
需求:字典实现类似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实现自定义字典转换的更多相关文章
- 字典转换成NSString(NSJson)
//字典转换成字符串 NSDictionary *dict = [NSMutableDictionary dictionary]; NSData *data = [NSJSONSerializatio ...
- 数据分析:基于Python的自定义文件格式转换系统
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 2、jeecg 笔记之 t:dictSelect 或 t:dgCol 自定义字典
1.需求 先说一下需求场景吧,我们知道 jeecg 中提供了下拉,其中包含两种使用场景: 一种是直接通过 t:dictSelect 使用,再就是 t:dgCol 用于表头的列表工具条标签: 总之就是 ...
- python3 下列表与字典转换
在写爬虫的时候,经常需要处理cookie,requests库里的cookie是dict,但是headers['cookie']却是一个key=value的字符串. 下面是几个用推导式实现的转换函数,供 ...
- mybatis自定义枚举转换类
转载自:http://my.oschina.net/SEyanlei/blog/188919 mybatis提供了EnumTypeHandler和EnumOrdinalTypeHandler完成枚举类 ...
- MyBatis使用自定义TypeHandler转换类型的实现方法
From: http://www.manongjc.com/article/15577.html 这篇文章主要介绍了MyBatis使用自定义TypeHandler转换类型的实现方法,本文介绍使用Typ ...
- MyBatis使用自定义TypeHandler转换类型
MyBatis虽然有很好的SQL执行性能,但毕竟不是完整的ORM框架,不同的数据库之间SQL执行还是有差异. 笔者最近在升级 Oracle 驱动至 ojdbc 7 ,就发现了处理DATE类型存在问题. ...
- python2.7字典转换成json时中文字符串变成unicode的问题:
参考:http://blog.csdn.net/u014431852/article/details/53058951 编码问题: python2.7字典转换成json时中文字符串变成unicode的 ...
- JS 自定义字典对象
<script type="text/javascript" language="javascript"> //自定义字典对象 function D ...
- python爬虫cookies jar与字典转换
#将CookieJar转为字典: cookies = requests.utils.dict_from_cookiejar(r.cookies) #将字典转为CookieJar: cookies = ...
随机推荐
- #树上带修莫队,树链剖分#洛谷 4074 [WC2013]糖果公园
题目 分析 考虑将树转换成序列求解,那就用欧拉序,入栈一次出栈一次正好抵消掉 注意当起点不是LCA的时候要将起点加入,剩下就是带修莫队板子题了 代码 #include <cstdio> # ...
- 基于文件语义实现S3接口语义的注意事项
本文标题中提到的文件语义,指的是POSIX规范. S3指的是AWS提供的对象存储服务以及相关接口.为方便描述,下文中以对象语义替代S3接口语义. 文件语义和对象语义存在比较多的差异. 对象语义不支持文 ...
- 并发和Read-copy update(RCU)
目录 简介 Copy on Write和RCU RCU的流程和API RCU要注意的事项 RCU的java实现 总结 简介 在上一篇文章中的并发和ABA问题的介绍中,我们提到了要解决ABA中的memo ...
- Java break、continue 详解与数组深入解析:单维数组和多维数组详细教程
Java Break 和 Continue Java Break: break 语句用于跳出循环或 switch 语句. 在循环中使用 break 语句可以立即终止循环,并继续执行循环后面的代码. 在 ...
- SQL JOIN 子句:合并多个表中相关行的完整指南
SQL JOIN JOIN子句用于基于它们之间的相关列合并来自两个或更多表的行. 让我们看一下"Orders"表的一部分选择: OrderID CustomerID OrderDa ...
- HarmonyOS如何使用异步并发能力进行开发
一.并发概述 并发是指在同一时间段内,能够处理多个任务的能力.为了提升应用的响应速度与帧率,以及防止耗时任务对主线程的干扰,HarmonyOS系统提供了异步并发和多线程并发两种处理策略. ● 异步 ...
- HDC2021技术分论坛:盘点分布式软总线数据传输技术中的黑科技
作者:houweibo,软总线首席技术专家:lidonghua,软总线技术专家 随着万物互联时代的到来,特别是大量媒体资源的涌入和使用,用户对传输的要求不断提高,怎样的传输技术才能满足未来的用户需求呢 ...
- HUAWEI DevEco Studio 3.1版本发布,配套ArkTS声明式开发全面升级
原文:https://mp.weixin.qq.com/s/ap5gH7vm3BUm0nU2WOzAzw,点击链接查看更多技术内容. 今年开发者大会发布了HarmonyOS应用开发套件Dev ...
- sql 语句系列(加减乘除与平均)[八百章之第十四章]
avg的注意事项 一张t2表: select * from t2 select AVG(sal) from t2 得到的结果是: 本来我们得到的结果应该是10的.但是得到的结果确实15. 这是因为忽略 ...
- C内存操作API的实现原理
我们在编写C代码时,会使用两种类型的内存,一种是栈内存,另外一种是堆内存,其中栈内存的申请和释放是由编译器来隐式管理的,我们也称为自动内存,这种变量是最简单而且最常用的,然后就是堆内存,堆的申请和释放 ...