<sql> 标签
<sql> 元素的作用在于可以定义 SQL 语句的一部分(代码片段),以方便后面的 SQL 语句引用它,例如反复使用的列名。
然后通过 <include> 元素的 refid 属性引用自定义的代码片段即可。例如:
<sql id="studentInfo"> student_no, student_name,introduce</sql>
<!-- 查询所有信息 -->
<select id="findAll" resultMap="BaseResultMap">
select <include refid="studentInfo" /> from t_student
</select>
<where> 标签
<where> 元素的作用是会在写入 <where> 元素的地方输出一个 where 语句,如果所有的条件都不满足,那么 MyBatis 就不会增加 where 条件。
如果输出后是以 and 开头的或者 or 开头的,MyBatis 会把第一个 and 或者 or 忽略。
因此:where 标签最好在每个语句前面都加上 and,还要注意后面不能有逗号。
<set> 标签
在动态 update 语句中可以使用 <set> 元素动态更新列。
使用 set 标签时,最好在每一个更新的语句后面都加上英文的逗号,mybatis 会智能的把最后一个逗号去掉。注意 set 标签没有 and 关键字。
<if> 标签
在 MyBatis 中 <if> 元素是最常用的元素,它类似于 Java 中的 if 语句。if 语句的常用方法有放在更新的语句 <set> 中,和查询的语句 <select> 中,固定的格式是 <if test = "XXX and ***"> 例子:
①更新语句
<update id="updateByPrimaryKey" parameterType="com.study.entity.StudentEntity">
update t_student
<set>
<if test="null != studentName and '' != studentName">
student_name = #{studentName,jdbcType=VARCHAR},
</if>
<if test="null != introduce and '' != introduce">
introduce = #{introduce,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
②查询语句
<select id="selectAll" resultMap="BaseResultMap">
select id, student_no, student_name, introduce
from t_student
<where>
<if test="null != studentNo and '' != studentNo ">
and student_no = #{studentNo,jdbcType=VARCHAR}
</if>
<if test="null != studentName and '' != studentName ">
and student_name like CONCAT('%',#{studentName,jdbcType=VARCHAR},'%')
</if>
</where>
</select>
<choose> <when> <otherwise>标签搭配使用
<choose> 标签,它有点像 Java 中的 switch 语句:其中一个条件满足,其它的条件都不会被执行。而 <when>标签相当于 switch 语句的 case 分支, <otherwise>标签相当于 default 。例如:
<select id="findAll" resultMap="BaseResultMap">
select id, student_no, student_name, introduce
from t_student
<where>
<choose>
<when test="null != studentName and '' != studentName ">
and student_name like CONCAT('%',#{studentName,jdbcType=VARCHAR},'%')
</when>
<when test="null != studentNo and '' != studentNo ">
and student_no = #{studentNo,jdbcType=VARCHAR}
</when>
<otherwise>
and id = #{id,jdbcType=INTEGER}
</otherwise>
</choose>
</where>
</select>
<bind>标签
很多人不知道 mybatis 会有 bind 标签,或者很少用到。bind 的英文单词是绑定的意思。而 mybatis 中使用 bind 标签,大部分适用于模糊查询。对于模糊查询,如果我们操作的数据库是 MySQL ,则使用 concat 函数即可。如果是 Oracle 则用连接符号“||”。但是这样一来 SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植。因此,mybatis 的 bind 标签就派上用场了。
例子①,数据库是 MySQL 的模糊查询(注意这里没有用到索引,因为 like 关键字如果前面加了 % 是没有用到索引的):
<select id="select_2" resultMap="BaseResultMap">
select id, student_no, student_name, introduce
from t_student
<where>
<if test="null != studentName and '' != studentName ">
and student_name like CONCAT('%',#{studentName,jdbcType=VARCHAR},'%')
</if>
</where>
</select>
例子②,通用的模糊查询。
<select id="select_2" resultMap="BaseResultMap">
select id, student_no, student_name, introduce
from t_student
<where>
<if test="null != studentName and '' != studentName ">
<bind name="concatStuName" value="'%' + studentName + '%'" />
and student_name like #{concatStuName,jdbcType=VARCHAR}
</if>
</where>
</select>
<foreach> 标签
<foreach> 元素主要用在构建 in 条件中,它可以在 SQL 语句中迭代一个集合。
<foreach> 元素的属性主要有 item、index、collection、open、separator、close。
item:表示集合中每一个元素进行迭代时的别名。
index:指定一个名字,用于表示在迭代过程中每次迭代到的位置。
open:表示该语句以什么开始。
separator:表示在每次进行迭代之间以什么符号作为分隔符。
close:表示以什么结束。
在使用 <foreach> 元素时,最关键、最容易出错的是 collection 属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下 3 种情况:
如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。
例子①:foreach 执行批量新增操作(id 主键在数据库里是自增的)collection 属性值为 list。
<!-- 批量新增 -->
<insert id="batchInsert" parameterType="java.util.List">
insert into t_student (id, student_no, student_name, introduce)
values
<foreach collection="list" item="item" index="index" separator="," >
(
null,
#{item.studentNo,jdbcType=VARCHAR},
#{item.studentName,jdbcType=VARCHAR},
#{item.introduce,jdbcType=VARCHAR}
)
</foreach>
</insert>
说明:批量新增不推荐使用: open="(" close=")" 两个属性,因为会导致 SQL 语句拼接错误,如:
insert into t_student (id, student_no, student_name, introduce)values (null,?,?,?,null,?,?,?)
会报错:Column count doesn't match value count at row 1
Dao 层接口的写法:
Integer batchInsert(List<StudentEntity> stuList);
说明:我们传递的参数是 List 集合,因此 xml 里 collection="list"。
例子②:批量查询,使用 in 关键字,注意这里不要写成 #{item.id} ,否则会报错:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.lang.Integer'。
因为传递进来的是基本数据类型,而不是某个实体。而 item 就是遍历集合里的元素了。
<!-- 查询 -->
<select id="batchSelect" parameterType="java.util.List" resultMap="BaseResultMap">
select *
from t_student
<where>
id in
<foreach collection="list" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</where>
</select>
dao 层写法:
List<StudentEntity> batchSelect(List<Integer> ids);
例子③:foreach 使用 in,入参是 Map 集合:
<select id="mapSelect" parameterType="java.util.Map" resultMap="BaseResultMap">
select *
from t_student
<where>
<if test="null != studentName">
and student_name = #{studentName,jdbcType=VARCHAR}
</if>
and id in
<foreach collection="ids" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</where>
</select>
说明:这里需要传递 2 个参数:studentName 和 ids。ids 为 key 值。
调用接口:
List<StudentEntity> mapSelect(Map<String,Object> map);
构造参数:
Map<String,Object> map = new HashMap<>();
List<Integer> ids = Arrays.asList(1,2,3);
map.put("ids",ids);
map.put("studentName","张三");
List<StudentEntity> resultList = studentEntityMapper.mapSelect(map);