mybatis/mybatis-3 · error · SQLException
SqlRunner requires an instance of Null to represent typed nu
Error message
SqlRunner requires an instance of Null to represent typed null values for JDBC compatibility
What it means
SqlRunner.setParameters() throws SQLException when a raw null appears in the argument list. JDBC drivers need a concrete jdbcType to set NULL, and SqlRunner has no annotation/XML to read it from, so you must pass the sentinel object org.apache.ibatis.jdbc.SqlRunner.Null (e.g. SqlRunner.NULL) which carries a TypeHandler and jdbcType.
Source
Thrown at src/main/java/org/apache/ibatis/jdbc/SqlRunner.java:219
}
}
/**
* @deprecated Since 3.5.4, this method is deprecated. Please close the {@link Connection} outside of this class.
*/
@Deprecated
public void closeConnection() {
try {
connection.close();
} catch (SQLException e) {
// ignore
}
}
private void setParameters(PreparedStatement ps, Object... args) throws SQLException {
for (int i = 0, n = args.length; i < n; i++) {
if (args[i] == null) {
throw new SQLException(
"SqlRunner requires an instance of Null to represent typed null values for JDBC compatibility");
}
if (args[i] instanceof Null) {
((Null) args[i]).getTypeHandler().setParameter(ps, i + 1, null, ((Null) args[i]).getJdbcType());
} else {
TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(args[i].getClass());
if (typeHandler == null) {
throw new SQLException("SqlRunner could not find a TypeHandler instance for " + args[i].getClass());
} else {
typeHandler.setParameter(ps, i + 1, args[i], null);
}
}
}
}
private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException {
List<Map<String, Object>> list = new ArrayList<>();
List<String> columns = new ArrayList<>();View on GitHub (pinned to 008069adb1)
Solutions
- Replace the null argument with SqlRunner.NULL (VARCHAR) or new Null(JdbcType.NUMERIC) / other jdbc types as appropriate.
- Where possible, avoid binding null by skipping the column from the INSERT statement.
- Wrap nullable values at the call site: value == null ? SqlRunner.NULL : value.
Example fix
// before
runner.update("update users set nickname=? where id=?", null, 42);
// after
runner.update("update users set nickname=? where id=?", SqlRunner.NULL, 42); Defensive patterns
Strategy: validation
Validate before calling
// Wrap nullable values before passing to SqlRunner
Object safe(Object v) {
return v == null ? SqlRunner.NULL : v;
}
runner.update("update users set nickname=? where id=?", safe(nickname), 42); Prevention
- Never pass raw null literals to SqlRunner varargs; use SqlRunner.NULL or new Null(JdbcType.X).
- Pick the Null matching the column's JDBC type (e.g. Null.NUMERIC for numeric columns) to avoid driver-side type errors.
- Remember SqlRunner is a test/utility class — production code should use mapper interfaces where jdbcType comes from XML.
When it happens
Trigger: Calling sqlRunner.update/insert/select with a plain Java null argument: runner.update("update users set nickname=? where id=?", null, 1). Any null literal, null-valued variable, or uninitialized field passed as a vararg triggers it.
Common situations: Test fixtures inserting rows with nullable columns; passing a nullable POJO getter result directly; forgetting that SqlRunner's API differs from PreparedStatement.setNull(i, type).
Related errors
- SqlRunner could not find a TypeHandler instance for {}
- Error accessing PooledConnection. Connection is invalid.
- Error getting constructor collection nested result map value
- Error getting nested result map values for '{}'. Cause: {}
- Error preparing statement. Cause: {}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/ad9a5572c8e25f4e.
Report an issue: GitHub.