MyBatis之配置文件解析_settings节点的处理

settings标签配置

MyBatis配置文件中settings子标签的配置,即是用setting子标签定义一个name及value属性,在解析时将其保存到Configuration对象中,下面是这个标签及其子标签的配置及含义:

<settings>
    <!--允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false,默认值为false -->
    <setting name="safeRowBoundsEnabled" value="false"/>
    <!--允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为false。默认值为true -->
    <setting name="safeResultHandlerEnabled" value="true"/>
    <!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 性名 aColumn 的类似映射,默认值为false -->
    <setting name="mapUnderscoreToCamelCase" value="false"/>    
    <!--当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载,默认值false-->
    <setting name="aggressiveLazyLoading" value="false"/>    
    <!--是否允许单一语句返回多结果集,默认值为true -->
    <setting name="multipleResultSetsEnabled" value="true"/>
    <!--允许 JDBC 支持自动生成主键,需要驱动兼容,默认值为false -->
    <setting name="useGeneratedKeys" value="false"/>
    <!--使用列标签代替列名,默认值为true -->
    <setting name="useColumnLabel" value="true"/>
    
    <!--全局全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为true-->
    <setting name="cacheEnabled" value="true"/>
       
    <!--指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或
        null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。-->
    <setting name="callSettersOnNulls" value="false"/>
    <!--允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。
           (从3.4.1开始)-->
    <setting name="useActualParamName" value="true"/>
   	<!--当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的
            结果集 (i.e. collectioin and association)。(从3.4.2开始-->
    <setting name="returnInstanceForEmptyRow" value="false"/>
    
    <!--指定 MyBatis 增加到日志名称的前缀-->
    <setting name="logPrefix" value="log"/>
    <!--指定 MyBatis 所用日志的具体实现,未指定时将自动查找
            SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING。 -->
    <setting name="logImpl" value="LOG4J"/>
    <!--指定VFS的实现-->
    <setting name="vfsImpl" value="vfs"/>
    <!--MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
         默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语
         句执行上,对相同 SqlSession 的不同调用将不会共享数据。-->
    <setting name="localCacheScope" value="SESSION"/>
    <!--当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情
        况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。默认值为OTHER -->
    <setting name="jdbcTypeForNull" value="OTHER"/>
    <!--指定哪个对象的方法触发一次延迟加载。 -->
    <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>        
    <!--设置超时时间,它决定驱动等待数据库响应的秒数。参数为任意正整数,未设置默认值-->
    <setting name="defaultStatementTimeout" value="25"/>
    <!--为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。参数为任意正整数,
            未设置默认值 -->
    <setting name="defaultFetchSize" value="100"/>
    
    <!--配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements);
            BATCH 执行器将重用语句并执行批量更新。默认值为SIMPLE -->
    <setting name="defaultExecutorType" value="SIMPLE"/>
       
    <!--指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL
            只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集
            (无论是否嵌套),默认值为PARTIAL-->
    <setting name="autoMappingBehavior" value="PARTIAL"/>
    <!--指定发现自动映射目标未知列(或者未知属性类型)的行为。NONE: 不做任何反应;
            ARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'
            的日志等级必须设置为 WARN);FAILING: 映射失败 (抛出 SqlSessionException),默认值为NONE -->
    <setting name="autoMappingUnknownColumnBehavior" value="NONE"/>
    
    <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置
            fetchType属性来覆盖该项的开关状态。默认值为false -->
    <setting name="lazyLoadingEnabled" value="false"/>
        
    <!--指定动态 SQL 生成的默认语言。默认XMLLanguageDriver,Configuration中无对应的成员变量 -->
    <setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
    <!--指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。CGLIB | JAVASSIST,默认为JavassistProxyFactory -->
    <setting name="proxyFactory" value="JAVASSIST"/>
    
    <!--指定一个提供Configuration实例的类。 这个被返回的Configuration实例用来加载被反序列化对象的懒加载属性值。 
            这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始)-->
    <setting name="configurationFactory" value="configClass"/>
</settings>

Configuration中对应的属性

​ 以上settings中的每个setting子标签的name属性都对应了Configuration中的一个属性,下面是Configuration类中定义的对应属性:

// 配置类中的属性,对应XML文件中的配置
public class Configuration {

  protected Environment environment;
  
