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的返回值类型

上一篇:Android 技能图谱学习路线


下一篇:ios动态修改指令