Databases 27 min read

How MyBatis Queries Without Method Implementations – 4 Tricks to Reverse an Interview Rejection

The article explains why MyBatis can execute database queries without concrete method implementations by using JDK dynamic proxies, detailing the roles of MapperProxy, MapperMethod, SqlSession and Executor, and walks through the four‑step process from proxy creation to result mapping.

Tech Freedom Circle
Tech Freedom Circle
Tech Freedom Circle
How MyBatis Queries Without Method Implementations – 4 Tricks to Reverse an Interview Rejection

Basic Usage of MyBatis

MyBatis is a semi‑automatic ORM framework that abstracts JDBC connection handling, SQL execution and result mapping. Developers only need to:

Define a Mapper interface that declares data‑access methods.

Write the corresponding SQL in an XML file or with annotations.

At runtime SqlSession.getMapper() returns a JDK dynamic proxy that implements the interface, so the method can be invoked directly without a manual implementation.

Why the Call Works Without an Implementation

MyBatis creates a JDK dynamic proxy ( MapperProxy ) for the Mapper interface. When a method such as userMapper.selectById(1L) is called, the following steps occur:

Intercept the call – the proxy’s invoke() method intercepts the method invocation.

Locate the SQL – a unique identifier composed of the fully‑qualified interface name and method name (e.g., com.example.UserMapper.selectById) is used to look up the matching <select> element in the XML or annotation.

Parameter conversion and execution – MapperMethod parses the method parameters, injects them into the SQL (e.g., #{id}), and delegates to SqlSession, which forwards the request to the Executor for actual JDBC execution.

Result mapping – after the JDBC ResultSet is returned, MyBatis maps the rows to Java objects based on resultType or a <resultMap>.

Key Components

SqlSessionFactory : builds a singleton SqlSession from configuration files.

SqlSession : represents a database session; provides CRUD APIs and getMapper().

Mapper Interface : declares method signatures; MyBatis generates an implementation at runtime.

XML Mapping File : contains SQL statements bound to method signatures via namespace and id.

MapperProxy : the dynamic‑proxy handler that intercepts interface calls and delegates to MapperMethod.

MapperMethod : encapsulates the SQL command and method signature; decides which SqlSession method (selectOne, insert, update, delete) to invoke.

Executor : the actual execution engine; manages first‑level cache, creates PreparedStatement, executes SQL, and handles transaction boundaries.

Detailed Flow of a Single Query

public interface UserMapper {
    User selectById(Long id);
}
<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectById" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

When userMapper.selectById(1L) is invoked:

Proxy creation : SqlSession.getMapper(UserMapper.class) uses MapperProxyFactory to create a JDK dynamic proxy via Proxy.newProxyInstance.

Method interception : the proxy forwards the call to MapperProxy.invoke. Calls to methods from Object (e.g., toString) are passed through.

MapperMethod resolution : MapperProxy caches or creates a MapperMethod instance that holds the mapped MappedStatement (SQL, command type, result mapping).

Execution : MapperMethod.execute examines the command type (SELECT/INSERT/UPDATE/DELETE) and calls the appropriate SqlSession method (e.g., selectOne).

Executor work : the Executor obtains a PreparedStatement, sets parameters via ParameterHandler, runs the SQL, and obtains a ResultSet.

Result handling : ResultSetHandler (e.g., DefaultResultSetHandler) maps rows to the User object using automatic name‑matching or a defined <resultMap>.

Return : the mapped User instance is returned to the caller through the proxy.

Source Code Highlights

MapperProxy.invoke (simplified) :

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
    }
    MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
}

MapperMethod.execute (simplified decision logic) :

public Object execute(SqlSession sqlSession, Object[] args) {
    switch (command.getType()) {
        case SELECT:
            if (method.returnsMany()) {
                return sqlSession.selectList(command.getName(), args);
            } else if (method.returnsMap()) {
                return sqlSession.selectMap(command.getName(), args);
            } else {
                return sqlSession.selectOne(command.getName(), args);
            }
        case INSERT:
        case UPDATE:
        case DELETE:
            return sqlSession.update(command.getName(), args);
        default:
            throw new BindingException("Unknown execution method for: " + command.getName());
    }
}

Design Trade‑offs

Flexibility vs. Automation : MyBatis gives developers full control over raw SQL (unlike full‑automatic ORMs such as Hibernate) while automating repetitive boilerplate (connection handling, result mapping).

Convention over Configuration : By default the interface name matches the XML namespace and method name matches the id, reducing configuration effort.

Separation of Concerns : Business logic stays in Java interfaces; SQL lives in XML/annotations, making each layer easier to maintain and optimise.

Summary of the Core Stages

Proxy creation – MapperProxyFactory.newInstance generates a JDK dynamic proxy.

SQL location – MappedStatement is retrieved using the fully‑qualified method identifier.

Parameter handling & execution – ParameterHandler sets #{} values; Executor runs the JDBC statement.

Result mapping – ResultSetHandler converts the ResultSet into Java objects.

This chain demonstrates how MyBatis turns a simple interface method call into a complete database operation without requiring a manual DAO implementation.

JavaMyBatisORMDynamic ProxyDatabase AccessSqlSessionMapperProxy
Tech Freedom Circle
Written by

Tech Freedom Circle

Crazy Maker Circle (Tech Freedom Architecture Circle): a community of tech enthusiasts, experts, and high‑performance fans. Many top‑level masters, architects, and hobbyists have achieved tech freedom; another wave of go‑getters are hustling hard toward tech freedom.

0 followers
Reader feedback

How this landed with the community

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.