MyBatis core configuration

Published 2026-07-30 19:27 Updated 2026-10-13 17:14 1020 words 6 min read ... Page views AI-reviewed An AI proof-read this post, but it still deserves a careful read. AI-rewritten Someone else wrote the original; AI helped me rewrite and polish it.

AI-reviewed An AI proof-read this post, but it still deserves a careful read.

This article introduces the core architecture and configuration of MyBatis, including core configuration files, Mapper interface and XML mapping, SQL execution process and result mapping mechanism. It focuses on environment configuration, property file use, SQL parameter placeholder security specifications, usage principles of SqlSessionFactory and SqlSession, and scenario applications of automatic and manual result mapping, and lists troubleshooting methods for common problems.

MyBatis core configuration

The core components of MyBatis

MyBatis projects typically include the following parts:

  • Core configuration files: Configure the runtime environment, data sources, transaction manager and Mapper.
  • Mapper interface: Declare database operation methods.
  • Mapper XML: Write SQL and establish mappings between methods, parameters, and return results.
  • SqlSessionFactory: Create based on configuration SqlSession。
  • SqlSession: Executes SQL, obtains Mapper agents, and manages transactions.

core configuration file

The core configuration file is usually named mybatis-config.xml。The file name can be customized, but the actual file name must be used when reading the configuration.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/book_shop"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapping/BookMapper.xml"/>
    </mappers>
</configuration>

environments Multiple operating environments can be configured,default The value of must be consistent with a environment the id Agreed. The above example selected is mysql Environment.

MyBatis not only reads the core configuration file itself, but also loads external property files, Mapper XML and other resources based on the configuration therein. example,<mapper resource="..."/> This means loading the specified mapping file from the classpath does not mean writing the mapping file content directly into the core configuration file.

Use external properties files

Database connection information is usually placed in db.properties Avoid writing directly in XML.

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/book_shop
jdbc.username=root
jdbc.password=1234

Introduce and use these attributes in the core configuration file:

<configuration>
    <properties resource="db.properties"/>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

Mapper interface

The Mapper interface is used to declare database operations. MyBatis creates proxy objects for interfaces at run time, so handwritten implementation classes are usually not required.

public interface BookMapper {
    List<TbBook> queryAllBook();

    TbBook queryById(Integer id);

    int insertBook(TbBook book);
}

The method name, parameter type, and return type should be consistent with the configuration of the corresponding statement in Mapper XML.

Mapper XML

Mapper XML is responsible for defining SQL and result mappings.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.oracle.dao.BookMapper">
    <select id="queryAllBook" resultType="com.oracle.entity.TbBook">
        SELECT *
        FROM tb_book
    </select>

    <select id="queryById"
            parameterType="java.lang.Integer"
            resultType="com.oracle.entity.TbBook">
        SELECT *
        FROM tb_book
        WHERE id = #{id}
    </select>

    <insert id="insertBook" parameterType="com.oracle.entity.TbBook">
        INSERT INTO tb_book(book_name, author, price)
        VALUES (#{bookName}, #{author}, #{price})
    </insert>
</mapper>

namespace with id

namespace The fully qualified class name of the Mapper interface should be filled in,id Should be consistent with the interface method name. Call this BookMapper.queryAllBook() Only when MyBatis can locate the corresponding SQL statement.

parameter placeholders

#{} Precompiled parameters are used to correctly handle types and reduce SQL injection risks. General business parameters should be used first #{}。

${} It is a direct concatenation of strings and is usually only used in locations where parameter placeholders cannot be used, such as sorted fields that have undergone strict whitelist verification. Don’t put user input directly into ${}。

MyBatis core API

create SqlSessionFactory

SqlSessionFactoryBuilder Create based on configuration SqlSessionFactory。Factory objects are costly to create, and only one is usually created in applications.

public final class MyBatisUtil {
    private static final SqlSessionFactory SQL_SESSION_FACTORY;

    static {
        try (InputStream inputStream =
                     Resources.getResourceAsStream("mybatis-config.xml")) {
            SQL_SESSION_FACTORY =
                    new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private MyBatisUtil() {
    }

    public static SqlSession openSession() {
        return SQL_SESSION_FACTORY.openSession();
    }
}

use SqlSession

SqlSession It is not a thread-safe object and should be created during a business operation and closed in a timely manner. After a write operation is performed, the transaction needs to be committed; an exception should be rolled back.

public class BookService {
    public List<TbBook> queryAllBook() {
        try (SqlSession sqlSession = MyBatisUtil.openSession()) {
            BookMapper mapper = sqlSession.getMapper(BookMapper.class);
            return mapper.queryAllBook();
        }
    }

    public int insertBook(TbBook book) {
        try (SqlSession sqlSession = MyBatisUtil.openSession()) {
            BookMapper mapper = sqlSession.getMapper(BookMapper.class);
            try {
                int rows = mapper.insertBook(book);
                sqlSession.commit();
                return rows;
            } catch (RuntimeException e) {
                sqlSession.rollback();
                throw e;
            }
        }
    }
}

may also be used openSession(true) Turn on automatic commit, but manual commit should be used in businesses that require multiple SQL to remain atomic.

result mapping

automatic mapping

When the column name of the query result is consistent with the Java property name, you can directly use the resultType。

<select id="queryById" resultType="com.oracle.entity.TbBook">
    SELECT id, book_name AS bookName, author, price
    FROM tb_book
    WHERE id = #{id}
</select>

If the underscore to hump configuration is enabled,book_name Can be automatically mapped to bookName。

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

manual mapping

When database column names differ significantly from Java property names, or complex mappings are required, use the resultMap。

<mapper namespace="com.oracle.dao.UserMapper">
    <resultMap id="userMapping" type="com.oracle.entity.User">
        <id property="userId" column="user_id"/>
        <result property="userName" column="user_name"/>
        <result property="realName" column="real_name"/>
        <result property="password" column="password"/>
        <result property="phone" column="phone"/>
        <result property="remain" column="remain"/>
        <result property="operator" column="operator"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="queryUserById" resultMap="userMapping">
        SELECT *
        FROM tb_user
        WHERE user_id = #{id}
    </select>
</mapper>

resultType and resultMap Both are used to describe the returned results, but only one of them is usually selected for the same query. Simple mapping use resultType, used when you need to clearly specify the correspondence between columns and attributes resultMap。

common problems

Unable to find mapping statement

appeared Invalid bound statement When, check in turn:

  • Whether Mapper XML is located in the correct resource directory.
  • Whether the core configuration loads the Mapper.
  • namespace Whether it is the fully qualified class name of the interface.
  • SQL label id Whether it is consistent with the interface method name.
  • Maven builds whether the XML file is copied to the classpath.

The query result attribute is null

Database column names, Java property names, and resultMap Whether it is consistent; when using hump naming, also check mapUnderscoreToCamelCase Whether to open.

The write operation did not take effect

default SqlSession Will not be automatically submitted. After adding, modifying, or deleting, you should call commit(); called when an exception occurs rollback(), and finally close the session.

Written by AI-rewritten

If you enjoyed this, leave a comment~

Loading...