书接前文的mybatis之select及insert、update、deleted映射器分析解读,前回书中有介绍如何使用以上映射器,在使用时对于参数的处理是一个细节要谨慎的点,让我们来看一下哪些细节需要提起重视。
参数
在参数使用简单数据类型或原始类型时,因为没有其他属性,可以使用它的值来作为参数:
<selectid="selectUsers"resultType="User">
select id, username, password
from users
where id = #{id}
</select> 当使用一个复杂对象作为参数对象时,需要使用如下的处理方式:
<insertid="insertUser"parameterType="User">
insert into users (id, username, password)
values (#{id}, #{username}, #{password})
</insert> 参数也可以设置特殊的数据类型,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap。这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用,JDBC 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型(jdbcType):
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}对于数值类型,还可以设置 numericScale 指定小数点后保留的位数:
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}最后mode 属性允许你指定 IN,OUT 或 INOUT 参数。如果参数的 mode 为 OUT 或 INOUT,将会修改参数对象的属性值,以便作为输出参数返回。如果 mode 为 OUT(或 INOUT),而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),你必须指定一个 resultMap 引用来将结果集 ResultMap 映射到参数的类型上。要注意这里的 javaType 属性是可选的,如果留空并且 jdbcType 是 CURSOR,它会被自动地被设为 ResultMap:
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}MyBatis 也支持很多高级的数据类型,比如结构体(structs),但是当使用 out 参数时,你必须显式设置类型的名称。比如(再次提示,在实际中要像这样不能换行):
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbcType,其他的事情交给 MyBatis 自己去推断就可以:
#{firstName}#{middleInitial,jdbcType=VARCHAR}#{lastName}关于#{}
默认情况下在使用#{}时,mybatis会创建preparedstatement参数占位符,并通过参数占位符安全地设置参数,效率也较快。当时有时我们想直接在sql语句中直接插入一个不转义的字符串,可以使用${}该字段就不会被mybatis转义和修改了,如:
ORDER BY ${columnName}
当sql语句中的元数据如表名或列名时动态生成时,字符串替换就会非常有效,如在select一个表任意一列数据时,不需要这么写:
@Select("select * from user where id = #{id}")User findById(@Param("id")long id);@Select("select * from user where name = #{name}")User findByName(@Param("name")String name);@Select("select * from user where email = #{email}")User findByEmail(@Param("email")String email);
而是可以使用下列代码取代:
@Select("select * from user where ${column} = #{value}")User findByColumn(@Param("column")String column,@Param("value")String value);
其中${column}会被直接替换,#{value}会使用?预处理,需要注意的是用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击。因此,要么不允许用户输入这些字段,要么自行转义并检验这些参数;
结果映射
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作,resultmap的设计思路是对简单的语句做到零配置,对复杂的句子把语句之间的关系描述清楚即可。
让我们先看一个简单的映射语句:
<select id="selectUsers" resultType="map">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
上述语句中只是将所有的列映射到hashmap上,通过resulttype指定,但有时hashmap无法满足,所以我们会选择使用pojo、javabean作为领域模型,mybatis对此都是支持的。
package com.someapp.model;public class User {
private int id;
private String username;
private String hashedPassword;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getHashedPassword() {
return hashedPassword;
}
public void setHashedPassword(String hashedPassword) {
this.hashedPassword = hashedPassword;
}}
<select id="selectUsers" resultType="com.someapp.model.User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
<!-- mybatis-config.xml 中使用类型别名,节省输入类全限定名的处理 -->
<typeAlias type="com.someapp.model.User" alias="User"/>
<!-- SQL 映射 XML 中 --><select id="selectUsers" resultType="User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECT 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配。比如:
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
虽然上述的例子不需要显示制定resultmap,那么如果遇到需要显式添加时该怎么处理呢?
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/><result property="password" column="hashed_password"/>
</resultMap>
在引用它的语句中设置 resultMap
属性就行了:
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
好了,以上为今天的mybatis参数及结果映射相关的介绍分析,那么当我们遇见一些复杂的sql处理时,该如何进行配置结果映射呢?让我们明天继续跟进讲解,我是雷记,非常开心可以和大家交流关于myabtis的使用学习心得,如果有疑问的话欢迎随时公众号私信我,如果今天的文章对你有帮助的话,还请点赞转发,这对我很重要!




