This article is generated by AI translation.
Dynamic Rules
These rules handle simple dynamic Command, such as only including arguments when non-empty. Rules available:
| Rule | Description |
|---|---|
@{and, queryExpr} | AND rule: if queryExpr produces non-empty conditions, it is appended to the final SQL. |
@{ifand, testExpr, queryExpr} | IFAND rule: when testExpr is true, queryExpr is processed with the AND rule. |
@{or, queryExpr} | OR rule: if queryExpr produces non-empty conditions, it is appended to the final SQL. |
@{ifor, testExpr, queryExpr} | IFOR rule: when testExpr is true, queryExpr is processed with the OR rule. |
@{in, queryExpr} | IN rule: queryExpr may contain one argument; when non-empty it is expanded to (?,?,?,...). |
@{ifin, testExpr, queryExpr} | IFIN rule: like IN, but only when testExpr is true. |
@{set, queryExpr} | SET rule: simplifies conditional updates in the set clause of update statements. |
@{ifset, testExpr, queryExpr} | IFSET rule: like SET, but only when testExpr is true. |
AND / IFAND
AND adds conditions only when they are non-empty; IFAND adds an activation expression.
select * from users
where status = :status -- status condition
@{and, uid = :userId} -- uid condition
<select id="queryUser">
select * from users
where status = #{status}
<if test="userId != null">
and uid = #{userId}
</if>
</select>
<!-- Mapper can also use rules -->
<select id="queryUser">
select * from users
where status = #{status} @{and, uid = :userId}
</select>
// Build SQL and args
String querySQL = "select * from users where status = ?";
Object queryArg = null;
if (userId != null) {
querySQL = querySQL + " and uid = ?";
queryArg = new Object[]{ 1, userId};
} else {
queryArg = new Object[]{ 1};
}
// Execute
jdbc.queryForList(querySQL, queryArg);
IFAND uses an expression to decide whether to apply the rule.
select * from users
where status = :arg0
@{ifand, arg1 != null, uid = :arg1}
arg1 != nulldecides whether to activate the rule.
<select id="queryUser">
select * from users
where status = #{status} @{ifand, userId != null, uid = :userId}
</select>
userId != nulldecides whether to activate the rule.
@{and} and @{ifand} adapt to these SQL shapes:
select * from users @{and, uid = :userId} -- auto-completes where
select * from users where @{and, uid = :userId} -- keeps where if empty
select * from users where status = :status @{and, uid = :userId} -- auto-completes and
select * from users where status = :status and @{and, uid = :userId} -- keeps and if empty
select * from users where status = :status or @{and, uid = :userId} -- downgrades to OR rule
OR / IFOR
OR/IFOR are analogous to AND/IFAND but join with or. Usage mirrors the AND rules.
IN / IFIN
IN simplifies building in clauses; IFIN adds an activation expression.
select * from users
where status = :arg0
@{in,and id in :arg1} -- produces id in (?,?,?)
<select id="queryUser">
select * from users
where status = #{status}
<if test="ids != null && ids.length > 0">
and id in
<foreach collection="ids" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
<!-- Mapper can also use rules -->
<select id="queryUser">
select * from users
where status = #{status} @{in,and id in :ids}
</select>
// Build SQL and args
StringBuilder querySQL = new StringBuilder("select * from user_info where status =?");
List<Object> queryArgs = new ArrayList<>();
queryArgs.add("1");
Object[] ids = new Object[] { 1, 2, 3 };
if (ids != null && ids.length > 0) {
querySQL.append("and id in (");
for (int i = 0; i < ids.length; i++) {
if (i == 0) {
querySQL.append("?");
} else {
querySQL.append(", ?");
}
queryArgs.add(ids[i]);
}
querySQL.append(")");
}
// Execute
jdbc.queryForList(querySQL.toString(), queryArgs.toArray());
IFIN uses an expression to decide whether to apply the IN rule.
select * from users
where status = :arg0
@{ifin, arg1.size() > 2 , and id in :arg1}
- Only when the argument count > 2 will the IN condition be added.
<select id="queryUser">
select * from users
where status = #{status} @{in, ids.size() > 2 ,and id in :ids}
</select>
- Only when the argument count > 2 will the IN condition be added.
IN rule limits:
- Only one
incondition per rule use. - IN does not auto-complete missing keywords like and/or/where.
- For example,
select * from users @{in,id in :ids}will be invalid SQL.
- For example,
IN supports arguments of type:
- Single object
- Collection/array wrapped by SqlArg
- Arrays
- Any Iterable subclass, including Collection/List/Set
SET / IFSET
SET simplifies conditional updates in the set clause of update; IFSET adds an activation expression.
update users
set update_time = now() -- update update_time
@{set, status = :arg0} -- update status when arg0 is non-empty (commas handled automatically)
where uid = :arg1
<update id="updateUser">
update users
set update_time = now()
<if test="status != null">, status = #{status}</if>
where
uid = #{uid}
</update>
<!-- Mapper can also use rules -->
<update id="updateUser">
update users
set update_time = now()
@{set, status = :status}
where
uid = #{uid}
</update>
// Build SQL and args
StringBuilder querySQL = new StringBuilder("update users set update_time = now()");
List<Object> queryArgs = new ArrayList<>();
if (status != null) {
querySQL.append(", status = ?");
queryArgs.add(status);
}
querySQL.append(" where uid =?");
queryArgs.add(uid);
// Execute
jdbc.executeUpdate(querySQL.toString(), queryArgs.toArray());
IFSET uses an expression to decide whether to apply the update item.
update users
set update_time = now()
@{ifset, arg0 != 2 ,status = :arg0}
where uid = :arg1
- Only when
statusis not equal to 2 will it be updated.
<update id="queryUser">
update users
set update_time = now()
@{ifset, status != 2 ,status = :status}
where
uid = #{uid}
</update>
- Only when
statusis not equal to 2 will it be updated.