映射接口的参数与返回值

一、映射接口的参数与映射文件的取值

参数可以是简单的数据类型,JavaBean、Map、List、Array。

 

参数名称解析规则:

ParamNameResolver 是一个参数名解析器,用来按顺序列出方法中的虚参,并对实参进行名称标注。

ParamNameResolver 类主要的方法有两个:构造方法 ParamNameResolver 和getNamedParams方法。

构造方法 ParamNameResolver能够将目标方法的参数名称依次列举出来。在列举的过程中,如果某个参数存在@Param注解,则会用注解的 value值替换参数名。

同时会为每个参数名对应一个param1,param2 …,并将实参值赋值给param1,param2 …。

MyBatis在3.4.2版本之前,传递参数支持使用#{0} - #{n};在3.4.2及之后版本,没有使用@param注解的情况下,传递参数需要使用#{arg0}-#{argn}或者#{param1}-#{paramn},按照顺序拿

(因此你可以通过参数名称 | @param的value值 | paramx来取到值)

 

1、简单类型

接口定义:

Customers selectById(Integer id);

 
在映射文件中支持以下几种方式取值:

1.1 #{value}取值

特殊的在只有单参数时,可以通过#{value}直接取值:

<select id="selectById" resultType="customers">
       select * from customers where id = #{value};
</select>

 

1.2 通过变量名取值

无论是单参数还是多参数都可以,前提是你没有使用@Param注解

<select id="selectById" resultType="customers">
       select * from customers where id = #{id};
</select>

 

1.3 使用@Param注解

无论是单参数还是多参数都可以,在此时你无法通过变量名取到值

Customers selectById(@Param("customerId") Integer id);
<select id="selectById" resultType="customers">
       select * from customers where id = #{customerId};
</select>

 

1.4 使用paramx|argx
<select id="selectById" resultType="customers">
       select * from customers where id = #{param1}; 
</select>

 

2、JavaBean

对于JavaBean我们需要取到其属性值,此时就需要用到OGNL表达式了。

OGNL表达式:

它是 apache 提供的一种表达式语言,全称是: Object Graphic Navigation Language 对象图导航语言 。

它是按照一定的语法格式来获取数据的。 语法格式就是使用 #{对象.对象}的方式。

#{user.username}它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()方法把值取出来。

如果对象里面再包含对象,则可以使用#{xxx.xxx.xx}取值

但是我们在 parameterType 属性上指定了实体类名称,所以可以省略 user. 而直接写 username。

 
接口:

public class Customers {
    private Integer id;
    private String name;
    private String email;
    private String birth;
}

----------------
    
List<Customers> selectByQuery(Customers customers);

 

2.1 #{value}取值

