java框架之MyBatis(1)-入门&动态代理开发

时间:2023-03-08 16:08:17

前言

学MyBatis的原因

1、目前最主流的持久层框架为 Hibernate 与 MyBatis,而且国内公司目前使用 Mybatis 的要比 Hibernate 要多。

2、Hibernate 学习门槛不低,且精通门槛更高。门槛高在如何设计 O/R 映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好 Hibernate 缓存与数据加载策略方面需要经验和能力都很强才行。

3、SQL 优化方面,Hibernate 的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然,Hibernate 也可以自己写 SQL 来指定需要查询的字段,但这样就破坏了 Hibernate 开发的间接性。说得更深入一点,如果有个查询要关联多张表,而且我们要取的只是几张表中的部分字段。这时用 Hibernate 就会有些力不从心,就算用 Hibernate 的 SQLQuery,后续的维护工作也会很麻烦。

JDBC存在的问题

可以先回顾一下 JDBC 的使用

1、频繁创建和打开、关闭数据库连接,太消耗资源。

2、SQL 语句及参数存在硬编码,不利于维护。

3、结果集获取与封装复杂,存在硬编码,不利于维护。

入门

介绍

MyBatis 本是 apache 的一个开源项目 iBatis,2010 年这个项目由 Apache software foundation 迁移到了 Google code,并改名为 iBatis。2013 年 11 月迁移到 Github。

MyBatis 是面向 SQL 的持久层框架,它封装了 jdbc 访问数据库的过程,我们开发时,只需要专注于 SQL 语句本身的拼装,其它复杂的过程全部可以交给 MyBatis 去完成。

更多可参考官方文档

入门程序

搭建

1、创建 maven java 工程,引入以下依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zze</groupId>
    <artifactId>mybatis_test1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.0-rc1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

pom.xml

2、创建 jdbc 连接属性文件:

jdbc.url=jdbc:mysql://192.168.208.192:3306/test?characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

jdbc.properties

3、创建与数据库表对应的 pojo:

package com.zze.mybatis.pojo;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Date birthday;
    private String uuid;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

com.zze.mybatis.pojo.User

4、创建 pojo 对应映射文件:

<?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="user">

</mapper>

mybatis/mapper/User.xml

5、创建 MyBatis 核心配置文件:

<?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>
    <!-- 加载属性文件 -->
    <properties resource="jdbc.properties"/>
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <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>
    <!-- 加载映射文件 -->
    <mappers>
        <mapper resource="mybatis/mapper/User.xml"/>
    </mappers>
</configuration>

mybatis/SqlMapConfig.xml

6、创建 log4j 属性文件:

log4j.rootLogger = debug,stdout,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j.properties

测试

1、抽取工具类:

package com.zze.mybatis.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        // 创建 SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建核心配置文件的输入流
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建 Session 工厂
        sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }

    /**
     * 打开一个 Session
     *
     * @return SqlSession 实例
     */
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession();
    }

    /**
     * 打开一个 Session
     *
     * @param autoCommit 是否自动提交事务
     * @return SqlSession 实例
     */
    public static SqlSession openSession(Boolean autoCommit) {
        return sqlSessionFactory.openSession(autoCommit);
    }
}

com.zze.mybatis.util.SqlSessionFactoryUtil

2、修改映射文件:

