一、映射接口的参数与映射文件的取值
参数可以是简单的数据类型,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方法中查看,如下:
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
switch (command.getType()) {
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: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
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()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
|