mybatis 不允许$_MyBatis(一):配置文件

bf16b8ddfea9c026c9b57864b22a6620.png

一:mybatis流程图

6369e22fe3ef2f76ce1a42c96cda7583.png

二:mybatis配置文件详解(读取Mybatis的内部核心文件并加载映射文件)

1 mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接、属性、类型别名、类型处理器、插件、环境配置、映射器(mapper.xml)等信息。

1.2 映射文件其实是在mybatis-config.xml里配置的。

(1)映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句, 映射文件是在mybatis-config.xml中加载;

(2)可以加载多个映射文件。常见的配置的方式有两种,一种是package扫描包,一种是mapper找到配置文件的位置。

1.3 这个核心配置文件最终会被封装成一个Configuration对象(在构建会话工厂的时候,会解析mybatis-config.xml,然后将相关信息存储到Configuration中)

(1)构建会话工厂类时,解析全局配置文件。

String resource = "mybatis-config.xml";//全局配置文件路径
InputStream inputStream = Resources.getResourceAsStream(resource);//读取xml文件
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//构建会话工厂类

(2)sqlSessionFactory .build(InputStream inputStream);

public SqlSessionFactory build(InputStream inputStream) {
   return build(inputStream, null, null);
}

(3)sqlSessionFactory .build(InputStream inputStream,String environment, Properties properties);

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties){
   try {
      //委托XMLConfigBuilder来解析XML文件
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //XMLConfigBuilder#parse()将配置文件解析
      return build(parser.parse());
   } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
   } finally {
      ErrorContext.instance().reset();
      try {
         inputStream.close();
      } catch (IOException e) {
         // Intentionally ignore. Prefer previous error.
      }
   }
}

(4)XMLConfigBuilder.parse()

public Configuration parse() {
   if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
   }
   parsed = true;
   //mybatis的配置文件的根节点是configuration,从根节点开始解析配置文件
   parseConfiguration(parser.evalNode("/configuration"));
   return configuration;
}

(5)XMLConfigBuilder.parseConfiguration(),这里的XNode是指根节点configuration下所有的节点内容

private void parseConfiguration(XNode root) {
   try {
       //解析子节点properties,该方法是解析properties节点内容;
       propertiesElement(root.evalNode("properties"));
      
       //解析子节点typeAliases 别名,<typeAliases>节点解析 
       typeAliasesElement(root.evalNode("typeAliases"));
      
       //解析子节点plugins 插件,
       //MyBatis允许你在映射语句执行过程中的某一点进行拦截调用。
          //默认情况下,MyBatis允许使用插件来拦截的方法调用包括:
          //Executor:拦截执行器的方法 (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
          //ParameterHandler:拦截参数的处理 (getParameterObject, setParameters)
          //ResultSetHandler:拦截结果集的处理 (handleResultSets, handleOutputParameters)
          //StatementHandler:拦截Sql语法构建的处理 (prepare, parameterize, batch, update, query)
       pluginElement(root.evalNode("plugins"));

       //解析子节点objectFactory mybatis为结果创建对象时都会用到objectFactory
     //每次MyBatis创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作
       objectFactoryElement(root.evalNode("objectFactory"));

       //解析子节点objectWrapperFactory
       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));

       //解析settings定义一些全局性的配置
       settingsElement(root.evalNode("settings"));

       //解析environments 可以配置多个运行环境,解析<environments>节点。
       //但是每个SqlSessionFactory 实例只能选择一个运行环境	
       environmentsElement(root.evalNode("environments"));

       //解析databaseIdProvider MyBatis能够执行不同的语句取决于你提供的数据库供应商。
       //许多数据库供应商的支持是基于databaseId映射
       databaseIdProviderElement(root.evalNode("databaseIdProvider"));

       //解析typeHandlers(类型处理器) 当MyBatis设置参数到PreparedStatement 
       //或者从ResultSet 结果集中取得值时,就会使用TypeHandler 来处理数据库类型与java 类型之间转换
       typeHandlerElement(root.evalNode("typeHandlers"));

       //解析mappers 主要的crud操作都是在mappers中定义的,定义SQL映射语句,告诉MyBatis到哪里去找到这些语句。
       mapperElement(root.evalNode("mappers"));

    } catch (Exception e) {
       throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  }
}

举例:用配置文件列举XMLConfigBuilder.parseConfiguration()都干了什么?

