MyBatis

Language: Java

Database/ORM

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.

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.

Installation

maven: 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>
gradle: Add dependencies in build.gradle: implementation 'org.mybatis:mybatis:3.5.13' implementation 'org.mybatis:mybatis-spring:2.0.11'

Usage

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.

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.

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.

Error Handling

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.