Resolving MyBatis OGNL Expression Evaluation Errors with Null Source

Problem Description

When executing MyBatis mapper methods, the folowing exception occurs:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: 
Error evaluating expression '_clause.operator.alias'. 
Cause: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, "operator")

The stack trace indicates the error originates from OGNL expression evaluation during SQL parsing:

org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:3226)
org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114)
org.apache.ibatis.scripting.xmltags.TextSqlNode$BindingTokenParser.handleToken(TextSqlNode.java:77)

Code Context

The issue manifests when invoknig repository methods through MyBatis:

humanDataRepository.retrieveHumanNamePage();

Root Cause Analysis

The error occurs due to method name conflicts in MyBatis mapper interfaces. MyBatis uses proxy-based method mapping and does not support Java method overloading in the same way as the JVM. When multiple methods share the same name, MyBatis may incorrectly map to the first occurrence.

In this scenario, three methods with similar names exist in the repository:

List<String> retrieveHumanNamePage();
List<SysHuman> retrieveHumanNamePage(@Param("filter") HumanFilter filter);
List<SysHuman> retrieveHumanNamePage(@Param("clause") SearchClause clause);

MyBatis incorrectly maps to the first method, which contains OGNL expressoins referencing _clause.operator.alias. Since no clause parameter is provided, the expression evaluates against a null source, causing the OGNL exception.

Solution

Two approaches resolve this issue:

1. Distinct Method Names

Use unique method names to avoid conflicts:

List<String> getHumanNames();
List<SysHuman> getHumanPageByFilter(@Param("filter") HumanFilter filter);
List<SysHuman> getHumanPageByClause(@Param("clause") SearchClause clause);

2. Script Tag Wrapping

For methods using OGNL expressions, wrap SQL in <script> tags:

<select id="retrieveHumanNamePage" resultType="string">
    <script>
        SELECT name FROM sys_human WHERE ${_clause.operator.alias}
    </script>
</select>

Important Considerations

Even when the error doesn't occur, incorrect method mapping can lead to unexpected behavior. For example, a method expecting List<SysHuman> might receive List<String> due to Java's type erasure mechanism, which doesn't enforce generic type checking at runtime.

Always verify that MyBatis mapper method names are unique and that return types align with executed SQL statements to prevent subtle runtime issues.

Tags: MyBatis OGNL SQL Mapping Method Overloading Type Erasure

Posted on Sat, 07 Nov 2026 16:31:41 +0000 by 01706