MyBatis3源码深度解析(十二)MyBatis的核心组件(一)Configuration

news2024/11/17 12:49:30

文章目录

  • 第四章 MyBatis的核心组件
    • 4.1 使用MyBatis操作数据库
    • 4.2 MyBatis核心组件
    • 4.3 Configuration组件
      • 4.3.1 属性
      • 4.3.2 设置
      • 4.3.3 类型别名
      • 4.3.3 类型处理器
      • 4.3.5 对象工厂
      • 4.3.6 插件
      • 4.3.7 配置环境
      • 4.3.8 映射器

第四章 MyBatis的核心组件

4.1 使用MyBatis操作数据库

在研究MyBatis的核心组件之前,有必要了解一下如何使用MyBatis操作数据库。本文使用maven创建一个简单的示例项目来演示。

(1)准备数据库环境:使用MySQL数据库,创建一个新的database:mybatis_demo,新的表user,并插入数据。

CREATE DATABASE mybatis_demo;
USE mybatis_demo;
CREATE TABLE `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(20) DEFAULT NULL,
  `age` INT(11) DEFAULT NULL,
  `phone` VARCHAR(20) DEFAULT NULL,
  `birthday` DATETIME DEFAULT NULL
)
insert into user (name, age, phone, birthday) values('孙悟空', 1500, '18705464523', '0000-01-01');
insert into user (name, age, phone, birthday) values('猪八戒', 1000, '15235468789', '0500-03-10');

(2)创建maven项目,导入相关依赖。

<dependencies>
    <!--单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>compile</scope>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.15</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
</dependencies>

(3)编写MyBatis主配置文件mybatis-config.xml。

<?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>
    <settings>
        <!--支持返回自动生成主键-->
        <setting name="useGeneratedKeys" value="true"/>
        <!--支持实体名驼峰原则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--别名处理-->
    <typeAliases>
        <package name="com.star.mybatis.entity"/>
    </typeAliases>
    <!--环境信息-->
    <environments default="dev">
        <environment id="dev">
            <!--事务管理器-->
            <transactionManager type="JDBC"/>
            <!--数据源:用户名和密码需要改成自己定义的-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/>
                <property name="username" value="******"/>
                <property name="password" value="******"/>
            </dataSource>
        </environment>
    </environments>
    <!--Mapper映射文件-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

MyBatis主配置文件用于配置MyBatis框架的配置信息,这些参数会改变MyBatis的运行时行为。

(4)编写Java实体User。

public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String phone;
    private Date birthday;
    
    // constructor getter setter ...
}

(5)编写UserMapper接口。

public interface UserMapper {

    List<User> selectAll();

    @Select("select * from user where id = #{id, jdbcType=INTEGER}")
    User selectById(@Param("id") Integer id);

}

为了演示方便,这里使用两种方式配置SQL语句,selectAll()方法用XML的方式,selectById()方法用注解的方式。

(6)编写映射文件UserMapper.xml。

<?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.star.mybatis.mapper.UserMapper">

    <select id="selectAll" resultType="User">
        select * from user
    </select>

</mapper>

(7)编写单元测试。

@Test
public void testMybatis() throws IOException {
    // 读取配置文件
    Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
    // 创建会话
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    // 获取Mapper接口
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 操作数据库
    List<User> userList = userMapper.selectAll();
    userList.forEach(System.out::println);
    System.out.println("---------");
    User user = userMapper.selectById(1);
    System.out.println(user.toString());
}

(8)执行单元测试,控制台打印结果。

User{id=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1}
User{id=2, name='猪八戒', age=1000, phone='15235468789', birthday=Fri Mar 10 00:00:00 CST 500}
---------
User{id=1, name='孙悟空', age=1500, phone='18705464523', birthday=Thu Jan 01 00:00:00 CST 1}

如示例代码所示,SqlSession是MyBatis提供的与数据库交互的接口,其实例通过工厂模式创建。

为了创建SqlSession对象,首先需要创建SqlSessionFactory对象,而SqlSessionFactory对象的创建又依赖于SqlSessionFactoryBuilder类,该类提供了一系列重载的build()方法,将主配置文件的输入流作为参数传入SqlSessionFactoryBuilder对象的build()方法,则可以返回一个SqlSessionFactory对象。

有了SqlSessionFactory对象后,调用其openSession()方法即可获得一个与数据库建立连接的SqlSession实例。

调用SqlSession对象的getMapper()方法创建一个Mapper接口的动态代理对象,然后调用代理实例的方法即可完成与数据库的交互。

需要注意的是,MyBatis来源于iBatis项目,依然保留了iBatis执行Mapper的方式,例如:

// 兼容iBatis执行Mapper的方式
List<User> userList = sqlSession.selectList("com.star.mybatis.mapper.UserMapper.selectAll");

另外,MyBatis还提供了一个SqlSessionManager类,同样可以用于与数据库的交互,例如可以把单元测试方法修改成如下:

@Test
public void testSqlSessionManager() throws IOException {
    Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
    // 创建SqlSessionManager对象
    SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(reader);
    sqlSessionManager.startManagedSession();
    // 通过SqlSessionManager获取Mapper接口
    UserMapper userMapper = sqlSessionManager.getMapper(UserMapper.class);
    List<User> userList = userMapper.selectAll();
    userList.forEach(System.out::println);
    System.out.println("---------");
    User user = userMapper.selectById(1);
    System.out.println(user.toString());
}

如示例代码所示,SqlSessionManager使用了单例模式,在整个应用程序中只存在一个实例。通过该类的静态方法newInstance()即可获取SqlSessionManager的实例。

SqlSessionManager实现了SqlSessionFactory和SqlSession接口,因此可以替代SqlSession完成与数据库的交互。

4.2 MyBatis核心组件

在上面的示例项目中,有一个比较核心的MyBatis组件——SqlSession,它是面向用户的操作数据库的API。除此之外,MyBatis还有一些其他的核心组件,其执行流程如下图所示:

这些核心组件的作用大致描述如下:

  • Configuration

用于描述MyBatis的主配置信息。其他组件需要获取配置信息时,可以直接通过Configuration对象获取。MyBatis在应用启动时,会读取主配置文件mybatis-config.xml中的配置,并将这些配置注册到Configuration组件中,其他组件需要这些配置时,可以直接通过Configuration对象获取。

  • MappedStatement

用于描述Mapper中的SQL配置信息,是对Mapper XML配置文件中的、、、等标签或者@Select、@Update、@Delete、@Insert等注解的封装。

  • SqlSession

是MyBatis提供的面向用户的API,表示和数据库交互时的会话对象,用于完成数据库的增删改查功能。SqlSession是Executor组件的外观,目的是对外提供易于理解和使用的数据库操作接口。

  • Executor

Executor是MyBatis的SQL执行器,MyBatis中对数据库的所有增删改查操作都是由Executor组件完成的。

  • StatementHandler

StatementHandler封装了对JDBC的Statement对象的操作,比如为Statement对象设置参数、调用Statement接口提供的方法与数据库交互等。

  • ParameterHandler

当MyBatis使用的Statement类型为PreparedStatement和CallableStatement时,ParameterHandler用于为Statement对象的参数占位符设置值。

  • ResultSetHandler

ResultSetHandler封装了对JDBC中的ResultSet对象的操作,当执行SQL类型为SELECT语句时,ResultSetHandler用于将查询结果转换为Java对象。

  • TypeHandler

TypeHandler是MyBatis的类型处理器,用于处理Java类型与JDBC类型之间的映射。它能够根据Java类型调用PreparedStatement或CallableStatement对象的setXXX()方法为Statement对象设置值,而且能够根据Java类型调用ResultSet对象的getXXX()方法获取SQL执行结果。

MyBatis操作数据库的过程大致如下:

  1. SqlSession是用户层面的API,它是Executor组件的外观,目的是为用户提供更友好的数据库操作接口。
  2. 真正执行SQL操作的是Executor组件,它是SQL执行器,会使用StatementHandler组件对JDBC的Statement对象进行操作。
  3. 当Statement类型为PreparedStatement和CallableStatement时,会通过ParameterHandler组件为参数占位符赋值。
  4. ParameterHandler组件会根据Java类型找到对应的TypeHandler对象,TypeHandler中会通过Statement对象提供的setXXX()方法为Statement对象中的参数占位符设置值。
  5. StatementHandler组件使用JDBC中的Statement对象与数据库完成交互后,当SQL语句类型为SELECT时,通过ResultSetHandler组件从Statement对象中获取ResultSet对象,然后将ResultSet对象转换为Java对象。

4.3 Configuration组件

MyBatis框架的配置信息有两种,一种是配置MyBatis框架属性的主配置文件,另一种是配置执行SQL语句的Mapper配置文件。

Configuration组件的作用是描述MyBatis主配置文件的信息,即mybatis-config.xml文件。

4.3.1 属性

在mybatis-config.xml文件中,属性使用标签进行配置,其特点是可外部配置可动态替换。例如:

<!-- mybatis-config.xml -->
<properties resource="C:\workspace\mybatis_demo2\config\config.properties">
    <property name="username" value="dev_user"/>
    <property name="password" value="*****"/>
</properties>

可外部配置的意思是,属性既可以在标签下使用标签直接配置,也可以通过resource属性引用外部的一个properties文件。如果两种方式都配置了属性,则优先加载标签下的属性,再加载resource路径下properties文件中的属性,并覆盖已有的同名属性。

可动态替换的意思是,标签下设置的属性,可以在整个配置文件中用于替换需要动态配置的属性值。例如,在配置文件的其它位置使用<property name="username" value="${username}"/>时,${username}会被替换为dev_user

在Configuration组件中,组合了一个Properties对象,用于保存属性配置。

源码1org.apache.ibatis.session.Configuration

protected Properties variables = new Properties();

借助Debug工具,可以看到属性均被加载到Configuration组件中:

4.3.2 设置

在mybatis-config.xml文件中,属性使用标签进行配置,这些设置属性的值会改变MyBatis运行时的行为,因此非常重要。

相对应的,Configuration组件定义了一系列属性来保存这些设置属性。例如:

<!-- mybatis-config.xml -->
<settings>
    <!--支持返回自动生成主键-->
    <setting name="useGeneratedKeys" value="true"/>
    <!--支持自动驼峰命名规则-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

对应到Configuration组件定义的属性是:

源码2org.apache.ibatis.session.Configuration

public class Configuration {
    protected boolean mapUnderscoreToCamelCase;
    protected boolean useGeneratedKeys;
    // ......
}

除了 源码1 中列出的2个设置属性,还有一系列属性,这些属性的作用、默认值等可以参见 W3Cschool的文档-MyBatis教程-XML配置 中的一张表。

借助Debug工具,可以看到设置属性被加载到Configuration组件中:

在这里插入图片描述

4.3.3 类型别名

类型别名就是为Java类型设置一个短的名字,用来减少类的完全限定名的冗余。例如使用User作为com.star.mybatis.entity.User的别名:

在mybatis-config.xml文件中,类型别名使用标签进行配置。例如:

<!-- mybatis-config.xml -->
<typeAliases>
    <typeAlias alias="User" type="com.star.mybatis.entity.User"/>
</typeAliases>

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

<!-- mybatis-config.xml -->
<typeAliases>
    <package name="com.star.mybatis.entity"/>
</typeAliases>

在没有@Alias注解的情况下,MyBatis会使用Java对象的首字母小写的非限定类名来作为它的别名,例如com.star.mybatis.entity包下的User类的别名为user;若该类有@Alias注解,则别名为其注解值。

@Alias("user")
public class User {...}

MyBatis本身已经为许多常见的Java类型内置了相应的类型别名,如下表:

在这里插入图片描述

对应到Configuration组件,组合了一个类型别名注册器,用于注册所有的类型别名。其源码如下:

源码3org.apache.ibatis.session.Configuration

// 用于注册所有的类型别名
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();

借助Debug工具,可以看到加载到Configuration组件中的别名有81个,其中包括自定义的User类的别名:

4.3.3 类型处理器

类型处理器的作用在于,MyBatis在预处理语句(PreparedStatement)中设置一个参数时,或者从ResulrSet结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成JDBC类型或Java类型。

在mybatis-config.xml文件中,类型别名使用标签进行配置。例如:

<!-- mybatis-config.xml -->
<typeHandlers>
    <typeHandler handler="com.star.mybatis.handler.ExampleTypeHandler"
        javaType="String"
        jdbcType="VARCHAR"/>
</typeHandlers>

MyBatis有许多默认的类型处理器实现,基本涵盖Java全部基本数据类型,如下表所示:

另外,类型处理器支持重写,或创建自定义的类型处理器来处理不支持的或非标准的类型

具体做法是:实现 org.apache.ibatis.type.TypeHandler接口, 或继承org.apache.ibatis.type.BaseTypeHandler,然后在主配置文件mybatis-config.xml中使用标签进行配置。例如:

@MappedTypes({String.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class ExampleTypeHandler extends BaseTypeHandler {...}

那如何确定这个自定义的类型处理器是处理什么类型的呢?

设置类型处理器处理的Java类型:

  • 在类型处理器的配置元素上增加一个javaType属性,如:<typeHandler javaType="String"/>
  • 在类型处理器的类上增加一个@MappedTypes注解,如:@MappedTypes({String.class})。 如果同时配置javaType属性和@MappedTypes注解,则注解方式将被忽略。

设置类型处理器处理的JDBC类型:

  • 在类型处理器的配置元素上增加一个jdbcType属性,如:<typeHandler jdbcType="VARCHAR"/>
  • 在类型处理器的类上增加一个@MappedJdbcTypes注解,如:@MappedJdbcTypes({JdbcType.VARCHAR})。 如果同时配置jdbcType属性和@MappedJdbcTypes注解,则注解方式将被忽略。

最后,还可以通过设置包名让MyBatis自动查找类型处理器,此时只能通过注解方式来指定类型处理器要处理的Java类型和JDBC类型。例如:

<!-- mybatis-config.xml -->
<typeHandlers>
    <package name="com.star.mybatis.handler"/>
</typeHandlers>

在Configuration组件中,组合了一个类型处理器的注册器,用于注册所有的类型处理器。

源码4org.apache.ibatis.session.Configuration

// 用于注册所有的类型处理器
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this);

借助Debug可知,Configuration组件中最终注册的类型处理器一共有41个,包括1个自定义的ExampleTypeHandler:

4.3.5 对象工厂

MyBatis每次创建结果映射对象的新实例时,会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。

在mybatis-config.xml文件中,对象工厂使用标签进行配置。例如:

<!-- mybatis-config.xml -->
<objectFactory type="com.star.mybatis.factory.ExampleObjectFactory">
    <property name="name" value="test"/>
</objectFactory>

通过创建自定义的对象工厂,可以覆盖对象工厂的默认行为。例如:

public class ExampleObjectFactory extends DefaultObjectFactory {

    // 处理默认构造方法
    @Override
    public <T> T create(Class<T> type) {
        return super.create(type);
    }

    // 处理带参数的构造方法
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        return super.create(type, constructorArgTypes, constructorArgs);
    }

    // 配置ObjectFactory属性
    @Override
    public void setProperties(Properties properties) {

    }

}

在Configuration组件中,组合了一个ObjectFactory对象,用于保存对象工厂,默认实现类为DefaultObjectFactory。

源码5org.apache.ibatis.session.Configuration

protected ObjectFactory objectFactory = new DefaultObjectFactory();

借助Debug可知,Configuration组件最终会将自定义的对象工厂注册到Configuration组件中:

4.3.6 插件

MyBatis允许在SQL语句执行过程中的某一点使用插件进行拦截调用。默认情况下,允许使用插件来拦截的方法包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

自定义一个插件比较简单,只需实现Interceptor接口,并指定了想要拦截的方法:

@Intercepts({@Signature(
        type= Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class})})
public class ExamplePlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
    }

}

在mybatis-config.xml文件中,插件使用标签进行配置。例如:

<!-- mybatis-config.xml -->
<plugins>
    <plugin interceptor="com.star.mybatis.plugin.ExamplePlugin">
        <property name="name" value="ExamplePlugin"/>
    </plugin>
</plugins>

在Configuration组件中,组合了一个拦截器链,用于存放自定义的插件。

源码6org.apache.ibatis.session.Configuration

protected final InterceptorChain interceptorChain = new InterceptorChain();

借助Debug可知,Configuration组件最终会注册自定义的插件:

4.3.7 配置环境

MyBatis可以配置成适应多种环境,例如,开发、测试和生产环境有不同的配置。

但要注意,尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择其中一个环境。因此,有几个数据库需要连接,就需要创建几个SqlSessionFactory实例。

在mybatis-config.xml文件中,配置环境使用标签进行配置。例如:

<!-- mybatis-config.xml -->
<environments default="dev">
    <environment id="dev">
        <transactionManager type="JDBC">
            <property name="..." value="..."/>
        </transactionManager>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
    <environment id="test">
        ...
    </environment>
    <environment id="prod">
        ...
    </environment>
    ...
</environments>

如例子所示,标签的default属性要和标签的id属性相匹配,选择出当前生效的环境,生效的环境才会注册到Configuration组件中的环境配置。

  • 事务管理器:

在MyBatis中,有两种事务管理器:JDBC、MANAGED。

(1)JDBC

这种事务管理器直接使用JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务。

(2)MANAGED

这种事务管理器相当于没有事务管理器,因为它从不提交或回滚一个连接,而是全权交给了容器来管理。

  • 数据源:

注意,这里使用${...}的方式,就是取用【4.3.1 属性】中配置的属性。

标签的type属性是指数据源类型,它的取值包括UNPOOLED、POOLED、JNDI。

(1)UNPOOLED

即非“池”类型的数据源,它的实现会在每次请求时打开和关闭连接。相比连接池,它虽然有一点慢,但对于没有性能要求的简单应用程序是一个很好的选择。

UNPOOLED类型的数据源仅需要配置以下5种属性:

  • driver– JDBC驱动的Java类的完全限定名。
  • url– 数据库的JDBC URL地址。
  • username– 登录数据库的用户名。
  • password– 登录数据库的密码。
  • defaultTransactionIsolationLevel– 默认的连接事务隔离级别。

(2)POOLED

即“池”类型的数据源,它的实现会将JDBC连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。这是一种使得并发Web应用快速响应请求的流行处理方式。

除了上述提到的5种属性,还有更多属性用来配置POOLED类型的数据源:

  • poolMaximumActiveConnections– 最大活动连接数,默认值:10。
  • poolMaximumIdleConnections– 最大空闲连接数。
  • poolMaximumCheckoutTime– 池中连接最大被检出时间,超时将被强制返回,默认值:20000毫秒。
  • poolTimeToWait– 获取连接如果超过这个时间,则会给连接池打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败但没有任何提示),默认值:20000毫秒。
  • poolPingQuery– 发送到数据库的心跳查询SQL语句,用来检验连接是否处在正常状态并准备接受请求。默认是NO PING QUERY SET,当数据库驱动失败时,返回一个错误消息。
  • poolPingEnabled– 是否启用心跳查询。若开启,必须使用一个可执行的SQL语句设置poolPingQuery属性(最好是一个非常快的SQL语句),默认值:false。
  • poolPingConnectionsNotUsedFor– 配置poolPingQuery的使用频度。可以设置成数据库连接超时时间,来避免不必要的检测,默认值:0(即所有连接每一时刻都被检测 — 当然仅当poolPingEnabled为true时适用)。

(3)JNDI

这种数据源的实现是为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。

这种数据源配置只需要2个属性:

  • initial_context– 用来在InitialContext中寻找上下文。这是个可选属性。
  • data_source– 引用数据源实例位置的上下文的路径。提供了initial_context配置时会在其返回的上下文中进行查找,没有提供时则直接在InitialContext中查找。

在Configuration组件中,组合了一个Environment对象,用于存放被选中的环境配置。

源码7org.apache.ibatis.session.Configuration

protected Environment environment;

借助Debug可知,Configuration组件最终会注册一个Environment对象:

4.3.8 映射器

映射器用于配置SQL映射文件的位置,也就是告诉MyBatis到哪里去找SQL映射文件。

在mybatis-config.xml文件中,映射器使用标签进行配置。例如:

    <!--映射文件-->
    <mappers>
        <!--通过指定XML文件的类路径来注册-->
        <mapper resource="mapper/UserMapper.xml"/>
        <!--通过指定XML文件的完全限定资源定位符来注册-->
        <!--<mapper url="file:///C:\workspace\mybatis_demo2\src\main\resources\mapper\UserMapper.xml"/>-->
        <!--通过Mapper接口的类路径来注册-->
        <!--<mapper class="com.star.mybatis.mapper.UserMapper"/>-->
        <!--通过Mapper接口所在包路径类注册-->
        <!--<package name="com.star.mybatis.mapper"/>-->
    </mappers>

如上面的配置所示,配置SQL映射文件的位置有4种方法是:第一是使用XML文件的类路径;第二是使用XML文件的完全限定资源定位符(即包括 file:///的URL);第三是使用Mapper接口的类路径;第四是使用Mapper接口所在包路径。

在Configuration组件中,组合了一个Mapper注册器,用于注册Mapper接口信息:

源码:

protected final MapperRegistry mapperRegistry;

借助Debug可知,Configuration组件最终会注册配置好的映射器:

本节完,更多内容请查阅分类专栏:MyBatis3源码深度解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1521993.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Boyer Moore 算法介绍

1. Boyer Moore 算法介绍 Boyer Moore 算法&#xff1a;简称为 BM 算法&#xff0c;是由它的两位发明者 Robert S. Boyer 和 J Strother Moore 的名字来命名的。BM 算法是他们在 1977 年提出的高效字符串搜索算法。在实际应用中&#xff0c;比 KMP 算法要快 3~5 倍。 BM 算法思…

【Machine Learning】Suitable Learning Rate in Machine Learning

一、The cases of different learning rates: In the gradient descent algorithm model: is the learning rate of the demand, how to determine the learning rate, and what impact does it have if it is too large or too small? We will analyze it through the follow…

【安全类书籍-1】asp代码审计.pdf

目录 内容简介 作用 下载地址 内容简介 这个文档摘录片段主要讨论了ASP编程中的安全性审计,包括SQL注入漏洞、Cookie注入防范措施及文件上传安全问题,并给出了相关示例代码。 SQL注入漏洞与防范 - ASP代码中展示了如何通过`Request.QueryString`和`Request.Form`获取用户…

SpringBoot打造企业级进销存储系统 第五讲

package com.java1234.repository;import com.java1234.entity.Menu; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query;import java.util.List;/*** 菜单Repository接口*/ public interface MenuReposit…

spacy进行简单的自然语言处理的学习

自然语言处理基本概念 概念&#xff1a;自然语言处理&#xff0c;是让机器理解人的语言的过程。 作用&#xff1a;通过使用自然语言处理&#xff0c;机器可以理解人的语言&#xff0c;从而进行语义分析&#xff0c;例如&#xff1a;从一句话中判断喜怒哀乐&#xff1b;从一段文…

电大搜题:开启学习新时代

身处信息化时代&#xff0c;学习的方式已经发生了巨大的变革。在这个多元化的学习环境中&#xff0c;传统的学习模式已经无法满足现代学习者的需求。然而&#xff0c;电大搜题应运而生&#xff0c;为学习者提供了一个高效、便捷的学习途径。 电大搜题&#xff0c;作为黑龙江开…

阅读 - 二维码扫码登录原理

在日常生活中&#xff0c;二维码出现在很多场景&#xff0c;比如超市支付、系统登录、应用下载等等。了解二维码的原理&#xff0c;可以为技术人员在技术选型时提供新的思路。对于非技术人员呢&#xff0c;除了解惑&#xff0c;还可以引导他更好地辨别生活中遇到的各种二维码&a…

铁路订票平台小程序|基于微信小程序的铁路订票平台小程序设计与实现(源码+数据库+文档)

铁路订票平台小程序目录 目录 基于微信小程序的铁路订票平台小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、车次信息管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐…

Transformer学习笔记(二)

一、文本嵌入层Embedding 1、作用&#xff1a; 无论是源文本嵌入还是目标文本嵌入&#xff0c;都是为了将文本中词汇的数字表示转变为向量表示&#xff0c;希望在这样的高维空间捕捉词汇间的关系。 二、位置编码器Positional Encoding 1、作用&#xff1a; 因为在Transformer…

冲动是魔鬼,工作不顺心时不要把坏脾气带给家人

今天与一个跟踪了很久的客户准备签合同了&#xff0c;客户突然反悔&#xff0c;为此与他周旋了一整天&#xff0c;忙碌得一口水都没有喝。回到小区坐在车里抽着烟&#xff0c;久久不愿回家&#xff0c;只想一个人坐着&#xff0c;疲惫、无奈。这个月的奖金似乎又将成为泡影。 …

Microsoft SQL Server2019占用大量磁盘空间的解决办法(占了我C盘120G的空间!!!)附SQL数据库定时清理代理作业

一、问题 安装Microsoft SQL Server2019后我的C盘在几天后少了100G&#xff0c;如图所示&#xff1a; 解决后&#xff1a; 出现这种情况&#xff0c;我在各种清理C盘后&#xff0c;空间还是没有太大变化 &#xff0c;且几乎每天都要少2个G&#xff0c;后来终于找见原因了&…

Postman接口测试:API 测试的必备技巧

在现代软件开发生命周期中&#xff0c;接口测试是一个至关重要的部分。使用 Postman 这一工具&#xff0c;可以轻松地进行 接口测试。以下是一份简单的使用教程&#xff0c;帮助你快速上手。 安装 Postman 首先&#xff0c;你需要在电脑上安装 Postman。你可以从官网上下载并…

虚拟机NAT模式配置

注意这里IP要和网关在同一网段&#xff0c;且虚拟机默认网关末尾为.2&#xff08;如果默认网关配置为.1会与宿主机冲突&#xff0c;导致无法ping通外网&#xff09; 点击NAT模式下的NAT设置即可查看默认网关 这里的网关可以理解为主机与虚拟机交互的入口

CSDN首发Chainlink(预言机)讲解:基础知识总结 到底什么是预言机本篇带你解析

苏泽 大家好 这里是苏泽 一个钟爱区块链技术的后端开发者 本篇专栏 ←持续记录本人自学两年走过无数弯路的智能合约学习笔记和经验总结 如果喜欢拜托三连支持~ 前面的专栏带大家熟悉了 区块链的基本组成 、共识机制、智能合约、最小信任机制 以及EVM等知识 如遇不懂的概念或名…

2024年【危险化学品经营单位主要负责人】新版试题及危险化学品经营单位主要负责人复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【危险化学品经营单位主要负责人】新版试题及危险化学品经营单位主要负责人复审考试&#xff0c;包含危险化学品经营单位主要负责人新版试题答案和解析及危险化学品经营单位主要负责人复审考试练习。安全生产模…

Kubernetes operator系列:webhook 知识学习

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Kubernetes operator学习 系列文章&#xff0c;本节会对 kubernetes webhook 知识进行学习 本文的所有代码&#xff0c;都存储于github代码库&#xff1a;https://github.com/graham924/share-code-operator-st…

说下你对TCP以及TCP三次握手四次挥手的理解?

参考自简单理解TCP三次握手四次挥手 什么是TCP协议&#xff1f; TCP( Transmission control protocol )即传输控制协议&#xff0c;是一种面向连接、可靠的数据传输协议&#xff0c;它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接&a…

【Python】进阶学习:基于Numpy实现按指定维度拼接两个数组

【Python】进阶学习&#xff1a;基于Numpy实现按指定维度拼接两个数组 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希…

无限自动出兵-入门版【war3地图编辑器】

文章目录 1、创建单位和地区2、新事件开端3、动作3.1、创建单位3.2、选取单位3.2.1、发布指令 4、最终 1、创建单位和地区 2、新事件开端 创建新的触发器→新事件开端→时间→时间周期事件 3、动作 3.1、创建单位 3.2、选取单位 单位组→选取单位组内单位做动作 矩形区域内的…

idea中database的一些用法

1、查看表结构 方法1&#xff0c;右键&#xff0c;选这个 方法2 双击表后&#xff0c;看到数据&#xff0c;点DDL 方法3 写SQL时&#xff0c;把鼠标放在表名上&#xff0c;可以快速查看表结构 2、表生成对应的实体类 表中右键&#xff0c;选择这2个&#xff0c;选择生成的路…