Backend Development 27 min read

MyBatis Complete Example and Internal Architecture Overview

This article provides a thorough introduction to MyBatis, including a complete beginner example with database schema, Maven configuration, XML and Java mapper files, and a demo program, followed by an in‑depth explanation of MyBatis’s lifecycle, core components such as SqlSession, Executor, StatementHandler, ParameterHandler, ResultSetHandler, and their interactions.

High Availability Architecture
High Availability Architecture
High Availability Architecture
MyBatis Complete Example and Internal Architecture Overview

This tutorial introduces MyBatis with a step‑by‑step beginner example. It starts by creating a simple user table in MySQL, showing the full CREATE and INSERT statements.

CREATE TABLE IF NOT EXISTS user (
    id BIGINT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Id',
    name VARCHAR(10) NOT NULL DEFAULT '' COMMENT '用户名',
    age INT(3) NOT NULL DEFAULT 0 COMMENT '年龄',
    address VARCHAR(32) NOT NULL DEFAULT '' COMMENT '地址',
    email VARCHAR(32) NOT NULL DEFAULT '' COMMENT '邮件',
    PRIMARY KEY (id)
) COMMENT = '用户表';

INSERT INTO user (name, age, address, email) VALUES ('张三', 18, '北京', '[email protected]');
INSERT INTO user (name, age, address, email) VALUES ('李四', 19, '上海', '[email protected]');

The Maven dependency needed for MyBatis is added to pom.xml :

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

A minimal MyBatis configuration file ( MyBatis-config.xml ) defines the data source and mapper locations:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//Mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/spring_tutorial?serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="Mybatis/mapper/UserMapper.xml"/>
  </mappers>
</configuration>

The mapper XML ( UserMapper.xml ) maps CRUD statements to the user table and links them with a result map that binds columns to the User Java bean:

<mapper namespace="io.github.dunwu.spring.orm.mapper.UserMapper">
  <resultMap id="BaseResultMap" type="io.github.dunwu.spring.orm.entity.User">
    <id column="id" jdbcType="BIGINT" property="id"/>
    <result column="name" jdbcType="VARCHAR" property="name"/>
    <result column="age" jdbcType="INTEGER" property="age"/>
    <result column="address" jdbcType="VARCHAR" property="address"/>
    <result column="email" jdbcType="VARCHAR" property="email"/>
  </resultMap>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    SELECT id, name, age, address, email FROM user WHERE id = #{id,jdbcType=BIGINT}
  </select>
  <insert id="insert" parameterType="io.github.dunwu.spring.orm.entity.User">
    INSERT INTO user (id, name, age, address, email) VALUES (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, #{address,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR})
  </insert>
  <update id="updateByPrimaryKey" parameterType="io.github.dunwu.spring.orm.entity.User">
    UPDATE user SET name = #{name,jdbcType=VARCHAR}, age = #{age,jdbcType=INTEGER}, address = #{address,jdbcType=VARCHAR}, email = #{email,jdbcType=VARCHAR} WHERE id = #{id,jdbcType=BIGINT}
  </update>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    DELETE FROM user WHERE id = #{id,jdbcType=BIGINT}
  </delete>
</mapper>

The corresponding Java mapper interface ( UserMapper.java ) declares the same methods without implementation:

public interface UserMapper {
    int deleteByPrimaryKey(Long id);
    int insert(User record);
    User selectByPrimaryKey(Long id);
    List
selectAll();
    int updateByPrimaryKey(User record);
}

The User entity class simply holds the fields that match the table columns:

public class User {
    private Long id;
    private String name;
    private Integer age;
    private String address;
    private String email;
}

A test program ( MyBatisDemo.java ) demonstrates how to load the configuration, obtain a SqlSession , and execute a mapper method:

public class MyBatisDemo {
    public static void main(String[] args) throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("MyBatis/MyBatis-config.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        try (SqlSession sqlSession = factory.openSession()) {
            Long params = 1L;
            List
list = sqlSession.selectList("io.github.dunwu.spring.orm.mapper.UserMapper.selectByPrimaryKey", params);
            for (User user : list) {
                System.out.println("user name: " + user.getName());
            }
        }
    }
}

The article then explains MyBatis’s internal lifecycle. It describes how SqlSessionFactoryBuilder creates a SqlSessionFactory , which in turn creates SqlSession instances. Each SqlSession delegates SQL execution to an Executor , which generates dynamic SQL (via BoundSql ), manages caching (first‑level and optional second‑level), and obtains a StatementHandler to interact with JDBC.

The Executor workflow is detailed: it creates a cache key, checks the local cache, and if a miss occurs, calls queryFromDatabase , which ultimately invokes StatementHandler.prepare , StatementHandler.parameterize (using ParameterHandler to set PreparedStatement parameters), and StatementHandler.query (which uses ResultSetHandler to map the ResultSet to Java objects via the defined ResultMap ).

Key sub‑components are summarized:

Executor : Generates SQL, handles caching, and orchestrates the query.

StatementHandler : Creates the JDBC Statement , sets parameters, and executes the query.

ParameterHandler : Converts Java parameters to JDBC types and binds them to the statement.

ResultSetHandler : Converts the JDBC ResultSet into a list of mapped Java objects.

TypeHandler : Bridges Java types and JDBC types.

Finally, the article lists reference resources, including official MyBatis repositories, integration guides for Spring and Spring Boot, and popular extensions such as MyBatis‑Plus, Mapper, and PageHelper.

BackendJavaSQLDatabaseMyBatisORMExecutorMapper
High Availability Architecture
Written by

High Availability Architecture

Official account for High Availability Architecture.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.