﻿---
title: Apache MyBatis
date: 2024-07-20
excerpt: MyBatis notes from the Heima Programmer Java Web course, covering core concepts and a Spring Boot CRUD demo.
tags: [Java, MyBatis, Apache]
thumbnail: https://assets.vluv.space/cover/Dev/Java/mybatis.webp
cover: https://assets.vluv.space/cover/Dev/Java/mybatis.webp
updated: 2026-07-08 21:21:59
lang: en
i18n:
  cn: /MyBatis
  translation: 2
---

<script type="module" src="/js/components/tab.js"></script>

## Introduction

- MyBatis is a persistence framework that simplifies the interaction between Java programs and databases. Compared to traditional JDBC (Java Database Connectivity), MyBatis configures and maps SQL statements via XML or annotations, greatly reducing boilerplate code.
- MyBatis was originally an Apache open-source project named iBatis. In 2010 the project moved from Apache to Google Code and was renamed MyBatis. In November 2013 it migrated to GitHub.

> **JDBC (Java DataBase Connectivity)**
>
> JDBC is the Java API for database connectivity, released in 1997 by Sun Microsystems (now part of Oracle Corporation). JDBC defines a standard that allows Java programs to interact with many relational databases. It provides a set of interfaces and classes for sending SQL statements and processing results. A JDBC driver is a Java class library implementing the JDBC interfaces for a specific DBMS; Java programs communicate with the DBMS through the driver.
>
> **Persistence Framework**
>
> In computing a **persistence framework** is middleware that assists in the storage and retrieval of information between applications and databases, especially relational databases. It acts as a layer of abstraction for persisted data, bridging conceptual and technical differences between storage and utilisation.
> Many persistence frameworks are also **object-relational mapping** (ORM) tools (e.g. Hibernate, MyBatis SQL Maps, Apache Cayenne, Entity Framework, Slick, and Java Ultra-Lite Persistence). Such frameworks map the objects in the application domain to data that needs to be persisted in a database. The mappings can be defined using either XML files or metadata annotations.
>
> Object-Relational Mapping (ORM, or O/RM, or O/R mapping) is a programming technique for converting data between incompatible type systems in object-oriented programming languages. Object orientation grew out of software engineering principles (coupling, aggregation, encapsulation), while relational databases grew out of mathematical theory. The two theories differ significantly, and ORM emerged to resolve this mismatch.
>
> **Comparison with other persistence-layer technologies**
>
> - JDBC
>   - SQL mixed into Java code creates tight coupling and hard-coding problems;
>   - Hard to maintain; in real projects SQL changes often and must be modified frequently;
>   - Verbose code, low development efficiency;
> - Hibernate and JPA
>   - Easy to use, high development efficiency;
>   - Long, complex SQL in a program has to bypass the framework;
>   - The internally generated SQL is hard to optimize for special cases;
>   - As fully mapped, fully automatic frameworks, partial mapping of POJOs with many fields is difficult;
>   - Heavy use of reflection hurts database performance;
> - MyBatis
>   - Lightweight, with excellent performance;
>   - SQL and Java code are separated, with clear boundaries: Java code focuses on business logic, SQL focuses on data;
>   - Development efficiency is slightly behind Hibernate, but entirely acceptable;
>
> Development efficiency: `Hibernate > Mybatis > JDBC`;
> Runtime efficiency: `JDBC > Mybatis > Hibernate`;
>
> **Why is MyBatis called a semi-automatic ORM tool? How does it differ from fully automatic ones?**
>
> Hibernate is a fully automatic ORM tool: when querying associated objects or associated collections with Hibernate, you can fetch them directly through the object-relational model, hence "fully automatic". MyBatis, in contrast, offers a flexible, semi-automatic way to handle database operations. Unlike fully automatic ORM frameworks, MyBatis emphasizes SQL control: developers write the SQL themselves and gain better performance and flexibility in return.

The core strengths of MyBatis:

- SQL Control: you fully control how SQL statements are written and executed, avoiding the complexity of ORM frameworks, especially when you need to optimize queries.
- Dynamic SQL Support: MyBatis provides very powerful dynamic SQL. Developers can flexibly generate different SQL statements based on business logic, without the pain of concatenating SQL strings.
- Lightweight: MyBatis is lightweight and easy to integrate, without pulling in as many dependencies as some heavier ORM frameworks.
- Simplified Mapping: through XML configuration or annotations, you can easily map database table columns to Java object properties.

### MyBatis Core Concepts

