On this page
MyBatis Basics
MyBatis is a persistence framework that maps SQL statements to Java methods. Unlike JPA/Hibernate, you write the SQL yourself, giving full control over queries.
MyBatis vs JPA
| Aspect | MyBatis | JPA/Hibernate |
|---|---|---|
| SQL control | Full (you write SQL) | Generated by ORM |
| Learning curve | Lower | Higher |
| Complex queries | Excellent | Good (JPQL/Criteria) |
| Object mapping | Manual or auto | Automatic |
| Best for | SQL-heavy apps, legacy DBs | Domain-driven design |
Setup
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.model
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
Mapper Interface
@Mapper
public interface UserMapper {
User findById(@Param("id") Long id);
List<User> findAll();
int insert(User user);
int update(User user);
int deleteById(@Param("id") Long id);
}
XML Mapper
src/main/resources/mapper/UserMapper.xml:
<?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="com.example.mapper.UserMapper">
<resultMap id="UserResultMap" type="User">
<id property="id" column="id"/>
<result property="email" column="email"/>
<result property="name" column="name"/>
<result property="createdAt" column="created_at"/>
</resultMap>
<select id="findById" resultMap="UserResultMap">
SELECT id, email, name, created_at FROM users WHERE id = #{id}
</select>
<select id="findAll" resultMap="UserResultMap">
SELECT id, email, name, created_at FROM users ORDER BY id
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (email, name, created_at)
VALUES (#{email}, #{name}, #{createdAt})
</insert>
<update id="update">
UPDATE users SET email = #{email}, name = #{name} WHERE id = #{id}
</update>
<delete id="deleteById">
DELETE FROM users WHERE id = #{id}
</delete>
</mapper>
Annotation-Based Mapper
For simple queries, skip XML:
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO users (email, name) VALUES (#{email}, #{name})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("UPDATE users SET name = #{name} WHERE id = #{id}")
int update(User user);
@Delete("DELETE FROM users WHERE id = #{id}")
int deleteById(Long id);
}
Using the Mapper
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User getUser(Long id) {
return userMapper.findById(id);
}
@Transactional
public User createUser(CreateUserRequest request) {
User user = new User(request.getEmail(), request.getName());
userMapper.insert(user);
return user;
}
}
SqlSession Lifecycle
MyBatis-Spring manages SqlSession automatically:
@Mapper interface → MyBatis proxy → SqlSession → JDBC Connection
No manual session management needed with Spring Boot integration.
Best Practices
- Use
map-underscore-to-camel-case: truefor automatic column mapping - Keep complex SQL in XML; use annotations for simple CRUD
- Use
@Paramwhen a method has multiple parameters - Enable SQL logging in development for debugging
- Combine with PageHelper for pagination