Backend Development 8 min read

Why System.out.println() Can Kill Your MyBatis Performance and How to Fix It

This article explains why MyBatis's default StdOutImpl logging, which relies on System.out.println, blocks threads and creates severe concurrency bottlenecks, and demonstrates how to replace it with asynchronous logging implementations like Slf4jImpl, configure log levels, and even create custom Log classes for optimal performance.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Why System.out.println() Can Kill Your MyBatis Performance and How to Fix It

When using MyBatis or its derivatives, we often enable the default log output to troubleshoot issues via SQL logs. However, MyBatis logs lack timestamps, levels, and are left‑aligned because they use a class called

StdOutImpl

that prints directly to

System.out.println()

.

Printing with

System.out.println()

blocks the current thread, causing SQL queries to wait for the log output to finish before returning results. This is why most articles recommend using a Log implementation instead of

System.out.println()

, as Log is asynchronous.

Worse Situation

Slow interface responses and high CPU usage can make the system almost unusable. Using

jstack

may reveal many web threads waiting to acquire the lock on

java.io.PrintStream

. The

println()

method synchronizes on the global

System.out

PrintStream, causing all threads to queue their SQL logs, leading to severe concurrency performance problems, especially with bulk inserts or data exports.

How to Optimize

Built‑in Log Implementations

MyBatis provides other logging implementations. Replacing

StdOutImpl

with

Slf4jImpl

solves the performance issue and allows unified formatting and output locations.

<code>&lt;configuration&gt;
  &lt;settings&gt;
    &lt;setting name="logImpl" value="SLF4J"/&gt;
  &lt;/settings&gt;
&lt;/configuration&gt;</code>

For MyBatis‑Plus:

<code>mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl</code>

For MyBatis Flex:

<code>@Configuration
public class MyBatisFlexConfig implements ConfigurationCustomizer {
    @Override
    public void customize(FlexConfiguration config) {
        // Use Slf4j for logging
        config.setLogImpl(Slf4jImpl.class);
    }
}</code>

Note that the MyBatis

Log

interface does not define an

info

level; it only provides

debug

,

trace

,

warn

, and

error

methods. To enable detailed logging, configure the logger level (e.g., TRACE) in your logging framework.

Custom Log Implementation

You can implement your own Log that outputs at the

info

level:

<code>public class MyBatisLogImpl implements Log {
    private final Logger log;
    public MyBatisLogImpl(String clazz) {
        log = LoggerFactory.getLogger(clazz);
        System.out.println(clazz);
    }
    @Override public boolean isDebugEnabled() { return true; }
    @Override public boolean isTraceEnabled() { return true; }
    @Override public void error(String s, Throwable e) { log.error(s, e); }
    @Override public void error(String s) { log.error(s); }
    @Override public void debug(String s) { log.info(s); }
    @Override public void trace(String s) { log.info(s); }
    @Override public void warn(String s) { log.warn(s); }
}</code>

MyBatis also logs some debug messages that are often unnecessary, such as session creation logs. These can be filtered out in the logging configuration, for example:

<code>&lt;!-- Exclude all logs from SqlSessionUtils --&gt;
&lt;logger name="org.mybatis.spring.SqlSessionUtils" level="OFF"/&gt;</code>

Conclusion

System.out.println()

is a far worse logging method than expected; it should be avoided not only in MyBatis (where

StdOutImpl

uses it) but in any system. Relying on unformatted

System.out

output can cause thread blocking and severe concurrency performance degradation.

JavaperformanceconcurrencyloggingMyBatisSlf4jSystem.out.println
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.