<configuration>
    <!-- 引入jdbc配置文件 -->
    <properties resource="db.properties"/>
    
    <!-- settings配置信息 -->
    <settings>
        <!-- 该配置影响的所有映射器中配置的缓存的全局开关。 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 是否允许单一语句返回多结果集(需要兼容驱动) -->
        <setting name="multipleResultSetsEnabled" value="true"/>
        <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找,可选值:SLF4J|LOG4J|LOG4J2|JDK_LOGGING|COMMONS_LOGGING|STDOUT_LOGGING|NO_LOGGING-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!-- 还有很多,在此就不一一列举了 -->
    </settings>

    <!-- 定义别名 -->
    <typeAliases>
        <!--   <typeAlias type="org.mybatis.example.pojo.Blog" alias="blog" /> --><!-- 手动定义别名 -->
        <!--   扫描包,自动以类名作别名 -->
        <package name="org.mybatis.example.pojo"/>
    </typeAliases>
    
    <!-- 插件扩展 -->
    <plugins>
        <plugin interceptor="org.mybatis.example.ExamplePlugin">
            <property name="someProperty" value="100"/>
        </plugin>
    </plugins>
 
	<!-- 定义数据源 -->
    <environments default="development">
        <environment id="development">
            <!-- 配置事务管理 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源 -->
            <dataSource type="POOLED">
                <!--下面的属性值必须和db.properties中的key对应 -->
                <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="mapper/BlogMapper.xml"/> -->
        <!-- 扫描包,自动绑定映射文件 -->
        <package name="org.mybatis.example.dao"/>
    </mappers>
</configuration>

①propertiesElement

//该方法是解析properties节点内容
<properties resource="db.properties"/>
//或者
<properties resource="org/mybatis/example/db.properties">
      <property name="username" value="xxx"/>
      <property name="password" value="xxxxxx"/>
</properties>

②typeAliasesElement

//该方法用于<typeAliases>节点解析
//类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写;
<!-- 定义别名 -->
<typeAliases>
    <typeAlias alias="Author" type="domain.blog.Author"/>
    <typeAlias alias="Blog" type="domain.blog.Blog"/>
    <typeAlias alias="Comment" type="domain.blog.Comment"/>
    <typeAlias alias="Post" type="domain.blog.Post"/>
    <typeAlias alias="Section" type="domain.blog.Section"/>
    <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

<typeAliases>
    <!--   <typeAlias type="org.mybatis.example.pojo.Blog" alias="blog" /> -->
    <!--   扫描包,自动以类名作别名 -->
    <package name="org.mybatis.example.pojo"/>
</typeAliases>

③pluginElement

MyBatis允许你在映射语句执行过程中的某一点进行拦截调用。 
默认情况下,MyBatis允许使用插件来拦截的方法调用包括:   
    1.Executor:拦截执行器的方法 (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)  
    2.ParameterHandler:拦截参数的处理 (getParameterObject, setParameters)         
    3.ResultSetHandler:拦截结果集的处理 (handleResultSets, handleOutputParameters)      
    4.StatementHandler:拦截Sql语法构建的处理 (prepare, parameterize, batch, update, query)

④objectFactoryElement

private void objectFactoryElement(XNode context) throws Exception {
    //开始解析
    if (context != null) {
        //获取type的值
	String type = context.getStringAttribute("type");
	//子节点作为属性存在
	Properties properties = context.getChildrenAsProperties();
	//同样这里可以用别名
	ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
	//注入属性
	factory.setProperties(properties);
	//非常重要
	configuration.setObjectFactory(factory);
     }
}

⑤objectWrapperFactoryElement

private void objectWrapperFactoryElement(XNode context) throws Exception {
    if (context != null) {
	//获取type的值
	String type = context.getStringAttribute("type");
	//实例化
	ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).newInstance();
	//非常重要
	configuration.setObjectWrapperFactory(factory);
    }
}

⑥settingsElement

