MyBatis Boolean vs Boolean: Unexpected 0 Value and Fix
Because MyBatis reads a primitive boolean field directly when no getter exists, the default false value is bound as 0, causing an unexpected zero in the MySQL tinyint column; changing the field to the Boolean wrapper (initialized to true) or fixing the update logic resolves the issue.
During a feature implementation a new MySQL column is_has_messages (unsigned tinyint, default 1) was added to record whether a session has messages. The corresponding POJO field was declared as private boolean hasMessages; following the Alibaba coding guidelines that forbid the is prefix on boolean variables.
After inserting a record the column unexpectedly stored 0 instead of 1. Debugging revealed that MyBatis looks for a getter named getHasMessages() or a field named hasMessages. Because no getter exists, MyBatis reads the primitive field directly, whose default value is false, resulting in 0 in the database.
The SQL logged by a custom interceptor ( @Intercepts on StatementHandler.prepare) shows the placeholder #{hasMessages} being bound to the primitive value:
@Slf4j
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyBatisSqlInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler sh = (StatementHandler) invocation.getTarget();
String sql = sh.getBoundSql().getSql();
Object param = sh.getBoundSql().getParameterObject();
log.info("Executing SQL: {}", sql);
log.info("Parameters: {}", param);
return invocation.proceed();
}
// plugin and setProperties omitted for brevity
}The relevant part of MyBatis' DefaultParameterHandler extracts the property value:
public void setParameters(PreparedStatement ps) {
List<ParameterMapping> mappings = boundSql.getParameterMappings();
for (int i = 0; i < mappings.size(); i++) {
ParameterMapping pm = mappings.get(i);
String prop = pm.getProperty();
Object value = metaObject.getValue(prop);
TypeHandler handler = pm.getTypeHandler();
handler.setParameter(ps, i + 1, value, pm.getJdbcType());
}
}Because the primitive boolean defaults to false, the bound value becomes 0. Moreover, a later xxxTalk update operation overwrites the column to 0 when the POJO field is still false.
Fixes:
Change the field type to Boolean and initialise it to Boolean.TRUE, ensuring the default value is 1 when not explicitly set.
Or adjust the update logic so that it does not reset the column unintentionally.
Final POJO snippet: private Boolean hasMessages = Boolean.TRUE; This change makes MyBatis bind 1 correctly and resolves the intermittent “0” values observed during inserts and updates.
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.
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.
