myBatis mapper 返回任意类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了myBatis mapper 返回任意类型相关的知识,希望对你有一定的参考价值。

<select id="select" parameterType="String" resultType="T">
感谢两位的回答,我现在的要求不是说我不会用mybatis,我是会一些基础的东西,我现在想对mybatis 框架进行封装,所以想要一些 相关mybatis 的动态写法,希望朋友们,多多指教!

定义一个MapInterceptor用于拦截对应的结果集返回一个Map。
其代码如下所示:
@Intercepts(@Signature(method="handleResultSets", type=ResultSetHandler.class, args=Statement.class))
public class MapInterceptor implements Interceptor

/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin.Invocation)
*/
public Object intercept(Invocation invocation) throws Throwable
//通过invocation获取代理的目标对象
Object target = invocation.getTarget();
//暂时ResultSetHandler只有FastResultSetHandler这一种实现
if (target instanceof FastResultSetHandler)
FastResultSetHandler resultSetHandler = (FastResultSetHandler) target;
//利用反射获取到FastResultSetHandler的ParameterHandler属性,从而获取到ParameterObject;
ParameterHandler parameterHandler = ReflectUtil.getFieldValue(resultSetHandler, "parameterHandler");
Object parameterObj = parameterHandler.getParameterObject();
//判断ParameterObj是否是我们定义的MapParam,如果是则进行自己的处理逻辑
if (parameterObj instanceof MapParam) //拦截到了
MapParam mapParam = (MapParam) parameterObj;
//获取到当前的Statement
Statement stmt = (Statement) invocation.getArgs()[0];
//通过Statement获取到当前的结果集,对其进行处理,并返回对应的处理结果
return handleResultSet(stmt.getResultSet(), mapParam);


//如果没有进行拦截处理,则执行默认逻辑
return invocation.proceed();


/**
* 处理结果集
* @param resultSet
* @param mapParam
* @return
*/
private Object handleResultSet(ResultSet resultSet, MapParam mapParam)
// TODO Auto-generated method stub
if (resultSet != null)
//拿到Key对应的字段
String keyField = (String) mapParam.get(MapParam.KEY_FIELD);
//拿到Value对应的字段
String valueField = (String) mapParam.get(MapParam.VALUE_FIELD);
//定义用于存放Key-Value的Map
Map<Object, Object> map = new HashMap<Object, Object>();
//handleResultSets的结果一定是一个List,当我们的对应的Mapper接口定义的是返回一个单一的元素,并且handleResultSets返回的列表
//的size为1时,Mybatis会取返回的第一个元素作为对应Mapper接口方法的返回值。
List<Object> resultList = new ArrayList<Object>();
try
//把每一行对应的Key和Value存放到Map中
while (resultSet.next())
Object key = resultSet.getObject(keyField);
Object value = resultSet.getObject(valueField);
map.put(key, value);

catch (SQLException e)
e.printStackTrace();
finally
closeResultSet(resultSet);

//把封装好的Map存放到List中并进行返回
resultList.add(map);
return resultList;

return null;


/**
* 关闭ResultSet
* @param resultSet 需要关闭的ResultSet
*/
private void closeResultSet(ResultSet resultSet)
try
if (resultSet != null)
resultSet.close();

catch (SQLException e)




/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object)
*/
public Object plugin(Object obj)
return Plugin.wrap(obj, this);


/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties)
*/
public void setProperties(Properties props)



参考技术A 虽然这个问题是N年前的了,但是我最近也用到了类似的功能,刚好也误打误撞碰巧做出来了,所以还是说一下我的解决方案吧,如有可改之处,敬请各位大佬不吝赐教。
首先,需求是,定义一个动态的方法,查询的时候根据查询语句直接查询,所以和楼主说的一样,我的select标签是这样的:
<select id="select" parameterType="java.lang.String" resultType="AllResultMap">
$_parameter
</select>
其中,$_parameter最好和我写的一样,因为我试过_param,发现报错了,我也不知道为什么,但是这么写是可以的。另外AllResultMap的具体实现为:
<resultMap type="java.util.Map" id="AllResultMap">
</resultMap>
这样,在XXXmapper.java文件里面,接口只需要这么写:
public LinkedList<Map> select(String _parameter);
这样最终查询出来的结果就是一个list里面有很多个map对象,而map中的key就是你的列名,value就是数据库一条record对应的值。然后剩下的就是按照你自己的意愿对map进行解析、封装成你自己想要的类的对象就好了。
参考技术B 可以知道resultTyp="map",查询语句类似 SELECT name AS nameKey,age AS ageKey FROM table;返回用一个Hashmap接收,对应的可以map.get(nameKey);map.get(ageKey);就可以获得对应的值,然后再封装吧。追问

我目前的写法是

SELECT
*
FROM
users
WHERE
userId = 'userId'
可是结果,让我无法理解 本来应该是 userId userName 都有值,结果 就只把userId 的值 以字符串的形式给我返回来。

