MyBatis映射文件
一、Mybatis文件的整体结构:
<?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="Mapper接口对应的全路径名称">
<!--可包含多个select、insert、update、resultMap、sql子节点-->
</mapper>
二、Mapper节点下的几个主要的子节点
1、select节点说明
-
select
:映射查询语句
作用:主要使用映射sql语句中的插叙语句id
:对应的是XxxMapper接口的方法名在命名空间中唯一的标识符,可以被用来引用这条语句。parameterType
:对应的是参数的类型resultType
:返回的类型,如果返回的是一个集合,需要写集合中存放的类型(泛型)statementType
:类型的取值有STATEMENT
(一般的stament语句)、PERPARED
(默认
,预编译的perparedStatement语句)、CALLABLE
(过程)resultMap
:复杂的结果集映射(下面会介绍到)。
2、insert、update和detele节点的说明
insert
(映射插入语句 )、update
(映射更新语句)、 delete
(映射删除语句)
parameterType
:对应的是参数的类型useGeneratedKeys="true"
和keyProperty="id"
: 在MySQL中使用主键自增策略获取主键的值,可通过这两个属性并映射到keyProperty
指定的主键中去,只有在insert
、update
语句中有效
备注:在Mapper文件中,一个sql语句的结束是不需要写 “ ;
”符号的
三、更丰富的用法resultMap、sql 以及动态 sql
1、resultMap复杂的返回值
属性:id 主要用于指定该resultMap标识
1)成员变量全是基本数据类型(对应的包装类)和Sting类的POJO
- id子节点:主要用于映射主键
<id column="数据库中对应的字段" property="实体类POJO中对应成员变量" >
- result 子节点: 用于映射普通属性
<result column="数据库字段名" property="成员变量名"/>
示例:
<resultMap id="user">
<!--这里映射的是主键-->
<id column="id" prorperty="id"/>
<result column="user_name" property="userName"/>
</resultMap>
2)成员变量包含其他引用的实体类,使用级联进行指定映射
JavaBean实体类的示例:
package com.example.bean;
class User{
private Integer id;
private String userName;
private Role role;
/*
省略setter和getter
*/
}
class Role{
private Integer id;
private String role_name;
/*
省略setter和getter
*/
}
格式
<result column="数据库字段名" property="成员变量名.成员变量名">
示例:
<resultMap id="user" type="com.example.bean.User">
<!--这里映射的是主键-->
<id column="id" prorperty="id"/>
<result column="user_name" property="userName"/>
<result column="rid" property="role.id"/>
<result column="role_name" property="role.role_name"/>
</resultMap>
3)成员变量包含其他引用的实体类,使用association关联
- 子节点:association,包含子节点 id、result,进行表字段映射对应JavaBean类的属性
<association property="成员变量名" javaType="引用类的全路径名称">....</association>
示例:还是上面的JavaBean,使用association
<resultMap id="userUseAssociation">
<!--这里映射的是主键-->
<id column="id" prorperty="id"/>
<result column="user_name" property="userName"/>
<association>
<id column="rid" property="role.id"/>
<result column="role_name" property="role.role_name"/>
</association>
</resultMap>
4)成员变量包含其他引用的实体类,分段查询
- 先查询出查出部分需要的数据
- 再通过查出的数据进行第二次查询
- 可以使用延迟加载,使用到相应的属性才会进行查询 (fetchType=“lazy”)
示例使用collection:分段查询
JavaBean:
package com.example.bean;
class Employee{
private Integer id;
private String name;
private Integer departmentId;
// 省略 getter 和 setter
}
class Department{
private Integer id ;
private departmentName;
private List<Employee> emplyeeList;
}
Mapper文件:
<!-- collection:分段查询 -->
<resultMap type="com.example.bean.Department" id="MyDeptStep">
<id column="id" property="id"/>
<id column="department_name" property="departmentName"/>
<collection property="emplyeeList"
select="com.example.EmployeeMapper.getEmpsByDeptId"
column="{deptId=id}" fetchType="lazy">
</collection>
</resultMap>
<select id="getEmpsByDeptId">
select * from employee where department_id = #{deptId}
</select>
拓展
- 单个值可以直接使用
column
直接传递,也可使使用封装成Map:column=“{参数名=字段名}”
- 多列的值传递过去:将多列的值封装map传递:
column="{key1=column1,key2=column2}"
2、if:判断
-
test
:判断表达式(OGNL) test从参数中取值进行判断,遇见特殊符号应该去写转义字符 -
格式:
<if test="判断条件">...</test>
-
为空判断:
<if test="name!=null"> ...</if>
-
空字符串判断:
<if test="name!="""></if>
-
使用and进行并列:
<if test="name!=null && name!=""">...</if>
示例:
<select id="getByConditionIf" parameterType="com.example.bean.User">
select * from user
where
<if test="id!=null and id>0">
id = #{id}
</if>
<!--不为空且不是空字符串-->
<if test="userName!=null and userName != "" ">
and user_name = #{userName}
</if>
</select>
3、where语句
在上面的if
示例中,如果出现了id为空的情况,会出现and 或者 or在where 关键字之后,Mybatis提供了where节点。
- 用于结合
if
条件判断语句进行查询 where
语句会把前面的and | or
排除,避免报错- 示例
<select id="getByConditionIf" parameterType="com.example.bean.User">
select * from user
<where>
<if test="id!=null and id>0">
id = #{id}
</if>
<!--不为空且不是空字符串-->
<if test="userName!=null and userName != "" ">
and user_name = #{userName}
</if>
</where>
</select>
4、trim语句
-
属性
prefix=""
(前缀):prefix给拼串后的整个字符串加一个前缀prefixOverrides=""
(前缀覆盖): 去掉整个字符串前面多余的字符suffix=""
(后缀):suffix给拼串后的整个字符串加一个后缀suffixOverrides=""
(后缀覆盖):去掉整个字符串后面多余的字符
-
作用:后面多出的and或者or where标签不能解决
-
示例
<select id="getByConditionTrim" parameterType="com.example.bean.User">
select * from user
<trim prefix="where" prefixOverridess="and">
<if test="id!=null and id>0">
id = #{id}
</if>
<!--不为空且不是空字符串-->
<if test="userName!=null and userName != "" ">
and user_name = #{userName}
</if>
</trim>
</select>
5、set语句
- 用于根据条件进行更新的操作
- set会删除结尾可能会有多余的
,
- 示例
<update id="updateBySet" paramterType="com.example.bean.User">
update user
<set>
<if test="userName!=null and userName != &quo;&quo;">
user_name = #{userName},
</if>
<if test="address!=null and address!= &quo;&quo;">
address = #{address}
</if>
</set>
where id = #{id}
</update>
set语句也可以使用trim
- 使用trim进行替换set
<update id="updateByTrim" paramterType="com.example.bean.User">
update user
<trim prefix="set" suffixOverrides=",">
<if test="userName!=null and userName != &quo;&quo;">
user_name = #{userName},
</if>
<if test="address!=null and address!= &quo;&quo;">
address = #{address}
</if>
</trim>
where id = #{id}
</update>
6、foreach语句
作用:用于遍历集合的
-
属性
collection
:指定要遍历的集合, list类型的参数会特殊处理封装在map中,map的key就叫listitem
:将当前遍历出的元素赋值给指定的变量separator
:每个元素之间的分隔符open
:遍历出所有结果拼接一个开始的字符close
:遍历出所有结果拼接一个结束的字符index
:索引, 遍历list的时候是index就是索引,item就是当前值;遍历map的时候index表示的就是map的key,item就是map的值#{变量名}
:就能取出变量的值也就是当前遍历出的元素
-
示例
<select id="getUserByConditionForeach" resultType="com.example.bean.User">
select * from user
<foreach collection="ids" item="id" separator=","
open="where id in(" close=")">
#{id}
</foreach>
</select>
7、choose、when、otherwise语句
在不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
- 可以根据传入的值进行不同条件的插叙
<select id="getUserByChoose" resultType="com.example.bean.User">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<!--如果名字不为空,就根据名字查-->
<when test="userName != null">
AND user_name like #{userName}
</when>
<!--如果地址不为空,就根据名字查-->
<when test="address != null">
AND address like #{address}
</when>
<otherwise>
AND sex= 1
</otherwise>
</choose>
</select>
8、sql的用法
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值
- 抽取可重用的sql片段。方便后面引用
- 1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
- 2、include来引用已经抽取的sql:
- 3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
示例
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
-
注意点
- include-property:取值的正确方式${prop}, 不能使用#{prop}这种方式
9、#{} 和${}的区别
- #{}:以预编译的形式,将参数设置到sql语句中,即预编译时的使用 “?”,实际执行的时候是传入的值,可以预防SQL注入
- ${}:是取出值,先直接拼接在sql语句中,会有安全问题,大多数请求下使用#{}
使用${}的情况:
- 原生jdbc不支持占位符的地方,需要使用${}进行取值
- 分库分表的情况
- 排序等