<settings>
   	<!-- 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。-->
   	<setting name="cacheEnabled" value="true"/><!-- 默认true-->

   	<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。-->
        <!-- 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。-->
        <setting name="lazyLoadingEnabled" value="false"/><!-- 默认false-->

        <!-- 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载 -->
        <setting name="aggressiveLazyLoading" value="false"/><!-- 默认false-->

        <!-- 是否允许单个语句返回多结果集(需要数据库驱动支持)。-->
        <setting name="multipleResultSetsEnabled" value="true"/><!-- 默认true-->

        <!-- 使用列标签代替列名。实际表现依赖于数据库驱动,可参考数据库驱动的相关文档-->
        <setting name="useColumnLabel" value="true"/><!-- 默认true-->

        <!-- 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键 -->
        <setting name="useGeneratedKeys" value="false"/><!-- 默认false-->

        <!-- 指定 MyBatis 应如何自动映射列到字段或属性。 -->
        <!-- NONE 表示关闭自动映射。 -->
        <!-- PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 -->
        <!-- FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 -->
   	<setting name="autoMappingBehavior" value="PARTIAL"/><!-- 默认PARTIAL-->

        <!-- 指定发现自动映射目标未知列(或未知属性类型)的行为。 -->
        <!-- NONE 不做任何反应 -->
        <!-- WARNING 输出警告日志,日志输出等级必须设置为WARN -->
        <!-- FAILING 映射失败 (抛出 SqlSessionException)  -->
   	<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/><!-- 默认WARNING-->

        <!-- 配置默认的执行器。 -->
        <!-- SIMPLE 就是普通的执行器 -->
        <!-- REUSE 执行器会重用预处理语句(PreparedStatement) -->
        <!-- BATCH 执行器不仅重用语句还会执行批量更新  -->
   	<setting name="defaultExecutorType" value="SIMPLE"/><!-- 默认SIMPLE-->

        <!-- 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 -->
   	<setting name="defaultStatementTimeout" value="25"/><!-- 任意正整数 -->

        <!-- 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 -->
   	<setting name="defaultFetchSize" value="100"/><!-- 任意正整数 -->

        <!-- 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 -->
   	<setting name="safeRowBoundsEnabled" value="false"/>

        <!-- 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 -->
   	<setting name="mapUnderscoreToCamelCase" value="false"/>

        <!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 -->
        <!-- SESSION,会缓存一个会话中执行的所有查询。 -->
        <!-- STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 -->
   	<setting name="localCacheScope" value="SESSION"/>

   	<!-- 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 -->
        <setting name="jdbcTypeForNull" value="OTHER"/>

        <!-- 指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。 -->
   	<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

⑦environmentsElement

<!-- 环境配置,解析<environments>节点 -->
<!-- 但是每个SqlSessionFactory 实例只能选择一个运行环境	-->
<environments default="development">
    <environment id="development">
       <!-- 配置事务管理 -->
       <transactionManager type="JDBC"/>
       <!-- 配置数据源 -->
       <dataSource type="POOLED">
       <!--下面的属性值必须和db.properties中的key对应 -->
             <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>

⑧databaseIdProviderElement

<!-- MyBatis能够执行不同的语句取决于你提供的数据库供应商。 -->
<!-- mybatis中我们可以使用databaseIdProvider这个元素实现数据库兼容不同厂商,即配置多中数据库。 -->
<databaseIdProvider type="DB_VENDOR">
    <!-- 其中的name属性是数据库名称,value是我们自定义的别名 -->
    <property name="Oracle" value="oracle"/>
    <property name="MySQL" value="mysql"/>
    <property name="DB2" value="d2"/>
</databaseIdProvider>

<!-- mapper.xml中使用 -->
<!-- 许多数据库供应商的支持是基于databaseId映射 -->
<select id="getAllProduct" resultType="product" databaseId="mysql">
   SELECT * FROM product
</select>

⑨typeHandlerElement

使用TypeHandler 来处理数据库类型与java 类型之间转换
1.TypeHandler 契约了自定义的对参数和返回值 的处理方法。 
将JDBC里的相关操作进行了尽可能的提取,而将自定义的需求以TypeHandler的形式向外界暴露。
2.针对传入参数进行处理的ParameterHandler(DefaultParameterHandler作为实现类)
  针对返回值进行处理的ResultSetHandler(DefaultResultSetHandler作为唯一实现类)
  它俩的实例化是在针对Statement进行处理的StatementHandler的实现类 BaseStatementHandler的构造函数中完成的。 
  而作为JDBC操作的核心组件的Statement是伴随着每次数据库操作重新生成的。
  所以相对应的ParameterHandler和ResultSetHandler的实现类也会相应的重新构建一份。
3.Mybatis在对JDBC整体流程的深刻理解之上,抽取了尽可能多的重复性代码由框架来完成,
  在此基础上又尽量保证了灵活性。
  并且Mybatis也给了TypeHandler足够的地位,专门分配了顶级package org.apache.ibatis.type。
  在该package中,除了相关辅助类外,绝大部分都是TypeHandler的实现类,
  Mybatis预定义了一堆针对常见JDK类型的TypeHandler。

⑩mapperElement

解析mappers 主要的crud操作都是在mappers中定义的,定义SQL映射语句,
告诉MyBatis到哪里去找到这些语句。
<!-- 使用相对于类路径的资源引用 -->
<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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值