<?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="user">
    <!--
     新增操作
        parameterType : 参数类型
            selectKey 配置主键返回
                keyProperty : 主键属性
                resultType : 主键数据类型
                order : 指定 selectKey 何时执行
     -->
    <insert id="add1" parameterType="com.zze.mybatis.pojo.User">

        <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID();
        </selectKey>
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>
    <!--
    新增操作
        useGeneratedKeys : 使用自增
        keyProperty : 指定主键属性,与 useGeneratedKeys 搭配使用
        用这两个属性相当于 add1 中使用 selectKey
    -->
    <insert id="add2" parameterType="com.zze.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>

    <!--
    新增操作
    在真正执行插入操作之前生成一个 uuid 赋值给指定属性
    -->
    <insert id="add3" parameterType="com.zze.mybatis.pojo.User">
        <selectKey keyProperty="uuid" resultType="string" order="BEFORE">
            select UUID();
        </selectKey>
        INSERT INTO user(name,age,birthday,uuid) VALUES(#{name},#{age},#{birthday},#{uuid});
    </insert>

    <!--
    更新操作
    -->
    <update id="update" parameterType="com.zze.mybatis.pojo.User">
        UPDATE user SET name=#{name},age=#{age},birthday=#{birthday} WHERE id=#{id};
    </update>
    <!--
    获取单个对象
    -->
    <select id="getById" parameterType="int" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where id=#{id};
    </select>

    <!--
    根据名字模糊查询方式一
         #{} 方式相当于 jdbc 的 ? 占位符方式
         当传入参数为基础类型,使用 #{任意变量名},来引用传入的参数
    -->
    <select id="getByName1" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like #{name};
    </select>

    <!--
    根据名字模糊查询方式二
         该方式为字符串拼接
         当传入的参数为基础类型时,只可以使用 ${value} 来引用传入参数
         当传入的参数为 POJO 时,直接使用${属性名}
    -->
    <select id="getByName2" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like '%${value}%';
    </select>

    <!--
    查询所有
    -->
    <select id="getAll" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user
    </select>
    <!--
    删除操作
    -->
    <delete id="deleteById" parameterType="int">
        DELETE FROM user WHERE id=#{id}
    </delete>
</mapper>

mybatis/mapper/User.xml

3、编写测试类测试:

package com.zze.mybatis.test;

import com.zze.mybatis.pojo.User;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class MyBatisTest {

    /**
     * 新增操作
     */
    @Test
    public void testAdd() throws Exception {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        // 要新增的对象
        User user = new User();
        user.setName("张三");
        user.setAge(19);
        Date birthday = new SimpleDateFormat("yyyy-MM-dd").parse("1998-1-1");
        user.setBirthday(birthday);
        // 执行新增操作
        // 第一个参数为映射文件中的 sql id
        // 第二个参数为要传入 sql 中的参数
        // 返回影响数据条数
        // int insert = sqlSession.insert("user.add1", user);    // selectKey 方式
        // int insert = sqlSession.insert("user.add2", user);    // useGeneratedKeys 方式
        int insert = sqlSession.insert("user.add3", user); // uuid 方式
        System.out.println(user);
        // 释放资源
        sqlSession.close();
    }

    /**
     * 更新操作
     */
    @Test
    public void testUpdate() throws ParseException {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        User user = new User();
        user.setId(4);
        user.setName("李四");
        user.setAge(45);
        user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1997-4-4"));
        // 返回影响数据条数
        int update = sqlSession.update("user.update", user);
        sqlSession.close();
    }

    @Test
    public void testGetById() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        User user = (User) sqlSession.selectOne("getById", 4);
        System.out.println(user);
        sqlSession.close();
    }

    /**
     * 模糊查询方式一
     */
    @Test
    public void testGetByName1() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<User> objects = sqlSession.selectList("user.getByName1", "%三%");
        objects.forEach(p -> System.out.println(p));
        sqlSession.close();

        /*
        ==>  Preparing: SELECT id,name,age,birthday FROM user where name like ?
        ==> Parameters: %三%(String)
        */
    }

    /**
     * 模糊查询方式二
     */
    @Test
    public void testGetByName2() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<User> users = sqlSession.selectList("user.getByName2", "三");
        users.forEach(u -> System.out.println(u));
        sqlSession.close();

        /*
        ==>  Preparing: SELECT id,name,age,birthday FROM user where name like '%三%'
         */
    }

    /**
     * 查询所有
     */
    @Test
    public void testGetAll() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        List<Object> users = sqlSession.selectList("getAll");
        users.forEach(u -> System.out.println(u));
        sqlSession.close();
    }

    /**
     * 删除操作
     */
    @Test
    public void testDelete(){
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession(true);
        // 返回影响数据条数
        int delete = sqlSession.delete("user.deleteById", 3);
        sqlSession.close();
    }
}

com.zze.mybatis.test.MyBatisTest

小结架构图

java框架之MyBatis(1)-入门&动态代理开发

动态代理开发

规则

  1. 映射文件的 namespace 必须是对应接口的全路径名。
  2. 接口中方法的方法名必须与对应映射文件中的 sql id 一致。
  3. 接口中方法的入参与对应映射文件中的 parameterType 类型一致。
  4. 接口中方法的返回值必须与对应映射文件中 resultType 类型一致。

使用

1、创建映射文件对应接口:

package com.zze.mybatis.mapper;

import com.zze.mybatis.pojo.User;

import java.util.List;

public interface UserMapper {
    Integer add1(User user);

    Integer add2(User user);

    Integer add3(User user);

    Integer update(User user);