- `SqlSessionFactory` is the core entry point of MyBatis; every MyBatis application is built around a SqlSessionFactory instance. It is created by reading a configuration file. From the SqlSessionFactory you obtain a SqlSession to perform database operations.
- `SqlSession` is similar to JDBC's `Statement` object and provides the methods for interacting with the database. Through a SqlSession you can run CRUD operations, commit transactions, close connections, and so on. Each session is isolated from the others.
- `Mapper Interface` is another convenient way MyBatis offers to operate on database tables. You define an interface for the operations on a table, with each method mapped to a SQL statement. For example, a UserMapper interface might have a method `getUserById()` corresponding to the SQL `SELECT * FROM user WHERE id = ?`.
- `Dynamic SQL` is a powerful MyBatis feature that lets you use conditional statements (such as `if, choose, where`) and loops (`foreach`) in SQL. Dynamic SQL improves flexibility, especially for complex query conditions, generating SQL statements dynamically based on the conditions.
- `Result Mapping` maps database columns in a query result to the properties of a Java object. The mapping can be defined via XML configuration or annotations.

## CRUD Demo

Suppose we have a `User` table with columns id, name, and age.

```sql
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT
);
```

<x-tabs>

<x-tab title="Project Structure" active>

In this project structure, we use Spring Boot's typical layered architecture to organize the MyBatis CRUD operations:

`Model Layer`: defines the User entity class.
`Mapper Layer`: defines database operations through the UserMapper interface, with SQL configured in UserMapper.xml.
`Service Layer`: wraps business logic in the UserService class.
`Controller Layer`: UserController receives HTTP requests and calls UserService to run the corresponding database operations.

```nu
src/
 └── main/
     ├── java/
     │    └── com/
     │        └── example/
     │            └── mybatisdemo/
     │                 ├── controller/
     │                 │    └── UserController.java
     │                 ├── mapper/
     │                 │    └── UserMapper.java
     │                 ├── model/
     │                 │    └── User.java
     │                 └── service/
     │                      └── UserService.java
     └── resources/
          ├── application.yml
          └── mapper/
               └── UserMapper.xml
```

```yml
# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_demo
    username: root
    password: root_password
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.mybatisdemo.model
```

</x-tab>

<x-tab title="Model">

```java
package com.example.mybatisdemo.model;

public class User {
    private int id;
    private String name;
    private int age;

    // Getters and Setters
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}
```

</x-tab>

<x-tab title="Service">

```java
package com.example.mybatisdemo.service;

import com.example.mybatisdemo.mapper.UserMapper;
import com.example.mybatisdemo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public int createUser(User user) {
        return userMapper.insertUser(user);
    }

    public User getUserById(int id) {
        return userMapper.getUserById(id);
    }

    public int updateUser(User user) {
        return userMapper.updateUser(user);
    }

    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }
}
```

</x-tab>

<x-tab title="Mapper">

```java
package com.example.mybatisdemo.mapper;

import com.example.mybatisdemo.model.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {

    // Insert a user record
    int insertUser(User user);

    // Query by user ID
    // In the `xml` file, write the corresponding SQL statement, e.g.
    // <select id = "getUserById" resultType = "User">
    //     select * from user where id = #{id}
    // </select>
    User getUserById(int id);

    // Update user info
    int updateUser(User user);

    // Delete by user ID
    int deleteUser(int id);
}
```

</x-tab>

<x-tab title="Controller">

```java
package com.example.mybatisdemo.controller;

import com.example.mybatisdemo.model.User;
import com.example.mybatisdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    // Create a user
    @PostMapping
    public String createUser(@RequestBody User user) {
        userService.createUser(user);
        return "User created successfully";
    }

    // Query a user by ID
    @GetMapping("/{id}")
    public User getUserById(@PathVariable int id) {
        return userService.getUserById(id);
    }

    // Update a user
    @PutMapping("/{id}")
    public String updateUser(@PathVariable int id, @RequestBody User user) {
        user.setId(id);
        userService.updateUser(user);
        return "User updated successfully";
    }

    // Delete a user
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable int id) {
        userService.deleteUser(id);
        return "User deleted successfully";
    }
}
```

</x-tab>

</x-tabs>

## More

[MyBatis Interview Questions Summary](https://javaguide.cn/system-design/framework/mybatis/mybatis-interview.html)
[Object-Relational Mapping](https://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1%E5%85%B3%E7%B3%BB%E6%98%A0%E5%B0%84)
