用MyBatis结果集拦截器做过这样一个需求:
由于项目需求经常变动,项目MySQL数据库都是存放JSON字符串,例如:用户的基本信息随着版本升级可能会有变动
数据表
CREATE TABLE `account` (
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
`infos` text NOT NULL COMMENT '用户JSON基本信息',
`createTime` int(10) unsigned NOT NULL COMMENT '创建时间',
`updateTime` int(10) unsigned NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
数据:
id
infos
createTime
updateTime
1
{"nickName":"Jan","region_area":"","region_city":"深圳市","region_country":"中国","region_province":"广东省","sex":"男","signature":"只要不放弃就还有机会!"}
1467793564
1470795733
JSONPlugin拦截器
使用MyBatis拦截器对ResultSetHandler接口的handleResultSets方法进行拦截:
package me.xuebai.modules.mybatis;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import me.xuebai.modules.entity.Account;
@Intercepts({@Signature(
type= ResultSetHandler.class,
method = "handleResultSets",
args = {Statement.class})})
public class JSONPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
// 获取到当前的Statement
Statement stmt = (Statement) args[0];
// 通过Statement获得当前结果集
ResultSet resultSet = stmt.getResultSet();
List resultList = new ArrayList();
if(resultSet != null && resultSet.next()) {
Account account = new Account();
// infos字段
String infos = resultSet.getString("infos");
// 判断是否为空
if(StringUtils.isNotBlank(infos)) {
// fastjson泛型反序列化
Map infMap = JSON.parseObject(infos, new TypeReference(){});
account.setInfos(infMap);
resultList.add(account);
}
// handleResultSets返回结果一定是一个List
// size为1时,Mybatis会取第一个元素作为接口的返回值。
return resultList;
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
mybatis-config.xml
在mybatis配置文件中注册插件:
测试输出
Account account = accountDao.get(1L);
// {sex=男, region_city=深圳市, region_area=, nickName=Jan, region_country=中国, signature=只要不放弃就还有机会!, region_province=广东省}
System.out.println(account.getInfos());