  protected boolean safeRowBoundsEnabled;
  protected boolean safeResultHandlerEnabled = true;
  // 映射下划线到格式  
  // 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。
  protected boolean mapUnderscoreToCamelCase;
  protected boolean aggressiveLazyLoading;
  //是否允许单一语句返回多结果集(需要兼容驱动)。
  protected boolean multipleResultSetsEnabled = true;
  // 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。
  protected boolean useGeneratedKeys;
  //使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。
  protected boolean useColumnLabel = true;
  // 默认启用缓存,全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存  
  protected boolean cacheEnabled = true;
  protected boolean callSettersOnNulls;
  protected boolean useActualParamName = true;
  protected boolean returnInstanceForEmptyRow;

  protected String logPrefix;
  protected Class<? extends Log> logImpl;
  protected Class<? extends VFS> vfsImpl;
  // MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
  // 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,
  //对相同 SqlSession 的不同调用将不会共享数据。  
  protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
  // 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、   或 OTHER。 
  protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
  // 指定哪个对象的方法触发一次延迟加载。  
  protected Set<String> lazyLoadTriggerMethods = new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString"));
  // 设置超时时间,它决定驱动等待数据库响应的秒数 
  protected Integer defaultStatementTimeout;
  // 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖  
  protected Integer defaultFetchSize;
  protected ResultSetType defaultResultSetType;
  // 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements);  
  protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
  // 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 
  //  FULL 会自动映射任意复杂的结果集(无论是否嵌套)。
  protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
  // 指定发现自动映射目标未知列(或者未知属性类型)的行为。
  //    NONE: 不做任何反应
  //    WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'的日志等级必须设置为 WARN)
  //    FAILING: 映射失败 (抛出 SqlSessionException)  
  protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
  // 以上配置对应着settings中的setting的配置  
    
    
    
  // 属性文件中定义的属性	
  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;
    
  protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL

  protected String databaseId;
    
  // 特别注意,Configuration的无参构造方法,注册了众多类型的别名,mybatis创建一个类型时,一般都是通过别名找到整正的类型。再通过反射创建出 	// 这些对象  
}

settings标签解析

settings标签的解析比较简单,就是 解析每个子setting标签的name及value属性,并设置到Configuration对象中,分为了两步实现:

第1步将settings中每个子节点的name-value转换为Properties对象,并返回,方法中会检测其名字是否是Configuration的属性,如没有则抛出异常,注意此时并没有将值设置到Configuration中,这个在方法settingsAsProperties中实现。

第2步 将第1步中获得的Properties对象,调用Configuration的setXxx方法设置到Configuration对象中,这些配置的名字都与Configuration的属性对应,前面已确保了Properties的名字与Configuration的属性名一致,这个在方法settingsElement中实现。以上两个方法都定义在XMLConfigBuilder中

// 这个方法解析settings标签,将其下的每个子标签settingname-value转换为Properties对象
private Properties settingsAsProperties(XNode context) {
  if (context == null) {
    return new Properties();
  }
  Properties props = context.getChildrenAsProperties();
  // Check that all settings are known to the configuration class
  MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
  // 通过反射检查Configuration中有没有对应的setter方法,如
  // 如setting中的name为mapUnderscoreToCamelCase,则检查Configuration中有无setMapUnderscoreToCamelCase,如没有则抛出异常  
  for (Object key : props.keySet()) {
    if (!metaConfig.hasSetter(String.valueOf(key))) {
      throw new BuilderException("The setting " + key + " is not known.  Make sure you spelled it correctly (case sensitive).");
    }
  }
  return props;
}
// 这个方法即比较直白,就是将上一个方法获得的Properties中的key-value,设置到Configuration对象的key属性中
// 如果没有配置,则设定其默认值,如defaultExecutorType的默认值为SIMPLE
private void settingsElement(Properties props) {
    configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
    configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
    configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
    configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
    configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
    configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
    configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
    configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
    configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
    configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
    configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
    configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
    configuration.setDefaultResultSetType(resolveResultSetType(props.getProperty("defaultResultSetType")));
    configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
    configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
    configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
    configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
    configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
    configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
    configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
    configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
    configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
    configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
    configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
    configuration.setLogPrefix(props.getProperty("logPrefix"));
    configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
  }

posted @   beckwu  阅读(361)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示