一、概念和使用场景
使用MyBatis进行数据持久化的过程中,除了基于基本的纯SQL语句查询外,动态SQL也是MyBatis的强大特性之一。许多情况下,我们需要根据不同的条件动态的组装SQL语句,这时候就需要用到动态SQL。
动态SQL一般是根据用户输入或者外部条件动态组合的SQL语句块,能够灵活的发挥SQL强大的功能、方便解决一些其他方法难以解决或解决方法繁琐的问题。动态SQL常用的标签如下:
标签 作用 备注
if 判断语句 单条件判断
choose、when、otherwise
相当于java中的switch、case、default 多条件判断
thrim、where 辅助元素 用于处理一些SQL拼装问题
foreach 循环 用于批量插入、删除,或者in语句
二、标签用法
1、if标签:条件判断
用于根据条件判断是否执行对应的sql。
示例如下,可用于多字段筛选,只筛选有值的条件。
<select id="getList" parameterType="java.util.Map" resultType="com.simon.model.baseModel.ADAccount">
select * from ADAccount where 1=1
<where>
<if test="map.corp != null and map.corp!=''">
and corp=#{map.corp}
</if>
<if test="map.account != null and map.account != ''">
and account=#{map.account}
</if>
<if test="map.name != null and map.name != ''">
and name=#{map.name}
</if>
<if test="map.departmentTrace != null and map.departmentTrace != ''">
and departmentTrace=#{map.departmentTrace}
</if>
<if test="map.email != null and map.email != ''">
and email=#{map.email}
</if>
<if test="map.mobile !=null and map.mobile != ''">
and mobile=#{map.mobile}
</if>
<if test="map.status != null and map.status != ''">
and status=#{map.status}
</if>
</where>
</select>
2、where标签
用于where语句,上述示例已有它的用法
3、set标签
用于update更新语句。常与if标签连用,根据条件更新对应字段
示例如下,根据字段是否为空,判断是否更新该字段。
<update id="updateUser">
update user
<set>
<if test="name != null">name=#{name},</if>
<if test="phone != null">phone=#{phone},</if>
account=#{account}
</set>
where id=#{id}
</update>
4、choose、when、otherwise标签
用于选择多个条件中的某一个条件执行。
示例如下,根据条件选择id、username、phone、account中的一个字段进行筛选。依次判断when语句中的条件是否成立,若成立,则只执行当前语句;否则继续判断下一个。
<select id="getUserList" resultType="java.util.Map" parameterType="com.simon.model.baseModel.ADAccount">
select * from user
<where>
<choose>
<when test="id !='' and id != null">
id=#{id}
</when>
<when test="username !='' and username != null">
and username=#{username}
</when>
<when test="phone !='' and phone != null">
and phone =#{phone }
</when>
<otherwise>
and account=#{account}
</otherwise>
</choose>
</where>
</select>
5、trim标签
用于在增加或删除语句的前后缀。有四个属性,分别为:
prefix:为语句增加指定前缀。
prefixOverrides:为语句去除指定前缀。
suffix:为语句增加指定后缀。
suffixOverrides:为语句去除指定后缀。
例如,可将1中的语句改成如下语句,在语句中增加指定前缀“where”,同时去除第一条语句的前缀“and”。同理3中的语句也可以改为增加指定前缀“set”,同时去除最后一条语句的后缀“,”。
<select id="getList" parameterType="java.util.Map" resultType="com.simon.model.baseModel.ADAccount">
select * from ADAccount
<trim prefix="where" prefixOverrides="and">
<if test="map.corp != null and map.corp!=''">
and corp=#{map.corp}
</if>
<if test="map.account != null and map.account != ''">
and account=#{map.account}
</if>
<if test="map.name != null and map.name != ''">
and name=#{map.name}
</if>
<if test="map.departmentTrace != null and map.departmentTrace != ''">
and departmentTrace=#{map.departmentTrace}
</if>
<if test="map.email != null and map.email != ''">
and email=#{map.email}
</if>
<if test="map.mobile !=null and map.mobile != ''">
and mobile=#{map.mobile}
</if>
<if test="map.status != null and map.status != ''">
and status=#{map.status}
</if>
</where>
</select>
6、foreach标签
用于遍历集合,同时可以设置对遍历的每条语句之前增加分隔符,也可以对整体遍历的结果增加前后缀。有如下属性:
collection:需要遍历的集合。
item:当前遍历出的元素所赋值的变量。
index:当前遍历出的元素的索引。
open:最终遍历结果所需增加的前缀。
close:最终遍历结果所需增加的后缀。
separator:遍历出的每条语句之间的分隔符。
示例如下:
<select id="findAll" resultType="Student" parameterType="Integer">
<include refid="selectvp"/> WHERE sid in
<foreach item="ids" collection="array" open="(" separator="," close=")">
#{ids}
</foreach>
</select>
7、sql和include标签
sql标签主要用于设置公共的语句,而include标签则用于引用sql标签所定义的语句。
开发过程中总会重复编写一些相同的sql语句,而这就可以用sql标签来统一定义;而之后在需要的地方用include标签来引用即可,避免重复编码相同语句。
示例如下:
<sql id="Base_Column_List">
ID, AZID, EID, badge, Name, Joindate, WorkBeginDate, BalType, Term, TakeDate, ExpiredDate,
TotalBal, TotalDec, Bal, xUnit, SeqID, totalbal2, totalbal3, hjbadge
</sql>
<select id="selectByExample" parameterType="com.simon.model.ehrModel.AbalanceExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
'true' as QUERYID,
<include refid="Base_Column_List" />
from aBalance
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
如果要在不同的文件中引用sql标签,则需要在include标签的refid属性中填写sql标签的具体路径,例如:
<include refid="com.xxx.dao.xxMapper.Base_Column_List"></include>
三、关联查询
一般情况下的关联查询,只需要使用对应关联sql语句就可以。但如果遇到一对多的情况,在使用对应的sql语句之外,还需用到mybatis的关联查询的结果映射。如下:
<resultMap id="BaseResultMap" type="com.simon.model.ehrModel.Abalance">
<id column="ID" jdbcType="INTEGER" property="id" />
<result column="AZID" jdbcType="INTEGER" property="azid" />
<result column="EID" jdbcType="INTEGER" property="eid" />
<result column="badge" jdbcType="VARCHAR" property="badge" />
<result column="Name" jdbcType="NVARCHAR" property="name" />
<result column="Joindate" jdbcType="TIMESTAMP" property="joindate" />
<collection property="list" ofType="workInfo">
<result property="company" column="company"/>
<result property="startDate" column="startDate"/>
<result property="endDate" column="endDate"/>
</collection>
</resultMap>
四、注意
当然,动态SQL虽然可以根据条件动态的调整sql语句,从而增加代码开发的便利,但有时候并不能增加执行性能,而如果使用不当的话,更有可能存在sql注入的风险。需要谨慎使用。
————————————————