5.2 Mapper API
Mapper API organizes data access layers using Java interfaces. SQL can be written in method annotations or placed in Mapper XML files.
Choose a Style First
| Your Goal | Recommended Style | Entry |
|---|---|---|
| SQL is short, clearest next to the method | Method annotations | Method Annotations |
| SQL is long, has many dynamic fragments, needs centralized maintenance | Mapper files | Call File Mapper |
| Single-table CRUD, primary-key operations, sample queries | BaseMapper | BaseMapper |
| Conditions are complex but should stay under a Mapper interface | Fluent calls | Call Builder API |
For single-table CRUD, prefer BaseMapper. Mapper API binds interface methods to annotation SQL, XML SQL, BaseMapper, or Fluent capabilities.
Minimal Example
@SimpleMapper
@RefMapper("/mapper/userMapper.xml")
public interface UserMapper {
// Method annotation: SQL written directly on the interface method
@Query("select * from users where email = #{email}")
User selectByEmail(@Param("email") String email);
// Mapper file: SQL written in userMapper.xml, id matches method name
List<User> listByCondition(@Param("name") String name,
@Param("age") Integer age);
}
<mapper namespace="net.example.mapper.UserMapper">
<select id="listByCondition">
select * from users
where 1 = 1
@{and, name like concat('%', #{name}, '%')}
@{and, age = #{age}}
</select>
</mapper>
Session session = config.newSession(dataSource);
UserMapper mapper = session.createMapper(UserMapper.class);
User user = mapper.selectByEmail("alice@example.com");
List<User> users = mapper.listByCondition("alice", 18);
How to obtain a Session depends on your project architecture. See Framework Integration.
Relationship to Other Core APIs
| Capability | How It Appears in Mapper API |
|---|---|
| JdbcTemplate | A Mapper method ultimately executes SQL; you just skip writing template calls manually. |
| Parameter Passing | Mapper method parameters bind to SQL via @Param, Bean, Map, etc. |
| Result Reception | The Mapper method return type determines how results are received — entity, list, page result, or affected rows. |
| Mapper File | @RefMapper maps interface methods to SQL statements in XML. |
| BaseMapper | An interface can extend BaseMapper for common CRUD and still declare annotation or XML methods. |
| Builder API | After extending BaseMapper, default methods can call query(), update(), and other Fluent builders. |
Method Annotations
Method annotations place SQL on Mapper interface methods. They work best when SQL is short and semantically bound to the method name. Callers depend only on the Java interface and never touch JdbcTemplate or Session execution methods directly.
| What You Want to Do | Annotation | Notes |
|---|---|---|
| Query and return results | @Query | Returns entity, collection, page result, etc. |
| Insert data | @Insert | Can work with generated keys or @SelectKeySql for primary key write-back. |
| Update data | @Update | Returns affected rows. |
| Delete data | @Delete | Returns affected rows. |
| Execute arbitrary SQL | @Execute | Suitable for DDL, multiple statements and result sets, not JDBC Batch. |
| Call a stored procedure | @Call | Uses CallableStatement to call procedures or functions. |
| Reuse SQL fragments | @Segment | Defines fragments that can be referenced by rules. |
@SimpleMapper
public interface UserMapper {
@Query("select * from users where id = #{id}")
User selectById(@Param("id") long id);
@Update("update users set name = #{name} where id = #{id}")
int updateName(@Param("id") long id, @Param("name") String name);
}
Annotation SQL supports rules, including conditional concatenation, IN queries, SET fragments, and other dynamic logic. Method parameters can be named with @Param, or passed as Bean/Map. The method return type determines result reception. See Parameter Passing and Result Reception for details.
If SQL is long, has many dynamic fragments, or needs centralized resultMap, entity mapping, and dynamic SQL tags, use Mapper files instead.
Mapper Reads and Writes
BaseMapper<T> auto-generates single-table CRUD SQL from Object Mapping. It is ideal when you don't want to hand-write common CRUD statements. It is usually used as a parent interface for Mapper interfaces, and can also be created directly via session.createBaseMapper(User.class).
BaseMapper depends on Object Mapping to generate SQL. Without entity mapping, use JdbcTemplate or Freedom Map Mode.
| What You Want to Do | Recommended Method |
|---|---|
| Query, delete, or update by primary key | selectById, deleteById, update |
| Insert one or multiple rows | insert |
| Query by sample object | listBySample, countBySample |
| Single-table pagination query | pageBySample |
| Conditions become complex | Switch from mapper.query() or mapper.update() to Call Builder API |
@SimpleMapper
public interface UserMapper extends BaseMapper<User> {
}
UserMapper mapper = session.createMapper(UserMapper.class);
int rows = mapper.insert(user);
User loaded = mapper.selectById(1L);
int updated = mapper.update(user); // Updates non-null fields by primary key
int replaced = mapper.replace(user); // Replaces entire row by primary key, including null fields
int deleted = mapper.deleteById(1L);
User sample = new User();
sample.setStatus("ACTIVE");
List<User> users = mapper.listBySample(sample);
Page page = PageObject.of(0, 20);
PageResult<User> result = mapper.pageBySample(sample, page);
Map<String, OrderType> orderBy = new HashMap<>();
orderBy.put("id", OrderType.DESC);
Map<String, OrderNullsStrategy> nulls = new HashMap<>();
nulls.put("name", OrderNullsStrategy.FIRST);
PageResult<User> result = mapper.pageBySample(sample, page, orderBy, nulls);
update only writes non-null fields; replace means whole-row replacement; upsert means insert if the primary key does not exist, update if it does. For primary key write-back after insert, see @Insert Generated Keys.
Key Strategies
Method annotations can retrieve database-generated keys through useGeneratedKeys, or obtain a key first with selectKey. BaseMapper uses the entity's key generator configuration; declare composite keys by marking multiple fields with primary = true.
Session Management
One Session can create annotation mappers, file mappers, and BaseMapper instances, and expose other APIs through jdbc() and lambda(). They share the Session's configuration and data source; mappings do not need to be registered again.
Session session = configuration.newSession(dataSource);
UserMapper mapper = session.createMapper(UserMapper.class);
BaseMapper<User> baseMapper = session.createBaseMapper(User.class);
Close sessions created by the application after use; leave framework-managed sessions to the integration framework. For transactions, see Cross-API Transactions.
Further Reading
- Method Annotations — Using
@Query,@Insert,@Update,@Delete, etc. to declare SQL on interface methods. - Call File Mapper — How Mapper methods call SQL in XML files.
- Call Builder API — Reusing LambdaTemplate/Fluent capabilities within Mapper interfaces.
- @Insert Generated Keys — Writing back auto-generated primary keys after INSERT.