Mybatis返回Map类型数据 - 全栈笔记

Mybatis返回Map类型数据

任亦伟 JAVA 2017-12-27 234 次浏览 没有评论

一、需求

在开发中,我们有时候需要将结果集映射成Map类型,不是List<Map>,如下:

 

sql查询得到的结果是:

sql_result

而我们需要的数据格式是:

Jietu20171227-201458

对应bean的属性类型为:

Jietu20171227-202747

二、解决方案:

1、在service层实现

这种方法会让service层显得比较臃肿,如果系统中用的比较多,会重复写很多这样的代码

2、编写mybatis拦截器实现

根据多种尝试,最终决定写mybatis拦截器进行实现。

2.1、先写一个拦截器

01
02
package com.renyiwei.mybatis.interceptor;
03
 
04
import java.lang.reflect.Field;
05
import java.sql.ResultSet;
06
import java.sql.Statement;
07
import java.util.ArrayList;
08
import java.util.HashMap;
09
import java.util.List;
10
import java.util.Map;
11
import java.util.Properties;
12
 
13
import org.apache.ibatis.executor.resultset.ResultSetHandler;
14
import org.apache.ibatis.mapping.BoundSql;
15
import org.apache.ibatis.plugin.Interceptor;
16
import org.apache.ibatis.plugin.Intercepts;
17
import org.apache.ibatis.plugin.Invocation;
18
import org.apache.ibatis.plugin.Plugin;
19
import org.apache.ibatis.plugin.Signature;
20
 
21
@Intercepts({ @Signature(method = "handleResultSets", type = ResultSetHandler.class, args = { Statement.class }) })
22
public class MapInterceptor implements Interceptor {
23
 
24
  @SuppressWarnings("unused")
25
  private Properties properties;
26
 
27
  @Override
28
  public Object intercept(Invocation invocation) throws Throwable {
29
    ResultSetHandler resultSetHandler = (ResultSetHandler) invocation.getTarget();
30
    Class<? extends ResultSetHandler> clazz = resultSetHandler.getClass();
31
    // 反射读取boundSql 获得sql语句
32
    Field field = clazz.getDeclaredField("boundSql");
33
    field.setAccessible(true);
34
    BoundSql boundsql = (BoundSql) field.get(resultSetHandler);
35
    String sql = boundsql.getSql();
36
    // 如果sql中包含 MAP_KEY 和 MAP_VALUE 则被认为需要该将结果集转为Map类型
37
    if (sql.contains("MAP_KEY") && sql.contains("MAP_VALUE")) {
38
      try {
39
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
40
        Map<String, Object> map = new HashMap<String, Object>();
41
        Statement statement = (Statement) invocation.getArgs()[0]; // 取得方法的参数Statement
42
        ResultSet rs = statement.getResultSet(); // 取得结果集
43
        while (rs.next()) {
44
          String mapKey = rs.getString("MAP_KEY");
45
          Object mapValue = rs.getObject("MAP_VALUE");
46
          map.put(mapKey, mapValue); // 取得结果集后K、V关联后放到MAP当中
47
        }
48
        list.add(map);
49
        // 这里返回list,而不是直接返回map
50
        return list;
51
      } catch (Exception e) {
52
        // 如果出现异常,可能是冲突,则...
53
        return invocation.proceed();
54
      }
55
 
56
    }
57
    // 如果没有进行拦截处理,则执行默认逻辑
58
    return invocation.proceed();
59
  }
60
 
61
  @Override
62
  public Object plugin(Object target) {
63
    return Plugin.wrap(target, this);
64
  }
65
 
66
  @Override
67
  public void setProperties(Properties properties) {
68
    this.properties = properties;
69
  }
70
 
71
}
72
 
73

2.2、配置拦截器

01
02
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
03
  <property name="dataSource" ref="dataSource" />
04
  <!-- 自动扫描mapping.xml文件 -->
05
  <property name="mapperLocations" value="classpath:com/renyiwei/sqlMap/*.xml"></property>
06
  <property name="typeHandlersPackage" value="com.renyiwei.handler"></property>
07
  <property name="configLocation" value="classpath:mybatis.xml" />
08
  <property name="plugins">
09
    <list>
10
      <bean class="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
11
        <property name="dialectClass"
12
          value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"></property>
13
      </bean>
14
      <bean class="com.renyiwei.mybatis.interceptor.MapInterceptor"></bean>
15
 
16
    </list>
17
  </property>
18
</bean>
19

2.3、写sql语句

1
2
  <select id="selectPropMap">
3
    SELECT name AS MAP_KEY,value AS MAP_VALUE FROM table
4
  </select>
5

发表评论

回顶部