MyBatis 核心配置

发布于 2026-07-30 19:27 更新于 2026-07-30 19:27 1275 字 7 min read ... 访问量

本文介绍了 MyBatis 的核心架构与配置,包括核心配置文件、Mapper 接口与 XML、SqlSessionFactory 和 SqlSession 的使用,强调了环境配置、属性文件分离、SQL 映射与结果处理的规范。同时指出常见问题如映射语句找不到、结果为 null 或写操作无效的原因及解决方案,确保开发中正确配置与使用 MyBatis 的各个组件。

MyBatis 核心配置

MyBatis 的核心组成

MyBatis 项目通常包含以下几部分:

  • 核心配置文件:配置运行环境、数据源、事务管理器和 Mapper。
  • Mapper 接口:声明数据库操作方法。
  • Mapper XML:编写 SQL,并建立方法、参数和返回结果之间的映射。
  • SqlSessionFactory:根据配置创建 SqlSession
  • SqlSession:执行 SQL、获取 Mapper 代理并管理事务。

核心配置文件

核心配置文件通常命名为 mybatis-config.xml。文件名可以自定义,但读取配置时必须使用实际文件名。

<?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 可以配置多个运行环境,default 的值必须与某个 environmentid 一致。上例选择的是 mysql 环境。

MyBatis 不仅会读取核心配置文件本身,还会根据其中的配置加载外部属性文件、Mapper XML 等资源。例如,<mapper resource="..."/> 表示从类路径加载指定的映射文件,并不是把映射文件内容直接写进核心配置文件。

使用外部属性文件

数据库连接信息通常放在 db.properties 中,避免直接写在 XML 里。

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

在核心配置文件中引入并使用这些属性:

<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 接口

Mapper 接口用于声明数据库操作。MyBatis 会在运行时为接口创建代理对象,因此通常不需要手写实现类。

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

    TbBook queryById(Integer id);

    int insertBook(TbBook book);
}

方法名、参数类型和返回类型应与 Mapper XML 中对应语句的配置保持一致。

Mapper XML

Mapper XML 负责定义 SQL 和结果映射。

<?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>

namespaceid

namespace 应填写 Mapper 接口的全限定类名,id 应与接口方法名一致。这样调用 BookMapper.queryAllBook() 时,MyBatis 才能定位到对应的 SQL 语句。

参数占位符

#{} 会使用预编译参数,能够正确处理类型并降低 SQL 注入风险。普通业务参数应优先使用 #{}

${} 是字符串直接拼接,通常只用于无法使用参数占位符的位置,例如经过严格白名单校验的排序字段。不要直接把用户输入放入 ${}

MyBatis 核心 API

创建 SqlSessionFactory

SqlSessionFactoryBuilder 根据配置创建 SqlSessionFactory。工厂对象创建成本较高,应用中通常只创建一个。

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();
    }
}

使用 SqlSession

SqlSession 不是线程安全对象,应在一次业务操作中创建并及时关闭。执行写操作后,需要提交事务;出现异常时应回滚。

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;
            }
        }
    }
}

也可以使用 openSession(true) 开启自动提交,但在需要多个 SQL 保持原子性的业务中,应使用手动提交。

结果映射

自动映射

当查询结果的列名与 Java 属性名一致时,可以直接使用 resultType

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

如果启用了下划线转驼峰配置,book_name 可以自动映射到 bookName

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

手动映射

当数据库列名与 Java 属性名差异较大,或需要复杂映射时,应使用 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>

resultTyperesultMap 都用于描述返回结果,但同一个查询通常只选择其中一种。简单映射使用 resultType,需要明确指定列与属性对应关系时使用 resultMap

常见问题

找不到映射语句

出现 Invalid bound statement 时,应依次检查:

  • Mapper XML 是否位于正确的资源目录。
  • 核心配置是否加载了该 Mapper。
  • namespace 是否为接口的全限定类名。
  • SQL 标签的 id 是否与接口方法名一致。
  • Maven 构建是否把 XML 文件复制到了类路径。

查询结果属性为 null

应检查数据库列名、Java 属性名和 resultMap 是否一致;使用驼峰命名时,还要检查 mapUnderscoreToCamelCase 是否开启。

写操作没有生效

默认 SqlSession 不会自动提交。执行新增、修改或删除后,应调用 commit();出现异常时调用 rollback(),最后关闭会话。

喜欢的话,留下你的评论吧~

... 访问量
© 2026 跨越星轨的客 @Hoshiumi
Powered by theme astro-koharu · Inspired by Shoka