本回答被提问者采纳
参考技术C 不行,myBatis要么你明确返回类型,配置某个类,要么你就返回HashMap。列表就用List<HashMap>追问

那怎么才能让它 根据我传入的类型,做为返回类型
例如 我传入 A 类 查询结果后 返回 A类

追答

http://zhidao.baidu.com/link?url=9NsAMlQyEjBT6Hk9wfLzQXogP4OzncU60LB4QGsiHisZJzJjD9X0yJC6gA-mZlejwPoZItXlcldSDKQYaiV8Eq

参考技术D 你是想提供答案,还是求助,求助的话遇到什么问题追问

你好,刚才着急提交实在不好意思,我想求助
mybatis在查询时可不可以不指定返回类型,用T或Object目前我试过了,不行

MyBatis中Mapper的返回值类型

insert、update、delete语句的返回值类型

对数据库执行修改操作时,数据库会返回受影响的行数。

在MyBatis(使用版本3.4.6,早期版本不支持)中insert、update、delete语句的返回值可以是Integer、Long和Boolean。在定义Mapper接口时直接指定需要的类型即可,无需在对应的<insert><update><delete>标签中显示声明。

对应的代码在 org.apache.ibatis.binding.MapperMethod 类中,如下:

  • 对于insert、update、delete语句,MyBatis都会使用 rowCountResult 方法对返回值进行转换;
  • rowCountResult 方法会根据Mapper声明中方法的返回值类型来对参数进行转换;
  • 对于返回类型为Boolean的情况,如果返回的值大于0,则返回True,否则返回False
 1 public Object execute(SqlSession sqlSession, Object[] args) {
 2     Object result;
 3     switch (command.getType()) {
 4       case INSERT: {
 5       Object param = method.convertArgsToSqlCommandParam(args);
 6         result = rowCountResult(sqlSession.insert(command.getName(), param));
 7         break;
 8       }
 9       case UPDATE: {
10         Object param = method.convertArgsToSqlCommandParam(args);
11         result = rowCountResult(sqlSession.update(command.getName(), param));
12         break;
13       }
14       case DELETE: {
15         Object param = method.convertArgsToSqlCommandParam(args);
16         result = rowCountResult(sqlSession.delete(command.getName(), param));
17         break;
18       }
19       case SELECT:
20         if (method.returnsVoid() && method.hasResultHandler()) {
21           executeWithResultHandler(sqlSession, args);
22           result = null;
23         } else if (method.returnsMany()) {
24           result = executeForMany(sqlSession, args);
25         } else if (method.returnsMap()) {
26           result = executeForMap(sqlSession, args);
27         } else if (method.returnsCursor()) {
28           result = executeForCursor(sqlSession, args);
29         } else {
30           Object param = method.convertArgsToSqlCommandParam(args);
31           result = sqlSession.selectOne(command.getName(), param);
32         }
33         break;
34       case FLUSH:
35         result = sqlSession.flushStatements();
36         break;
37       default:
38         throw new BindingException("Unknown execution method for: " + command.getName());
39     }
40     if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
41       throw new BindingException("Mapper method ‘" + command.getName() 
42           + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
43     }
44     return result;
45   }
46 
47   private Object rowCountResult(int rowCount) {
48     final Object result;
49     if (method.returnsVoid()) {
50       result = null;
51     } else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
52       result = rowCount;
53     } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
54       result = (long)rowCount;
55     } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
56       result = rowCount > 0;
57     } else {
58       throw new BindingException("Mapper method ‘" + command.getName() + "‘ has an unsupported return type: " + method.getReturnType());
59     }
60     return result;
61   }

select语句的返回值类型

对于select语句,必须在Mapper映射文件中显示声明返回值类型,否则会抛出异常,指出“A query was run and no Result Maps were found for the Mapped Statement”。

select语句返回的column值与Mapper方法返回值的属性的映射有两种方式:

  • 通过名称实现自动映射
  • 通过resultMap标签指定映射方式

通过名称实现自动映射

只要保证数据库查询返回的column名称和Bean的属性名一致,Mybatis便能够实现自动映射。如:

    <select id="selectActorById"  resultType="canger.study.chapter04.bean.Actor">
        select actor_id as id, first_name as firstName ,last_name as lastName
        from actor
        where actor_id=#{id}
    </select>
public class Actor {
    Long id;
    String firstName;
    String lastName;
}

 需要特别说明的有3个地方:

  • 返回值Bean无需为属性设置getter/setter方法,Mybatis依然能够为其赋值;
  • 如果column名称和Bean的属性名只有部分相同,那么只有名称相同的属性会被赋值,Bean依然会被创建;
  • 如果column名称与所有Bean的属性名都不相同,则select语句会返回null值,即使数据库中存在符合查询条件的记录;

 通过resultMap标签指定映射方式

待续

以上是关于myBatis mapper 返回任意类型的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot集成Mybatis及通用Mapper

MyBatis中Mapper的返回值类型

MyBatis应用开发映射之参数绑定parameterType

mapper代理查询

mybatis的mapper接口动态代理开发

mybatis报Mapper配置文件出错