Skip to main content

Dynamic SQL

Mapper XML supports Dynamic SQL via if, choose, foreach, etc., using the familiar MyBatis style.

if tag

<if> conditionally appends SQL.

<select id="queryUser">
select * from users
where state = 'ACTIVE'
<if test="age != null">
and age = #{age}
</if>
</select>
Simple if can be replaced by rules
<select id="queryUser">
select * from users
where state = 'ACTIVE'
@{and, age = #{age}}
</select>

Attributes

PropertyDescription
testRequired OGNL expression returning boolean; when true the SQL inside is rendered.

choose (when, otherwise) tags

Renders the first matching <when> branch; if none match, <otherwise> is used.

<select id="queryUser">
select * from users
where state = 'ACTIVE'
<choose>
<when test="title != null">and title = #{title}</when>
<when test="content != null">and content = #{content}</when>
<otherwise>and owner = 'owner1'</otherwise>
</choose>
</select>

Attributes

<choose> and <otherwise> have no attributes. <when> attributes:

PropertyDescription
testRequired OGNL expression returning boolean; when true the SQL inside is rendered.

trim (where, set) tags

<trim>, <where>, and <set> help avoid malformed SQL. Consider this example:

<select id="queryUser">
select * from users
where
<if test="age != null">
and age = #{age}
</if>
</select>

If age is null, the generated SQL becomes:

select * from users
where

That is invalid SQL; <where> fixes this.

where tag (example 1)

When <if> produces content, <where> automatically adds the where keyword.

<select id="queryUser">
select * from users
<where>
<if test="age != null">
age = #{age}
</if>
</where>
</select>
Depending on the value of age, the generated statement will be one of the following:
select * from users;
select * from users where age = ?

where tag (example 2)

With multiple conditions, <where> also trims leading and/or.

<select id="queryUser">
select * from users
<where>
<if test="age != null">
age = #{age}
</if>
<if test="name != null">
and name = #{name}
</if>
</where>
</select>

set tag

Use <set> for dynamic UPDATE columns:

<update id="queryUser">
update users
<set>
<if test="age != null">age=#{age},</if>
<if test="name != null">name=#{name},</if>
</set>
where id=#{id}
</update>

<set> only trims separators; it does not supply missing update columns. Reject the update before calling the mapper if all fields are null.

trim tag

<trim> can replace <where> or <set> for special cases.

Use trim tag to replace where tag
<trim prefix="where" prefixOverrides="and | or">
...
</trim>
Use trim tag to replace set tag
<trim prefix="set" suffixOverrides=",">
...
</trim>

trim attributes

PropertyDescription
prefixOptional Prefix to add when rendering SQL.
suffixOptional Suffix to add when rendering SQL.
prefixOverridesOptional Trim these prefixes from the generated SQL (use `
suffixOverridesOptional Trim these suffixes from the generated SQL (use `

foreach tag

<foreach> is commonly used for IN clauses or value lists.

<select id="queryByIds">
select * from users
where id in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
Simple foreach can be replaced by rules
<select id="queryByIds">
select * from users where @{in,id in :list}
</select>

foreach attributes

PropertyDescription
collectionRequired Data to iterate (array, collection, etc.).
itemRequired Variable name for the current element; accessible inside the tag.
openOptional Text prepended before iteration output.
closeOptional Text appended after iteration output.
separatorOptional Separator between items.

bind tag

<bind> creates a variable via OGNL and binds it to the context.

<select id="queryByLike">
<bind name="pattern" value="'%' + title + '%'" />
select * from users
where title like #{pattern}
</select>

bind attributes

PropertyDescription
nameRequired Name of the variable to create.
valueRequired OGNL expression whose result is bound to name.