Mybatis源码之美:2.11.通过settings配置初始化全局配置

413 阅读18分钟

通过settings配置初始化全局配置

讲到了通过settings初始化Mybatis全局配置,我们就很难继续绕开MybatisConfiguration对象。

Configuration对象无疑是Mybatis的核心对象之一,他定义了很多属性和方法,在解析的过程中,我们可能会遇到一些我们不了解其具体作用的属性或者方法,不用担心,在后续的解析过程中,我们会慢慢填充对于Configuration对象的了解。

先贴出Configuration对象的属性,这里先大致看一下,有一个印象,在后期解析的过程中,会逐渐讲到每个属性的作用。

这一章可能会比较枯燥,但是坚持学下去也能让我们对mybatis的使用更熟练一些。

Configuration.java(代码总览,可以跳过)
/**
* Mybatis配置类
* 提供了Mybatis所有的配置以及Mapper文件的元数据容器
*
* @author Clinton Begin
*/
public class Configuration {

    /**
     * 环境信息,包括事务和数据源等数据
     */
    protected Environment environment;
    /**
     * 是否允许在嵌套语句中使用{@link RowBounds}执行分页操作
     */
    protected boolean safeRowBoundsEnabled;
    /**
     * 是否允许在嵌套语句中使用{@link ResultHandler}执行分页操作
     */
    protected boolean safeResultHandlerEnabled = true;
    /**
     * 将下划线转换为驼峰
     */
    protected boolean mapUnderscoreToCamelCase;
    /**
     * 是否允许在在方法调用时直接加载该对象的所有属性
     */
    protected boolean aggressiveLazyLoading;
    /**
     * 是否允许单条语句返回多个结果集
     */
    protected boolean multipleResultSetsEnabled = true;
    /**
     * 是否允许JDBC自动生成主键
     */
    protected boolean useGeneratedKeys;
    /**
     * 使用列标签代替列名
     */
    protected boolean useColumnLabel = true;
    /**
     * 是否启用缓存
     */
    protected boolean cacheEnabled = true;
    /**
     * 当内容为null时,是否依然设值
     */
    protected boolean callSettersOnNulls;
    /**
     * 是否使用实际的参数名称,一定程度上可以减少{@link org.apache.ibatis.annotations.Param}的代码
     */
    protected boolean useActualParamName = true;
    /**
     * 在获取不到内容的时候,是否允许返回一个空实例
     * 在常规情况下如果查询结果返回的内容是null,MyBatis默认返回null,如果开启该功能,其将会返回一个空实例
     */
    protected boolean returnInstanceForEmptyRow;
    /**
     * Mybatis日志前缀
     */
    protected String logPrefix;
    /**
     * 日志实现类,如果未实现则自动查找
     */
    protected Class<? extends Log> logImpl;
    /**
     * 虚拟文件系统,提供了一个访问系统文件资源的简单API
     */
    protected Class<? extends VFS> vfsImpl;
    /**
     * 缓存的生命周期
     * MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
     * 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询.
     * 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。
     */
    protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
    /**
     * 字段在数据库中的类型
     * 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。
     * 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。
     */
    protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
    /**
     * 懒加载的触发方法
     */
    protected Set<String> lazyLoadTriggerMethods = new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString"));
    /**
     * {@link java.sql.Statement}的默认超时时间,他决定了驱动等待数据库响应的秒数,默认不超时
     */
    protected Integer defaultStatementTimeout;
    /**
     * 获取数据的默认大小
     * 为驱动的结果集设置默认获取数量。
     */
    protected Integer defaultFetchSize;
    /**
     * 执行预期时使用的执行器的行为类型
     * 其中:
     * {@link ExecutorType#SIMPLE} 会为每个语句的执行都创建一个新的预处理语句({@link java.sql.PreparedStatement})
     * {@link ExecutorType#REUSE} 会复用预处理语句
     * {@link ExecutorType#BATCH} 会复用预处理语句并执行批量操作
     */
    protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
    /**
     * 自动映射行为定义
     * {@link AutoMappingBehavior#NONE} 禁用自动映射
     * {@link AutoMappingBehavior#PARTIAL} 局部自动映射,只映射没有定义嵌套结果集映射的结果集
     * {@link AutoMappingBehavior#FULL} 完整自动映射,会自动映射任意复杂的结果集(无论是否嵌套)
     */
    protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
    /**
     * 当自动映射遇到无法识别的字段的时候的处理行为
     * {@link AutoMappingUnknownColumnBehavior#NONE} 不做任何操作
     * {@link AutoMappingUnknownColumnBehavior#WARNING} 输出警告日志
     * {@link AutoMappingUnknownColumnBehavior#FAILING} 终止自动映射并抛出异常
     */
    protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
    /**
     * 属性配置 configuration->settings下的属性
     */
    protected Properties variables = new Properties();
    /**
     * 配置反射工厂,简化操作属性和构造器
     */
    protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    /**
     * 配置对象创建工厂
     */
    protected ObjectFactory objectFactory = new DefaultObjectFactory();
    /**
     * 配置对象包装工厂,主要用于创建非原生对象
     */
    protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
    /**
     * 是否启用懒加载。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。
     */
    protected boolean lazyLoadingEnabled = false;
    /**
     * 代理工厂,指定Mybatis创建懒加载对象使用的代理工具
     */
    protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL
    /**
     * 数据库类型唯一标志,Mybatis根据能够根据不能的数据库厂商执行不同的语句,实现此功能就是依赖于该标志。
     */
    protected String databaseId;
    /**
     * 配置工厂
     * Configuration factory class.
     * Used to create Configuration for loading deserialized unread properties.
     *
     * @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300 (google code)</a>
     */
    protected Class<?> configurationFactory;
    /**
     * Dao操作对象注册表
     */
    protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
    /**
     * 拦截器职责链(Mybatis插件)
     */
    protected final InterceptorChain interceptorChain = new InterceptorChain();
    /**
     * 类型处理器注册表
     */
    protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
    /**
     * 类型别名注册表,主要用在执行SQL语句的出入参以及一些类的简写
     */
    protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
    /**
     * 语言支持驱动注册表
     */
    protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
    /**
     * 声明语句映射表
     */
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
            .conflictMessageProducer((savedValue, targetValue) ->
                    ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
    /**
     * 缓存映射表
     */
    protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
    /**
     * ResultMap映射表
     */
    protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
    /**
     * 参数映射表
     */
    protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
    /**
     * 主键生成器映射表
     */
    protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<>("Key Generators collection");

    /**
     * 已加载过得资源集合,可以用来防止重复加载文件
     */
    protected final Set<String> loadedResources = new HashSet<>();
    /**
     * 代码块映射集合
     */
    protected final Map<String, XNode> sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers");

    /**
     * 未完成处理的声明语句
     */
    protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<>();
    /**
     * 未完成处理的缓存引用
     */
    protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<>();
    /**
     * 未完成处理的返回结果映射
     */
    protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<>();
    /**
     * 未完成处理的方法集合
     */
    protected final Collection<MethodResolver> incompleteMethods = new LinkedList<>();

    /*
     * 缓存引用映射关系
     * 缓存引用方=》缓存
     */
    protected final Map<String, String> cacheRefMap = new HashMap<>();

    public Configuration(Environment environment) {
        this();
        this.environment = environment;
    }

    public Configuration() {
        // 注册别名

        // 注册JDBC别名
        typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
        // 注册事务管理别名
        typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
        // 注册JNDI别名
        typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
        // 注册池化数据源别名
        typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
        // 注册为池化的数据源
        typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
        // 注册永久缓存
        typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
        // 注册先入先出的缓存
        typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
        // 注册最近最少使用缓存
        typeAliasRegistry.registerAlias("LRU", LruCache.class);
        // 注册软缓存
        typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
        // 注册弱缓存
        typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
        // 注册处理数据库ID的提供者
        typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
        // 注册基于XML的语言驱动
        typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
        //注册静态语言驱动(通常无需使用)
        typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
        // 注册Sl4j日志
        typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
        //注册Commons日志
        typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
        //注册log4j日志
        typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
        //注册log4j2日志
        typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
        //注册jdk log日志
        typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
        //注册标准输出日志
        typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
        //注册无日志
        typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
        // 注册CGLIB
        typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
        // 注册JAVASSIST
        typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
        // 默认使用XML语言驱动
        languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
        // 支持原始语言驱动
        languageRegistry.register(RawLanguageDriver.class);
    }

settingsElement方法中是比较繁琐且枯燥的属性赋值操作。

settingsElement(settings)(代码总览,可以跳过)
    /**
     * 通过用户自定义配置覆盖系统默认配置
     *
     * @param props 用户自定义配置
     * @see http://www.mybatis.org/mybatis-3/zh/configuration.html#settings
     */
    private void settingsElement(Properties props) {
        // 定义Mybatis如何自动将JDBC列转换为字段或者属性,它对应AutoMappingBehavior枚举类,其中
        // NONE:表示禁用自动映射
        // PARTIAL: 局部自动映射,只映射没有定义嵌套结果集映射的结果集
        // FULL: 完整自动映射,会自动映射任意复杂的结果集(无论是否嵌套)
        configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));

