XML模式开发顺序:
在MyBatis中使用XML首先需要在 application.properties 文件中添加配置。
mybatis.mapper-locations=classpath:com/youkeda/dao/*.xml,classpath:com/youkeda/comment/dao/*.xml
一般来说这个路径和DAO的包路径一致,一个DAO类对应一个XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
//以上为头信息
<mapper namespace="com.youkeda.comment.dao.UserDAO">
</mapper>
XML在写入头信息后需要继续添加mapper节点,节点存在 namespace 属性表示命名空间,一般这里所对应的DAO的全称。
resultMap
resultMap用于处理表和DO对象的属性映射,确保表中的每一个字段都有属性可以匹配
<mapper namespace="com.youkeda.comment.dao.UserDAO">
<resultMap id="userResultMap" type="com.youkeda.comment.dataobject.UserDO">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
</resultMap>
</mapper>
resultMap中的属性如下:
resultMap的子节点:
resultMap也存在子节点 <association> 用于聚合其他对象:
<association property="author" javaType="com.youkeda.comment.model.User">
<id column="user_id" property="id"/>
<result column="user_name" property="userName"></result>
<result column="nick_name" property="nickName"></result>
<result column="avatar" property="avatar"></result>
</association>
其中 javaType 表示对应是数据模型,property 对应的是表中字段名
XML实现Insert功能
<insert id="add" parameterType="com.youkeda.comment.dataobject.UserDO" >
INSERT INTO user (user_name, pwd, nick_name,avatar,gmt_created,gmt_modified)
VALUES(#{userName}, #{pwd}, #{nickName}, #{avatar},now(),now())
</insert>
属性:
如之前的DAO内写入Insert方法,XML也可以修改主键设置
<insert id="add" parameterType="com.youkeda.comment.dataobject.UserDO" useGeneratedKeys="true" keyProperty="id">
与DAO内 @Options 注解效果相同
Update/Delete语句同理
<update id="update" parameterType="com.youkeda.comment.dataobject.UserDO">
update user set nick_name=#{nickName},gmt_modified=now() where id=#{id}
</update>
<delete id="delete">
delete from user where id=#{id}
</delete>
需要注意的是,因为我们在写删除语句的DAO时,语句为
int delete(@Param("id") long id);
@Param传入的参数(详见注解整理)是普通参数,默认情况下这类数据会被当做 Map 类型传入,而parameterType默认的类型就是 Map 因此这里可以把类型指定省略。
Select语句
select语句由于是获取数据,与上面几个语句不同,所以语法也不同
<select id="findByUserName" resultMap="userResultMap">
select * from user where user_name=#{userName} limit 1
</select>
这里使用了 resultMap 属性,它的值一般为XML文件下 resultMap 节点的id值,可以将获取的数据通过 resultMap 节点集体映射。
if语句
XML模式是支持添加if语句的如:
<update id="update" parameterType="com.youkeda.comment.dataobject.UserDO">
update user set
<if test="nickName != null">
nick_name=#{nickName},gmt_modified=now()
</if>
where id=#{id}
</update>
其中 if 存在属性 test 表明 if 的条件
set语句
在实际使用if语句中,可能会产生由于条件不满足而导致SQL语句错误,我们一般配合 set标签来完成 update
<update id="update" parameterType="com.youkeda.comment.dataobject.UserDO">
update user
<set>
<if test="nickName != null">
nick_name=#{nickName},
</if>
<if test="avatar != null">
avatar=#{avatar},
</if>
gmt_modified=now()
</set>
where id=#{id}
</update>
这里通过 set 标签代替了SQL语句中的set ,但注意的是其中的逗号不能漏掉,且使用 <set> 系统会自动去除最后一个逗号,而不用担心哪一列才是最后一个。
if+select
先看例子
<select id="search" resultMap="userResultMap">
select * from user where
<if test="keyWord != null">
user_name like CONCAT('%',#{keyWord},'%')
or nick_name like CONCAT('%',#{keyWord},'%')
</if>
<if test="time != null">
and gmt_created <![CDATA[ >= ]]> #{time}
</if>
</select>
这里 >=、<、<=、>、&、| 这类表达式会导致MyBatis解析失败,所以我们需要使用 <![CDATA[ key ]]> 来包裹
类似于 Insert中的 set 可以用 <set> 语句代替,select中的 where 也可以用 <where> 语句代替
<where>
<if test="keyWord != null">
user_name like CONCAT('%',#{keyWord},'%')
or nick_name like CONCAT('%',#{keyWord},'%')
</if>
<if test="time != null">
and gmt_created <![CDATA[ >= ]]> #{time}
</if>
</where>
循环语句
XML存在循环语句 <foreach>
<insert id="batchAdd" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (user_name, pwd, nick_name,avatar,gmt_created,gmt_modified)
VALUES
<foreach collection="list" item="it" index="index" separator =",">
(#{it.userName}, #{it.pwd}, #{it.nickName}, #{it.avatar},now(),now())
</foreach >
</insert>
属性:
上面代码结果为:
INSERT INTO user (user_name, pwd, nick_name,avatar,gmt_created,gmt_modified)
VALUES
(?, ?, ?,?,now(),now()),
(?, ?, ?,?,now(),now()),
(?, ?, ?,?,now(),now())
MyBatis会自动优化最后一个逗号,确保SQL正确。
添加上open和close:
<select id="findByIds" resultMap="userResultMap">
select * from user
<where>
id in
<foreach item="item" index="index" collection="ids"
open="(" separator="," close=")">
#{item}
</foreach>
</where>
</select>
其结果为:
select * from user where id in (?,?,?)
配置优化
当数据JSON输出时,会存在null数据,我们需要忽略它来节约流量,通过修改配置文件 application.properties 来完成
spring.jackson.deserialization.fail-on-unknown-properties=false
spring.jackson.default-property-inclusion=non_null
两个配置的作用是: