问题背景:
项目使用的是mybatis,原先用的数据库是Oracle, 最近需要改造成Postgresql数据库,由于项目中有很多查询返回的结果是Map, oracle查询出来的转换的结果是大写,但是Postgresql查询出来的结果默认都转换成了小写。
解决方案:
写在前面的话: Mybatis牛逼
遇到问题的第一反应是使用Mybatis插件,对结果集进行改变,当然也达到了效果,但是一次偶然的机会,我发现了更好的解决办法,那就是自定义一个对象加工工厂配到Mybatis里面。
以下代码是第一种插件代码:
@Intercepts({ @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class MapResultDealPlugin extends AbstractInterceptor {
private static final Logger logger = LoggerFactory.getLogger(com.al.persistence.plugin.AgentCountRowNumber.class);
public Object intercept(Invocation invocation) throws Throwable {
ResultSetHandler target = (ResultSetHandler) invocation.getTarget();
if(target instanceof FastResultSetHandler){
FastResultSetHandler fastResultSetHandler = (FastResultSetHandler) target;
//sql封装在fastResultSetHandler里面,并且是protect属性,需要用反射拿到值
BoundSql boundSql = (BoundSql) getKeyValue(FastResultSetHandler.class, fastResultSetHandler, "boundSql");
String sql =boundSql.getSql();
//判断sql里面有没有双引号,有双引号久不用管了
if(sql.contains("\"")) {
return invocation.proceed();
}else{
return caseDeal(invocation.proceed());
}
}
return invocation.proceed();
}
private <T> Object getKeyValue(Class<?> clazz, T obj, String key){
try {
Field field = clazz.getDeclaredField(key);
field.setAccessible(true);
return field.get(obj);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private Object caseDeal(Object result) {
if(result instanceof List){
//将result进行强转
List resultlist = (List) result;
List caseDeallist = new ArrayList();
if(resultlist.size() > 0) {
for(Object item:resultlist){
if(item instanceof Map){
caseDeallist.add(toUpperKey((Map)item));
}else{
return result;
}
}
}
return caseDeallist;
}else if (result instanceof Map){
return toUpperKey((Map)result);
}else{
return result;
}
}
private Map toUpperKey(Map orignMap){
Map resultMap = new HashMap();
for(Object keyObj:orignMap.keySet()) {
if(keyObj instanceof String) {
String key = keyObj.toString();
String newKey = key.toLowerCase();
if (key.equals(newKey)) {
resultMap.put(key.toUpperCase(),orignMap.get(keyObj));
}else{
resultMap.put(keyObj,orignMap.get(keyObj));
}
}else{
resultMap.put(keyObj,orignMap.get(keyObj));
}
}
return resultMap;
}
}
代码有点长,写完之后总感觉有点不舒服。
以下是对象加工工程的代码
先上mybatis-conf.xml里的配置:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<objectWrapperFactory type="com.ai.CustomerService.sqlset.MapWrapperFactory"/>
在上代码:
public class MapWrapperFactory implements ObjectWrapperFactory {
@Override
public boolean hasWrapperFor(Object object) {
return object != null && object instanceof Map;
}
@Override
public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
return new MyMapWrapper(metaObject,(Map)object);
}
}
public class MyMapWrapper extends MapWrapper {
public MyMapWrapper(MetaObject metaObject, Map<String, Object> map) {
super(metaObject, map);
}
@Override
public String findProperty(String name, boolean useCamelCaseMapping) {
if(useCamelCaseMapping){
//这一行代码实现将map所有key值转换成大写,除去sql里用双引号转换的驼峰命名
return name==null?"": name.toLowerCase().equals(name)?name.toUpperCase():name;
}
return name;
}
}
第二种对象加工工厂的方法,怎么看怎么顺眼。