        // 定义当发现使用自动映射功能无法处理(识别)的列或者字段时的行为.它对应AutoMappingUnknownColumnBehavior枚举类,其中
        // NONE:表示无任何操作
        // WARNING:表示输出警告日志
        // FAILING:映射失败并抛出SqlSessionException异常
        configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));

        // 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。
        configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));

        // 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工厂,默认使用JavassistProxyFactory.
        configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));

        // 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。
        configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));

        // 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).
        configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));

        // 是否允许单一语句返回多结果集(需要兼容驱动)。
        configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));

        // 是否使用列标签代替列名称。
        configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));

        // 是否允许JDBC自动生成主键,需要驱动兼容。
        // 如果设置为 true 则设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。
        configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));

        // 配置默认的执行器。对应ExecutorType枚举类
        // SIMPLE 就是普通的执行器;
        // REUSE 执行器会重用预处理语句(prepared statements);
        // BATCH 执行器将重用语句并执行批量更新。
        configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));

        // 设置超时时间,它决定驱动等待数据库响应的秒数。
        configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));

        // 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。
        configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));

        // 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射
        configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));

        // 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false,看好了,允许使用是False。
        configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));

        // MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
        // 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
        // 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。
        configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));

        // 在没有为参数指定JDBC类型时,在该参数为null的时候,默认使用的JDBC类型,通常使用NULL,VARCHAR,OTHER.
        configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));

        // 懒加载的触发方法,指定哪个对象的哪些方法触发一次延迟加载。
        configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));

        // 允许在嵌套语句中使用返回结果处理器(ResultHandler)。如果允许使用则设置为false。
        configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));

        // 指定动态 SQL 生成的默认语言,目前默认是XMLLanguageDriver.
        configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));

        // 指定 Enum 使用的默认 TypeHandler 。
        configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));

        // 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,
        // 这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。
        // 注意基本类型(int、boolean等)是不能设置成 null 的。
        configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));

        // 是否使用允许使用方法签名中的名称作为语句参数名称,一定程度上可以减少{@link org.apache.ibatis.annotations.Param}的代码
        configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));

        // 当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。
        // 需要注意的是,他也适用于嵌套的结果集(collection和association).
        configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));

        // 指定 MyBatis 增加到日志名称的前缀。
        configuration.setLogPrefix(props.getProperty("logPrefix"));

        // 指定一个提供Configuration实例的类。
        // 这个被返回的Configuration实例用来加载被反序列化对象的懒加载属性值。
        // 这个类必须包含一个签名方法static Configuration getConfiguration().
        configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
    }

