Skip to content

MyBatis

Databases & CachingDatabase/ORMJava

What it is

MyBatis is a persistence framework that simplifies working with relational databases in Java. Unlike full ORM frameworks, it focuses on mapping SQL queries to Java objects, giving developers control over SQL while reducing boilerplate code.

MyBatis allows mapping SQL statements, stored procedures, and results to Java objects. You define mappers via XML or annotations, and the framework handles parameter substitution, result mapping, and caching. It integrates seamlessly with Spring for transaction management.

Installation

Add dependencies in pom.xml: <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.13</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.11</version> </dependency>

Getting started

The smallest useful thing you can do with it, and what each part means.

Simple Mapper XML
<mapper namespace="com.example.UserMapper">
  <select id="getUser" parameterType="int" resultType="User">
    SELECT id, name, email FROM users WHERE id = #{id}
  </select>
</mapper>
Defines an XML mapper to fetch a User object by ID.
Mapper Interface
public interface UserMapper {
    User getUser(int id);
}
Java interface matching the XML mapper to access database methods.

Advanced usage

Where the library earns its place over a simpler alternative.

Annotation-based Mapper
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
    @Select("SELECT id, name, email FROM users WHERE id = #{id}")
    User getUser(int id);
}
Defines the mapper using annotations instead of XML.
Insert and Update
<insert id="insertUser" parameterType="User">
  INSERT INTO users(name, email) VALUES(#{name}, #{email})
</insert>
<update id="updateUser" parameterType="User">
  UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}
</update>
Shows how to insert and update records using MyBatis XML mappers.
Integration with Spring
@Configuration
@MapperScan("com.example.mappers")
public class MyBatisConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        return factoryBean.getObject();
    }
}
Configures MyBatis with Spring Boot and enables automatic mapper scanning.
Result Mapping for Nested Objects
<resultMap id="UserWithAddressMap" type="User">
  <id property="id" column="id" />
  <result property="name" column="name" />
  <association property="address" javaType="Address">
    <id property="id" column="address_id" />
    <result property="city" column="city" />
  </association>
</resultMap>
Maps a nested Address object inside the User object using a resultMap.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

BindingException
Occurs when SQL parameters do not match the mapper method. Verify parameter names and types.
PersistenceException
General database error. Check SQL syntax, connection configuration, and transactions.
TooManyResultsException
Occurs when a query expected a single result but returned multiple. Adjust SQL or resultType accordingly.

Best practices

  • Use XML or annotation mapping consistently throughout the project.
  • Define reusable resultMaps for complex object mappings.
  • Integrate with Spring for transaction management and dependency injection.
  • Use caching wisely to improve performance for frequently accessed data.
  • Write unit tests for mappers with an in-memory database like H2.

Background

Why it exists, and what it was reacting to.

MyBatis was created to provide a flexible persistence framework for Java applications that allows developers to write SQL directly while mapping results to Java objects. It emphasizes simplicity, maintainability, and performance. MyBatis is popular in enterprise applications where complex queries, stored procedures, or fine-grained control over SQL is required.