Understanding MyBatis Dynamic SQL: Parsing, Nodes, and Execution
This article explains MyBatis dynamic SQL, covering its purpose, the distinction between static and dynamic SQL, the core SqlNode and SqlSource classes, how MyBatis parses and assembles SQL scripts recursively, and provides concrete code examples to illustrate each step.
MyBatis dynamic SQL is a powerful feature that helps developers build flexible SQL statements based on runtime conditions, avoiding manual string concatenation and common pitfalls such as missing spaces or trailing commas.
The article introduces dynamic SQL, compares it with static SQL, and explains that MyBatis uses two core classes— SqlNode and SqlSource —to parse and assemble statements.
SqlNode encapsulation
SqlNode parses XML mapper files and represents each part of a dynamic statement. For nested dynamic SQL, MyBatis recursively processes nodes. The article provides a detailed example of a select statement with if conditions and shows how SqlNode objects are created.
SQL script classification
MyBatis distinguishes between static SQL (no conditional logic) and dynamic SQL (contains if, foreach, where, trim, etc.). The following code demonstrates a static SQL snippet and highlights how MyBatis treats it as static:
// Select is a query attribute
<select id="selectBypageTwo" resultType="com.wwl.mybatis.dao.User">
// this query selects * from user where id > #{user.id}
select * from user where id > #{user.id}
// if condition makes the SQL dynamic
<if test="user.name != null and user.name!=''">
AND name = #{user.name}
</if>
</select>The article then shows the class hierarchy of SqlNode, including MixedSqlNode (which holds a list of child nodes) and IfSqlNode (which evaluates OGNL expressions to decide whether to apply its child nodes).
public class MixedSqlNode implements SqlNode {
private final List<SqlNode> contents;
public MixedSqlNode(List<SqlNode> contents) { this.contents = contents; }
@Override
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : contents) { sqlNode.apply(context); }
return true;
}
} public class IfSqlNode implements SqlNode {
private final ExpressionEvaluator evaluator;
private final String test;
private final SqlNode contents;
public IfSqlNode(SqlNode contents, String test) {
this.test = test; this.contents = contents; this.evaluator = new ExpressionEvaluator();
}
@Override
public boolean apply(DynamicContext context) {
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
}Dynamic SQL parsing process
When MyBatis needs a BoundSql, it creates a DynamicContext, lets the root SqlNode (often a MixedSqlNode) apply itself, and then uses SqlSourceBuilder to replace #{} placeholders with ? parameters, producing a static SQL ready for JDBC.
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
}The article concludes with a two‑step summary: (1) Dynamic SQL is first transformed into a tree of SqlNode objects during mapper parsing; (2) At execution time, the tree is traversed to generate a concrete SQL string, replace placeholders, and bind parameters.
Despite promotional messages about gifts and community groups, the core content provides a thorough technical walkthrough of MyBatis dynamic SQL, making it valuable for backend developers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
