动态sql
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
if
if 是最基本的动态 SQL 标签,其 test 属性是一个用于判断输入参数的 OGNL 表达式,当条件判断为真时会拼接其中的内容。与编程语言不同,mybatis 没有 else 标签,if 标签仅用于最基本的条件判断,如果有多个并列的条件需要连续使用相应数量的 if 标签。
<select id="find" resultType="House"> select * from house where 1=1 <if test=" h_id!= null"> AND h_id like #{h_id} </if> <if test=" harea!= null"> AND harea like concat ("%",#{harea},"%") </if> <if test=" hestate!= null"> AND hestate like concat ("%",#{hestate},"%") </if> <if test=" hunitNumber!= null"> AND hunitNumber like #{hunitNumber} </if> <if test=" hfloor!= null"> AND hfloor like #{hfloor} </if> </select>
choose、when、otherwise
choose 标签的应用场景是多个条件选择一个,类似编程语言的 switch 语法。它有 when 和 otherwise 两个子标签:
-
when 子标签和 if 类似,test 属性用于判断 OGNL 表达式,一个 otherwise 标签内可以有任意数量、只会命中第一个 test 属性为真的。
-
otherwise 子标签类似 switch 的 default,如果前方所有的 when 子标签条件判断都为假,才会拼接上 otherwise 子标签里的内容。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
trim、where、set
trim 标签用于避免使用 if 或 choose 时为了 SQL 语法的正确性而不得不插入类似 1=1 and
这种语句,保证生成的 SQL 更干净、优雅,where 和 set 标签是 trim 的一种具体用法。
set
<update id="update" parameterType="House"> update house <set> <if test="harea!=null"> harea=#{harea}, </if> <if test="hestate!=null"> hestate=#{hestate}, </if> <if test="hunitNumber!=null"> hunitNumber=#{hunitNumber}, </if> <if test="hfloor!=null"> hfloor=hfloor}, </if> </set> where h_id=#{h_id} </update>
trim
trim 标签用于避免使用 if 或 choose 时为了 SQL 语法的正确性而不得不插入类似 1=1 and
这种语句,保证生成的 SQL 更干净、优雅,where 和 set 标签是 trim 的一种具体用法。
trim 属性详解
trim 标签有以下四个属性:
-
prefix:当 trim 内有内容时,会给内容增加 prefix 指定的前缀
-
prefixOverrides:当 trim 内有内容时,会将内容中匹配的前缀字符串取掉
-
suffix:当 trim 内有内容时,会给内容增加 suffix 指定的后缀
-
suffixOverrides:当 trim 内有内容时,会将内容中匹配的后缀字符串取掉
foreach
<!--添加--> <insert id="add"> insert into house <trim prefix="(" suffix=")" suffixOverrides=","> <if test="h_id != null">h_id,</if> <if test="harea != null">harea,</if> <if test="hestate != null">hestate,</if> <if test="hunitNumber != null">hunitNumber,</if> </trim> <trim prefix="values(" suffix=")" suffixOverrides=","> <if test="h_id != null">h_id,</if> <if test="harea != null">harea,</if> <if test="hestate != null">hestate,</if> <if test="hunitNumber != null">hunitNumber,</if> </trim> </insert>
foreach
顾名思义,foreach 标签用于实现集合遍历,它有以下属性:
-
collection:要迭代遍历的属性名。
-
item:变量名,每次迭代时从集合中取出的值的名称。
-
index:索引值,对 List 集合值为当前索引值,对 Map 集合值为当前 key。
-
open:整个循环内容开头处添加的字符串。
-
close:整个循环内容结尾处添加的字符串。
-
separator:每次循环的分隔符。
<!-- 可以重复查询多次 --> <select id="finds" resultType="House" parameterType="Integer"> select * from house where h_id in <foreach collection="array" item="h_id" open="(" separator="," close=")"> #{h_id} </foreach> </select>
映射关系
一对一映射:
比如一个对象有多个岗位
有两张数据表,其中A表的某个字段的值指向B表的主键。因为A表的任何一条记录只能对应B表的一条且唯一一条记录,所以称这种 映射为A表对B表数据的一对一映射。(当然,反过来,你也可是说,是B表对A表的一对多映射)。
<!--一对多--> <resultMap id="myStudent1" type="student1"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <result property="sex" column="sex"/> <result property="sage" column="sage"/> <collection property="list" ofType="teacher"> <id property="tid" column="tid"/> <result property="tname" column="tname"/> <result property="tage" column="tage"/> </collection> </resultMap> <!--一对多--> <select id="find1" resultMap="myStudent1"> select * from student1 s left join teacher t on s.sid=t.sid </select>
一对多映射:
一个岗位有多个人
<!--多对一--> <resultMap id="myTeacher" type="teacher"> <id property="tid" column="tid"/> <result property="tname" column="tname"/> <result property="tage" column="tage"/> <association property="student1" javaType="Student1"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> <result property="sex" column="sex"/> <result property="sage" column="sage"/> </association> </resultMap> <!--多对一--> <select id="find2" resultMap="myTeacher"> select * from teacher t right join student1 s on t.sid=s.sid </select>
多对多映射:
有中间表
<!--多对多 以谁为主表查询的时候,主表约等于1的一方,另一方相当于多的一方--> <select id="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>x