动态SQL(code that is executed dynamically),它一般是根据用户输入或外部条件动态组合的SQL语句块。动态SQL能灵活的发挥SQL强大的功能、方便的解决一些其它方法难以解决的问题。相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能 (效率)上面不如静态SQL,而且使用不恰当,往往会在安全方面存在隐患 (SQL 注入式攻击)。
MyBatis动态 sql 的特性
Mybatis 动态 sql 是做什么的?
Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。
MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML 的维护上。
if 语句使用方法简单,常常与 test 属性联合使用。语法如下:
<iftest="判断条件"> SQL语句</if>
不使用动态sql
<selectid="selectUserByUsernameAndSex" resultType="user"parameterType="com.ys.po.User"> <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面 不一定要写id, 写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 --> select * from user where username=#{username} and sex=#{sex} </select>
使用动态sql
上面的查询语句,我们可以发现,如果 #{username} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断,可多个 if 语句同时使用。
<selectid="selectAllWebsite"resultMap="myResult"> select id,name,url from website where 1=1 <iftest="name != null"> AND name like #{name} </if> <iftest="url!= null"> AND url like #{url} </if> </select>
<selectid="selectUserByChoose"resultType="com.ys.po.User"parameterType="com.ys.po.User"> select * from user <where> <choose> <whentest="id !='' and id != null"> id=#{id} </when> <whentest="username !='' and username != null"> and username=#{username} </when> <otherwise> and sex=#{sex} </otherwise> </choose> </where> </select>
也就是说,这里我们有三个条件,id、username、sex,只能选择一个作为查询条件
如果 id 不为空,那么查询语句为:select * from user where id=?
如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;
如果 username 为空,那么查询语句为 select * from user where sex=?
trim
trim标记是一个格式化的标记,可以完成set或者是where标记的功能
用 trim 改写上面第二点的 if+where 语句
<selectid="selectUserByUsernameAndSex"resultType="user"parameterType="com.ys.po.User"> select * from user <!-- <where> <if test="username != null"> username=#{username} </if> <if test="username != null"> and sex=#{sex} </if> </where> --> <trimprefix="where"prefixOverrides="and | or"> <iftest="username != null"> and username=#{username} </if> <iftest="sex != null"> and sex=#{sex} </if> </trim> </select>
prefix:前缀
prefixoverride:去掉第一个and或者是or
用 trim 改写上面第三点的 if+set 语句
<!-- 根据 id 更新 user 表的数据 --> <updateid="updateUserById"parameterType="com.ys.po.User"> update user u <!-- <set> <if test="username != null and username != ''"> u.username = #{username}, </if> <if test="sex != null and sex != ''"> u.sex = #{sex} </if> </set> --> <trimprefix="set"suffixOverrides=","> <iftest="username != null and username != ''"> u.username = #{username}, </if> <iftest="sex != null and sex != ''"> u.sex = #{sex}, </if> </trim> where id=#{id} </update>
//批量查询 <selectid="findAll"resultType="Student"parameterType="Integer"> select * from student WHERE sid in <foreachitem="ids"collection="array"open="("separator=","close=")"> #{ids} </foreach> </select> //批量删除 <deleteid="del"parameterType="Integer"> delete from student where sid in <foreachitem="ids"collection="array"open="("separator=","close=")"> #{ids} </foreach> </delete>
</insert> <selectid="findAll"resultType="Student"parameterType="Integer"> <includerefid="selectvp"/> WHERE sid in <foreachitem="ids"collection="array"open="("separator=","close=")"> #{ids} </foreach> </select>
<deleteid="del"parameterType="Integer"> delete from student where sid in <foreachitem="ids"collection="array"open="("separator=","close=")"> #{ids} </foreach> </delete>
<!--一对一--> <selectid="find2"resultMap="myTeacher"> select * from teacher t right join student1 s on t.sid=s.sid </select>
MyBatis多对多关联查询
<!--多对多 以谁为主表查询的时候,主表约等于1的一方,另一方相当于多的一方--> <selectid="find3"resultMap="myStudent1"> select * from student1 s left join relevance r on s.sid=r.sid left join teacher t on r.tid=t.tid </select>