不得不说settingsElement(Properties)方法中的代码也挺多的,我们先耐着性质一个一个看下去。

配置mybatis的自动映射行为

配置Mybatis在自动映射时遇到无法识别的字段的时候的处理行为

configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));

AutoMappingBehavior是mybatis的定义自动映射列和字段的策略定义枚举,他有三个参数,NONE,PARTIAL,FULL. 其中:

  • NONE,表示禁用自动映射的功能。
  • PARTIAL,表示局部自动映射,意思就是只会自动映射没有定义嵌套结果集的结果集。
  • FULL,表示完整的自动映射功能,他会自动映射任意复杂的结果集,包括嵌套结果集的结果集。

当我们在ResultMap的返回参数中定义了collection或者association属性的时候,其查询操作并不是一个简单的SQL,他的具体结果实际上是一个一对多的复杂集合,这里这个一对多的复杂集合就是嵌套结果集。 比如:我们定义了如下Mapper

    <!--ClassInfo和Student都具有ID和name两个属性,但是这里不明确指出,采用Mybatis的自动映射结果集。-->
    <!--定义学生类的返回结果-->
    <resultMap id="Student" type="*.*.*.Student" >
    </resultMap>
    <!--
        定义班级类的返回结果
        班级和学生的关系是:一对多
    -->
    <resultMap id="ClassInfo" type="*.*.*.ClassInfo">
        <collection property="student"  resultMap="Student"/>
    </resultMap>

