映射器是MyBatis最强大的工具,也是我们使用MyBatis时用得做多的工具,因此熟练掌握它是十分必要的。MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返回给调用者,而这些配置主要便是映射器。
映射器的主要元素
select元素
select元素常用配置:
举例:
<select id="findAll" resultType="user">
select
<include refid="column_list" />
from user
</select>
其中user表示User对象的别名,这里的id标识了这条SQL,resultType定义返回值类型
使用Map传递参数
<resultMap type="com.example.demo.entity.User" id="UserMap">
<id column="id" jdbcType="BIGINT" property="id" />
<!-- 两种方式 使用自定义的typeHandler -->
<!-- <result column="name" property="name" javaType="string" jdbcType="VARCHAR"
/> -->
<result column="name" property="name"
typeHandler="com.example.demo.handler.MyStringTypeHandler" />
<result column="sex" property="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
<sql id="column_list">
id,name,age
</sql>
<select id="findAll" parameterMap="map" resultMap="UserMap">
select
<include refid="column_list" />
from user
where name=#{name}
</select>
与之对应的,我们定义了一个接口方法
List<User> findAll (Map<String,String> params);
//在调用时:
Map<String,String> paramsMap=new HashMap<>;
paramsMap.put("name","wojiushiwo");
userMapper.findAll(paramsMap);//这里未给出userMapper的定义
这种方法虽然简单易用,但是有一个弊端:由于Map需要键值对应,由于业务关联性不强,造成代码可读性下降。
使用注解方法传递参数
我们需要使用MyBatis的参数注解@Param来实现想要的功能,如
//接口如下:
List<User> findAll (@Param("name") String name);
//查询方式:
<sql id="column_list">
id,name,age
</sql>
<select id="findAll" resultMap="UserMap">
select
<include refid="column_list" />
from user
where name=#{name}
</select>
当我们把参数传递给后台的时候,通过@Param提供的名称MyBatis就会知道#{name}代表name参数,参数的可读性大大提高。但是如果参数较多的情况下,这种情况就不适用了。
使用JavaBean传递参数
在参数过多的情况下,Mybatis允许组织一个JavaBean,通过简单的getter和setter方法设置参数,这样可以提高我们的可读性。
public class User{
private Long id;
private String name;
private int age;
...
}
//查询方式改为:
<select id="findAll" parameterType="user" resultMap="UserMap">
select
id,age,name
from user
where name=#{name}
</select>
//这里的user是实体类的别名,在Mybatis-conf.xml文件中配置的
使用resultMap映射结果集
其实在上面我们已经使用过了resultMap,现在我们大概了解一下其内部构造吧。
<resultMap type="com.example.demo.entity.User" id="UserMap">
<id column="id" jdbcType="BIGINT" property="id" />
<!-- 两种方式 使用自定义的typeHandler -->
<!-- <result column="name" property="name" javaType="string" jdbcType="VARCHAR"
/> -->
<result column="name" property="name"
typeHandler="com.example.demo.handler.MyStringTypeHandler" />
<result column="sex" property="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
定义了一个唯一标识(id)为UserMap的resultMap,用type属性去定义它对用的是哪个JavaBean(也可以使用别名)
通过id元素定义resultResultMap,这个对象代表着使用哪个属性作为其主键,result元素定义普通列的映射关系,例如,把SQL结果返回的列name和type属性定义的JavaBean的属性name对应
resultMap一般用于复杂、级联这些关联的配置,在简单的情况下,我们可以使用resultType通过自动映射来完成,这样配置的工作量就会大大减少。
insert元素
insert元素,将对于select元素而言要简单许多。MyBatis会在执行插入之后返回一个整数,以表示你进行操作后插入的记录数。
举例:
<insert id="insert" parameterType="user">
insert into
user
(name,sex,age)
values
(#{name},#{sex},#{age})
</insert>
在现实中我们插入数据后往往需要获得这个主键,以便于未来的操作。同样地,MyBatis提供了实现的方法
首先我们可以使用keyProperty属性指定哪个是主键字段,同时使用useGeneratedKeys属性告诉MyBatis这个主键是否使用数据库内置策略生成
<insert id="insert" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into
user
(name,sex,age)
values
(#{name},#{sex},#{age})
</insert>
这样我们传入的user对象就无需设置id的值,MyBatis就会用数据库的设置进行处理。这样做的好处是在Mybatis插入的时候,它会回填JavaBean的id值。
update元素&&delete元素
与insert一样均为DML语句,所以处理思路很相像。update和delete元素执行后会返回一个整数,标识执行后影响的记录条数
<delete id="delete" parameterType="java.lang.Long">
delete from user
where id=#{id}
</delete>
<update id="update" parameterType="user">
update user
set
<if test="#{name}!=null">name=#{name},</if>
<if test="#{age}!=null">age=#{age}</if>
where id=#{id}
</update>
#和$
在MyBatis中,我们产出传递字符串,我们设置的参数#{name}在大多数情况下MyBatis会用创建预编译的语句,然后MyBatis为它赋值,而有的时候我们需要的是传递SQL语句的本身,而不是SQL所需要的参数。例如,根据某些列进行排序等
例如,为orderColumn=“name” 表示待排序的列为name列,那么在Mybatis中可以这么写
select * from user order by ${orderColumn}
这样MyBatis就不会帮我们转义orderColumn,而变为直出,而不是作为SQL的参数进行设置。只是这样是对SQL而言不安全
sql元素
其实在上面我们已经用到过了,
<sql id="column_list">
id,name,age
</sql>
sql元素的意义,在于我们可以定义一穿sql语句的组成部分,其他的语句可以通过引用来使用它。例如,你有一条sql需要select几十个字段映射到JavaBean中去,我的第二个sql也是这几十个字段映射到JavaBean中区,显然这些字段写两遍不合适,因此我们就可以使用sql元素来完成
参考文献:
深入浅出MyBatis技术原理与实战