    User getById(Integer id);

    List<User> getByName1(String name);

    List<User> getByName2(String name);

    List<User> getAll();

    Integer deleteById(Integer id);
}

com.zze.mybatis.mapper.UserMapper

2、修改映射文件 namespace 为对应接口全路径名:

<?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.zze.mybatis.mapper.UserMapper">
    <!--
     新增操作
        parameterType : 参数类型
            selectKey 配置主键返回
                keyProperty : 主键属性
                resultType : 主键数据类型
                order : 指定 selectKey 何时执行
     -->
    <insert id="add1" parameterType="com.zze.mybatis.pojo.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID();
        </selectKey>
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>
    <!--
    新增操作
        useGeneratedKeys : 使用自增
        keyProperty : 指定主键属性,与 useGeneratedKeys 搭配使用
        用这两个属性相当于 add1 中使用 selectKey
    -->
    <insert id="add2" parameterType="com.zze.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(name,age,birthday) VALUES(#{name},#{age},#{birthday});
    </insert>

    <!--
    新增操作
    在真正执行插入操作之前生成一个 uuid 赋值给指定属性
    -->
    <insert id="add3" parameterType="com.zze.mybatis.pojo.User">
        <selectKey keyProperty="uuid" resultType="string" order="BEFORE">
            select UUID();
        </selectKey>
        INSERT INTO user(name,age,birthday,uuid) VALUES(#{name},#{age},#{birthday},#{uuid});
    </insert>

    <!--
    更新操作
    -->
    <update id="update" parameterType="com.zze.mybatis.pojo.User">
        UPDATE user SET name=#{name},age=#{age},birthday=#{birthday} WHERE id=#{id};
    </update>
    <!--
    获取单个对象
    -->
    <select id="getById" parameterType="int" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where id=#{id};
    </select>

    <!--
    根据名字模糊查询方式一
         #{} 方式相当于 jdbc 的 ? 占位符方式
         当传入参数为基础类型,使用 #{任意变量名},来引用传入的参数
    -->
    <select id="getByName1" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like #{name};
    </select>

    <!--
    根据名字模糊查询方式二
         该方式为字符串拼接
         当传入的参数为基础类型时,只可以使用 ${value} 来引用传入参数
         当传入的参数为 POJO 时,直接使用${属性名}
    -->
    <select id="getByName2" parameterType="string" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user where name like '%${value}%';
    </select>

    <!--
    查询所有
    -->
    <select id="getAll" resultType="com.zze.mybatis.pojo.User">
        SELECT id,name,age,birthday FROM user
    </select>
    <!--
    删除操作
    -->
    <delete id="deleteById" parameterType="int">
        DELETE FROM user WHERE id=#{id}
    </delete>
</mapper>

mybatis/mapper/User.xml

3、测试:

package com.zze.mybatis.test;

import com.zze.mybatis.mapper.UserMapper;
import com.zze.mybatis.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class MyBatisMapperProxyTest {
    @Test
    public void test() {
        SqlSession sqlSession = SqlSessionFactoryUtil.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//        userMapper.add1();
//        userMapper.add2();
//        userMapper.add3();
//        userMapper.getByName1();
//        userMapper.getByName2();
//        userMapper.getById();a
//        userMapper.deleteById();
//        userMapper.update()
        userMapper.getAll().forEach(u -> System.out.println(u));
    }
}

com.zze.mybatis.test.MyBatisMapperProxyTest

配置相关

属性(properties)

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:

<properties resource="jdbc.properties">
  <property name="username" value="root"/>
  <property name="password" value="root"/>
</properties>

然后其中的属性就可以在整个配置文件中被用来替换需要动态配置的属性值。比如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。

类型别名(typeAliases)

类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如

<typeAliases>
  <typeAlias alias="user" type="com.zze.pojo.User"/>
  <typeAlias alias="customer" type="com.zze.pojo.Customer"/>
  <typeAlias alias="order" type="com.zze.pojo.Order"/>
</typeAliases>

当这样配置时, user 可以用在任何使用 com.zze.pojo.User 的地方。

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="com.zze.pojo"/>
</typeAliases>

每一个在包 com.zze.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。看下面的例子:

@Alias("order")
public class Order{
    ...
}

这是一些为常见的 Java 类型内建的相应的类型别名。它们都是大小写不敏感的,需要注意的是由基本类型名称重复导致的特殊处理。

别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

映射器(mappers)

我们要定义 SQL 映射语句,首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>