简述
映射器是MyBatis最复杂且最重要的组件,它由一个接口加上XML文件(或者注解)组成。在映射器中可以配置参数、各类SQL语句、存储过程、缓存、级联等复杂内容,并且通过建议的映射规则映射到指定的POJO或者其他对象上,映射器能有效消除JDBC底层的代码。
元素名称 | 描述 | 备注 |
---|---|---|
select | 查询语句,最常用、最复杂的元素之一 | 可以自定义参数,返回结果集等 |
insert | 插入语句 | 执行后返回一个整数,代表插入的条数 |
update | 更新语句 | 执行后返回一个整数,代表更新的条数 |
delete | 删除语句 | 执行后返回一个整数,代表删除的条数 |
定义参数映射关系 | 即将被删除的元素,不建议大家使用 | |
sql | 定义一部分SQL,在各个地方引用它 | 例如,一张表列名,一次定义,可以在多个SQL语句中使用 |
resultMap | 用来描述从数据库结果集中加载对象,它是最复杂、最强大的元素 | 提供映射规则 |
cache | 给定命名空间的缓存配置 | |
cache-ref | 其他命名空间缓存配置的引用 |
select元素
先来看看select元素的几个重要配置:
元素 | 说明 | 备注 |
---|---|---|
id | 它和Mapper的命名空间组合起来是唯一的,供MyBatis调用 | 如果命名空间和id结合起来不唯一,MyBatis会抛出异常 |
parameterType | 类的全命名,也可以是别名,但是别名必须是MyBatis内部定义的 | 可以选择JavaBean、Map等简单参数类型传递给SQL |
即将废弃的元素 | ||
resultType | 定义类的全路径,结果集将通过JavaBean的规范映射或者定义成int、double等参数,也可以使用别名 | 常用的参数之一 |
resultMap | 它是映射集的引用,执行强大的映射功能,resultMap能提供自定义的映射规则 | MyBatis最复杂的元素,可以配置映射规则、级联、typeHandler等 |
useCache | 启动二级缓存的开关,是否要求MyBatis将此次结果缓存 | 取值为布尔值,默认值为true |
简单的select例子:
<select id="findArticleById" parameterType="integer" resultMap="BaseResultMap">
SELECT * FROM article WHERE id = #{id}
</select>
- id配合Mapper的全限定名,成为一个唯一的标识,标识这条SQL
- parameterType为入参的类型
- resultMap为SQL语句返回的结果集的映射
自动映射和驼峰映射
MyBatis提供了自动映射功能,默认情况下自动映射是开启的,使用自动映射功能可以大量减少映射配置,在setting元素中有两个配置的选项 autoMappingBehavior 和 mapUnderscoreToCamelCase,它们是控制自动映射和驼峰映射的开关。
配置自动映射的 autoMappingBehavior 选项取值范围是:
- NONE 不进行自动映射
- PARTIAL 默认值,只对没有嵌套结果集进行自动映射
- FULL 对所有结果集进行自动映射,包括嵌套结果集
传参问题
在上面的例子中,只有一个参数传递,现实需求可能需要多个参数,MyBatis提供了多种方法来解决多参传入的问题。
- 使用map接口传递参数
接口定义
public List<User> findUserByMap(Map<String,Object>parameterMap);
映射器
<select id="findUserByMap" parameterType="map" resultType="user">
SELECT * FROM user WHERE id = #{id} and name = #{name}
</select>
注意,参数id和name,要求的是map的键!
- 使用注解传递多个参数 @Param
使用map传递参数有个弊端–代码可读性差,MyBatis提供了一个注解@Param,可以通过它去定义映射器的参数名称。
接口定义
public List<User> findUserByMap(@Param("id")Integer id,@Param("name")String name);
映射器
<select id="findUserByMap" resultType="user">
SELECT * FROM user WHERE id = #{id} and name = #{name}
</select>
注意,这里使用了@Param注解就不需要给出parameterType属性,MyBatis可以自动探索。
- 通过JavaBean传递多个参数
定义POJO
public class UserSelect{
private Integer id;
private String name;
................
}
接口定义
public List<User> findUserByMap(UserSelect userSelect);
映射器
<select id="findUserByMap" parameterType="com.ssm.vo.UserSelect" resultType="user">
SELECT * FROM user WHERE id = #{userSelect.id} and name = #{userSelect.name}
</select>
insert、update、delete元素
由于insert、update、delete这三个元素使用方法类似,这里就将三种元素放在一起。
MyBatis在执行完insert、update、delete语句之后,会返回一个整数来表示其影响的数据库记录数。
insert
<insert id="insert" parameterType="com.ronin.blog.entity.Article" >
insert into article (article_user_id, article_title, article_summary,
article_view_count, article_comment_count,
article_like_count, article_is_comment, article_status,
article_update_time, article_create_time,
article_html, article_content)
values ( #{articleUserId,jdbcType=INTEGER}, #{articleTitle,jdbcType=VARCHAR},
#{articleViewCount,jdbcType=INTEGER}, #{articleCommentCount,jdbcType=INTEGER},
#{articleLikeCount,jdbcType=INTEGER}, #{articleIsComment,jdbcType=INTEGER}, #{articleStatus,jdbcType=INTEGER},
#{articleUpdateTime,jdbcType=TIMESTAMP}, #{articleCreateTime,jdbcType=TIMESTAMP},
#{articleHtml,jdbcType=LONGVARCHAR}, #{articleContent,jdbcType=LONGVARCHAR})
</insert>
主键回填
可以看出上面这条语句没有插入id列,因为MySql中表格采用了主键自增,MySql数据库会自动生成主键,我们也可以在MyBatis插入数据时获取到数据库生成的主键值。在insert语句中有个开关属性 useGeneratedKeys,用来控制是否打开这个功能,默认值是false。打开时要配置其属性 keyProperty 或 keyColumn,告诉系统把生成的主键放入哪个属性,如果存在多个主键,用逗号(,)隔开。
update
<update id="updateByPrimaryKey" parameterType="com.ronin.blog.entity.Article" >
update article
set article_user_id = #{articleUserId,jdbcType=INTEGER},
article_title = #{articleTitle,jdbcType=VARCHAR},
article_summary = #{articleSummary,jdbcType=VARCHAR},
article_view_count = #{articleViewCount,jdbcType=INTEGER},
article_comment_count = #{articleCommentCount,jdbcType=INTEGER},
article_like_count = #{articleLikeCount,jdbcType=INTEGER},
article_is_comment = #{articleIsComment,jdbcType=INTEGER},
article_status = #{articleStatus,jdbcType=INTEGER},
article_update_time = #{articleUpdateTime,jdbcType=TIMESTAMP},
article_create_time = #{articleCreateTime,jdbcType=TIMESTAMP},
article_html = #{articleHtml,jdbcType=LONGVARCHAR},
article_content = #{articleContent,jdbcType=LONGVARCHAR}
where article_id = #{articleId,jdbcType=INTEGER}
</update>
delete
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from article
where article_id = #{articleId,jdbcType=INTEGER}
</delete>
sql元素
sql元素的作用在于可以定义一条SQL的一部分,方便后面的SQL引用它,把重复的SQL语句抽取出来,降低耦合性。
定义
<sql id="articleAndTagLine">
a.* , t.tag_id , t.tag_description , t.tag_name , u.user_id , u.user_name
</sql>
引用
<select id="selectTopArticle" resultMap="BaseResultMap">
select <include refid="articleLine"/> from article
</select>
resultMap元素
resultMap的作用是定义映射规则、级联的更新、定制类型转化器等。resultMap定义的主要是一个结果集的映射关系,就是SQL到JavaBean的映射关系定义,它也支持级联等特性。
<resultMap id="BaseResultMap" type="com.ronin.blog.entity.Article" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="title" property="title" jdbcType="VARCHAR" />
<result column="keywords" property="keywords" jdbcType="VARCHAR" />
<result column="desci" property="desci" jdbcType="VARCHAR" />
<result column="pic" property="pic" jdbcType="VARCHAR" />
<result column="click" property="click" jdbcType="INTEGER" />
<result column="time" property="time" jdbcType="TIMESTAMP" />
<result column="catalog_id" property="catalogId" jdbcType="INTEGER" />
</resultMap>