和简单数据类型一样只有单参数时才可以使用,同时由于只有单参数因此可以省略value。(单个参数时,可不写value:#{value.name} 等价于 #{name})

<select id="selectByQuery" resultType="customers">
       select * from customers where name = #{name} and email = #{email}
</select>

 

2.2 变量名取值

和简单类型时一样的,范围也一样(单个参数时,可不写变量名:#{customers.name} 等价于 #{name})

<select id="selectByQuery" resultType="customers">
       select * from customers where name = #{name} and email = #{email}
</select>

 

2.4 使用@Param取值

和简单类型时一样的,范围也一样

List<Customers> selectByQuery(@Param("customer") Customers customers);
<select id="selectByQuery" resultType="customers">
       select * from customers where name = #{customer.name} and email = #{customer.email}
</select>

 

2.4 使用paramx|argx

和简单数据类型一样,范围也一样

<select id="selectByQuery" resultType="customers">
       select * from customers where name = #{param1.name} and email = #{param1.email}
</select>

 

3、Map

对于Map既可以使用foreach遍历使用,也可以不遍历使用

 

3.1 变量名、paramx|argx取值
3.1.1 单参数
List<Customers> selCustomersByMap(Map<String,String> map);

-------------
try(SqlSession sqlSession = factory.openSession()){
    ICustomersMapper mapper = sqlSession.getMapper(ICustomersMapper.class);
    HashMap<String, String> map = new HashMap<>();
    map.put("id","1");
    List<Customers> customers = mapper.selCustomersByMap(map);
    for(Customers e : customers)
        System.out.println(e);
}    

单参数情况下,它的取值方式类似于bean对象的取值,直接通过#{key值}来获取,但无法进行foreach遍历。
 
直接获取:

<select id="selCustomersByMap" resultType="com.bihai.pojo.Customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
    	id = #{id}
    </where>
</select>

 
foreach方式:

获取不到map,会报错,报错如下:

Caused by: org.apache.ibatis.builder.BuilderException: The expression ‘map’ evaluated to a null value.

 

3.1.2 多参数
List<Customers> selCustomerByMapAndId(Map<String,String> maps, String id);

----------------------
    
try(SqlSession sqlSession = factory.openSession()){
    ICustomersMapper mapper = sqlSession.getMapper(ICustomersMapper.class);
    HashMap<String, String> map = new HashMap<>();
    map.put("name","汪峰");
    List<Customers> customers = mapper.selCustomerByMapAndId(map,"1");
    for(Customers e : customers)
        System.out.println(e);
}    

对于多参数,无法通过#{id}、#{maps.xxx}获取;但可以通过paramx (从1开始)、argx (从0开始) 获取;对于map中的元素可以通过**#{paramx.key名称}**来获取。

 
直接使用:

<select id="selCustomerByMapAndId" resultType="customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
        id = #{param2}
        <if test="param1 != null">
            AND name = #{param1.name}
        </if>
    </where>
</select>

 
foreach方式:

<select id="selCustomerByMapAndId" resultType="customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
    	id = #{param2}
        <if test="param1 != null">
            <foreach open="AND " collection="param1" separator="AND " index="key" item="value">
            	#{key} = #{value}
        	</foreach>
        </if>
     </where>
</select>

 

3.2 @param取值

 

3.2.1 单、多参数

直接使用:

List<Customers> selCustomerByMapAndId(@Param("map") Map<String,String> maps, @Param("id") String id);
<select id="selCustomerByMapAndId" resultType="customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
        id = #{id}
        <if test="map != null">
            AND name = #{map.name}
        </if>
    </where>
</select>

 
foreach使用:

错误方式:通过#{key}获取到的key不对,带了''号,导致查不到数据;但上面通过paramx的方式遍历的key又是对的,无语了

<select id="selCustomerByMapAndId" resultType="customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
        <foreach open="AND " collection="map" separator="AND " index="key" item="value">
            #{key} = #{value}
        </foreach>
    </where>
</select>

 
正确方式:

<select id="selCustomerByMapAndId" resultType="customers">
    SELECT id, name, email,birth
    FROM `customers`
    <where>
        <foreach open="AND " collection="map" separator="AND " index="key" item="value">
            ${key} = #{value}
        </foreach>
    </where>
</select>

 

4、List与Array

对于List与Array用在foreach中,取值的方式可以通过变量名、paramx、@Param取值,并且单参数情况下可以通过list(仅仅针对List)、array(仅仅针对Array)取值。

 

4.1 变量名、@param、paramx取值
List<User> selectById(List<String> ids, String name);
<select id="selectById" parameterType="string" resultType="user">
    SELECT * FROM user WHERE
    <foreach collection="ids" item="e">
    	<if test = "e == '00001'">
        	id = #{e};
		</if>
    </foreach>
</select> 

 

4.2 通过list、array取值
<select id="selectById" parameterType="string" resultType="user">
    SELECT * FROM user WHERE
    <foreach collection="list" item="e">
    	<if test = "e == '00001'">
        	id = #{e};
		</if>
    </foreach>
</select> 

类似的Array也是一样的

 

二、接口的返回值

对于MyBatis支持的类型,可以在MapperMethod的execute方法中查看,如下:

/**
   * 执行映射接口中的方法
   * @param sqlSession sqlSession接口的实例,通过它可以进行数据库的操作
   * @param args 执行接口方法时传入的参数
   * @return 数据库操作结果
   */
  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) { // 根据SQL语句类型,执行不同操作
      case INSERT: { // 如果是插入语句
        // 将参数顺序与实参对应好
        Object param = method.convertArgsToSqlCommandParam(args);
        // 执行操作并返回结果
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: { // 如果是更新语句
        // 将参数顺序与实参对应好
        Object param = method.convertArgsToSqlCommandParam(args);
        // 执行操作并返回结果
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: { // 如果是删除语句MappedStatement
        // 将参数顺序与实参对应好
        Object param = method.convertArgsToSqlCommandParam(args);
        // 执行操作并返回结果
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT: // 如果是查询语句
        if (method.returnsVoid() && method.hasResultHandler()) { // 方法返回值为void,且有结果处理器
          // 使用结果处理器执行查询
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) { // 多条结果查询
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) { // Map结果查询
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) { // 游标类型结果查询
          result = executeForCursor(sqlSession, args);
        } else { // 单条结果查询
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
          if (method.returnsOptional()
              && (result == null || !method.getReturnType().equals(result.getClass()))) {
            result = Optional.ofNullable(result);
          }
        }
        break;
      case FLUSH: // 清空缓存语句
        result = sqlSession.flushStatements();
        break;
      default: // 未知语句类型,抛出异常
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      // 查询结果为null,但返回类型为基本类型。因此返回变量无法接收查询结果,抛出异常。
      throw new BindingException("Mapper method '" + command.getName()
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值