Implementing Data Queries using the MyBatis Mapper Proxy Pattern
Mapper Interface Definition
To use the proxy mode in MyBatis, define an interface that represents the data access operations. The method signatures defined here will be mapped to SQL statements in the XML configuration.
package org.example.dao;
import org.example.entity.Staff;
import java.util.List;
public interface StaffMapper {
/**
* Retrieves all staff records from the database.
* @return A list containing all Staff objects.
*/
List<Staff> selectAllStaff();
}
XML Mapping Configuration
The XML mapper file must align with the interface to enable automatic proxy generation. Note the following requirements:
- The
namespacemust match the fully qualified name of the Mapper interface. - The
idof the SQL statement must match the method name in the interface. - The result type must correspond to the return type of the method.
- The XML file and the interface should ideally reside in the same directory structure after compilation.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.dao.StaffMapper">
<select id="selectAllStaff" resultType="Staff">
SELECT * FROM staff_info
</select>
</mapper>
Registering the Mapper in Configuration
In the MyBatis core configuraton file (e.g., mybatis-config.xml), register the mapper using the class attribute of the mapper tag to point to the interface.
<mappers>
<mapper class="org.example.dao.StaffMapper"/>
</mappers>
Execution and Testing
The following unit test demonstrates how to obtain the proxy object through SqlSession.getMapper() and execute queries.
package org.example.test;
import org.example.dao.StaffMapper;
import org.example.entity.Staff;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MapperProxyTest {
private SqlSession session;
@Before
public void setup() throws IOException {
InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
this.session = factory.openSession();
}
@Test
public void testFetchAll() {
// MyBatis dynamically creates an implementation of StaffMapper
StaffMapper staffMapper = session.getMapper(StaffMapper.class);
List<Staff> staffList = staffMapper.selectAllStaff();
staffList.forEach(System.out::println);
}
@After
public void teardown() {
if (session != null) {
session.close();
}
}
}
Internal Proxy Mechanism
MyBatis simplifies data access by utilizing the JDK Dynamic Proxy pattern. When calling sqlSession.getMapper(StaffMapper.class), MyBatis generates a proxy object at runtime that implements the specified interface. This proxy intercepts method calls, looks up the corresponding SQL statement in the mappped XML (using the namespace and method ID), eexcutes it via the internal execution engine, and returns the result. This eliminates the need for developers to write boilerplate implementation classes.