在这里ClassInfo对应的查询结果里面包括了一个Student集合,这里Student集合就是嵌套的结果集

这样,只有在我们的Configuration#autoMappingBehavior值为AutoMappingBehavior#FULL的时候,才会自动将Student的返回结果的ID和Name值赋给Student对象的相应字段

配置Mybatis在自动映射时遇到无法识别的字段的时候的处理行为

configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));

AutoMappingUnknownColumnBehavior是Mybatis定义在自动映射时发现无法处理(识别)的列或字段的时候的行为枚举类,他提供了一个叫做doAction的方法`来实现具体的操作.

    /**
     * 检测到自动映射目标的未知列(或未知属性类型)时执行操作。
     *
     * @param mappedStatement 映射声明语句
     * @param columnName      字段名称
     * @param propertyName    属性名称
     * @param propertyType    字段类型,如果该字段不为null,则表示未注册TypeHandler.
     */
    public abstract void doAction(MappedStatement mappedStatement, String columnName, String propertyName, Class<?> propertyType);

AutoMappingUnknownColumnBehavior有三种模式,其中默认使用的是NONE.

  • NONE,不执行任何操作
  • WARNING,输出警告日志.
  • FAILING,映射失败并抛出{@link SqlSessionException}.

是否启用二级缓存

configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));

cacheEnabledMybatis用于配置是否启用所有缓存的开关,默认为true,在分布式应用下最好禁用掉二级缓存,避免出现脏读。

指定Mybatis懒加载对象的代理工厂

configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));

proxyFactory指定了Mybatis创建具有延迟加载能力的对象所用到的代理工厂,默认使用JavassistProxyFactory.

是否启用懒加载

configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));

lazyLoadingEnabledMybatis是否启用懒加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。

是否允许在在方法调用时直接加载该对象的所有属性

configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));

当开启时,任何方法的调用都会加载懒加载对象的所有属性。否则,每个属性会按需加载,默认为false(参考lazyLoadTriggerMethods).

是否允许单一语句返回多结果集

configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));

默认为true

是否使用列标签代替列名称

configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));

默认为true

是否允许JDBC自动生成主键

configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));

该参数用于设置是否自动生成主键,默认为false,如果这个参数为true,那么,将强制自动生成主键,尽管一些驱动不能兼容但仍可正常工作。

配置Mybatis的默认Sql执行器

configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));

defaultExecutorType对应了ExecutorType枚举类,该枚举类定义了MybatisSql执行器的三种类型:

  • SIMPLE 就是普通的执行器,会为每个语句的执行都创建一个新的预处理语句({@link java.sql.PreparedStatement});
  • REUSE 执行器会重用预处理语句(prepared statements);
  • BATCH 执行器将重用语句并执行批量更新。

默认使用的是SIMPLE

配置Mybatis请求超时时间

configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));

该值决定了Mybatis等待数据库响应的秒数,默认永不超时。

配置Mybatis请求结果集的数量限制

configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));

为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。

开启自动将下划线转换为驼峰的功能

configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));

开启该功能后,Mybatis将会自动将JDBC的类名称由典型的下划线命名法转换为Java属性的驼峰命名法,默认值为false

是否允许在嵌套语句中使用分页(RowBounds)

configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));

是否允许在嵌套结果集中使用RowBouds,默认为false,注意!! false允许.

RowBounds是Mybatis的分页类,具体的使用会在后面给出。

设置Mybatis本地缓存的生命周期

本地缓存也被称为一级缓存

configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));

LocalCacheScopeMybatis本地缓存的生命周期定义枚举,他有两个属性,分别对应本地缓存的不同生命周期。

  • SESSIO,,这种情况下会缓存一个会话中执行的所有查询
  • STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据.

默认使用的SESSION.

配置在没有为参数指定JDBC类型时,该参数为NULL时默认使用的JDBC类型

configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));

在没有为参数指定JDBC类型时,且参数为null的时候,默认使用的JDBC类型,通常是NULL,VARCHAR,OTHER三者之一,这里就不列举JdbcType枚举的实例了,里面的内容挺多的,这里默认为OTHER

配置Mybatis懒加载的触发方法

configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));

该参数在aggressiveLazyLoading中提到过,两者通常配合使用,他制定了懒加载的触发方法,用来指定哪些对象的哪些方法触发一次懒加载,默认值为:equals,clone,hashCode,toString

允许在嵌套语句中使用分页(ResultHandler)

configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));

设置Mybaits是否允许在嵌套语句中使用ResultHandler,注意!!如果允许的话,请设置为false,默认值为false.

Mybatis Sql脚本语言处理器注册表

configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));

配置mybatis全局默认的Sql语言处理器,Mybatis的默认SQL语言处理器是XMLLanguageDriver

关于语言驱动器的内容,我们将会在扩展内容给出。

配置枚举类型的默认转换器

configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")))
   /**
     * 配置枚举类型的默认的TypeHandler,默认使用EnumTypeHandler。
     *
     * @param typeHandler 用于处理枚举类型的类型处理器
     * @since 3.4.5
     */
    public void setDefaultEnumTypeHandler(Class<? extends TypeHandler> typeHandler) {
        if (typeHandler != null) {
            // 获取类型处理器注册表,并设置默认的枚举类型处理器
            getTypeHandlerRegistry().setDefaultEnumTypeHandler(typeHandler);
        }
    }

获取Configuration中的typeHandlerRegistry实例.

    /**
     * 获取类型处理器注册表
     */
    public TypeHandlerRegistry getTypeHandlerRegistry() {
        return typeHandlerRegistry;
    }

配置默认的枚举类型处理器.

 /**
     * 配置枚举类型的默认的TypeHandler,默认使用EnumTypeHandler。
     *
     * @param typeHandler 用于处理枚举类型的类型处理器
     * @since 3.4.5
     */
    public void setDefaultEnumTypeHandler(Class<? extends TypeHandler> typeHandler) {
        this.defaultEnumTypeHandler = typeHandler;
    }

TypeHandlerRegistry是Mybatis中的类型转换处理器注册表,它主要负责维护用于java类型和JDBC类型的转换的TypeHandler, 他是Mybatis中不可或缺的一个组件,作为一个注册表,在初始化的时候他注册了很多默认的类型转换处理器,便于我们使用。

TypeHandlerRegistrydefaultEnumTypeHandler属性用于记录默认的枚举类型处理器。

参数defaultEnumTypeHandler的作用就是指定TypeHandlerRegistry#defaultEnumTypeHandler的值,默认为EnumTypeHandler

当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法

configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));

设置在Mybatis中当结果集中的某个值为null时,是否依然调用所属JAVA对象的属性对应的Setter方法,默认值为false

当查询内容为空时,是否初始化一个空实例

configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));

设置当Mybatis的查询结果集所有的返回行都是空的时候,是否初始化一个空的实例,该值默认为false,即不使用。

需要注意的是,当开启了该功能之后,对于嵌套结果(collectionassociation)也是同样生效的。

指定 MyBatis 统一日志名称前缀

configuration.setLogPrefix(props.getProperty("logPrefix"));

设置Mybatis中日志使用的公共前缀。

指定Configuration的工厂

configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));

指定一个提供Configuration实例的类,这个被返回的Configuration实例用来加载被反序列化对象的懒加载属性。

configurationFactory指向的类必须有一个static Configuration getConfiguration()方法定义.

OK,基于settings元素配置Configuration的过程告一段落,这一部分的内容相对比较枯燥,也很繁琐,到这里,对这些不同的字段 有个大概的印象就好了。

关注我,一起学习更多知识

关注我