Mybatis源码分析-读取非项目中的xml文件

原创
2018/05/17 17:24
阅读数 243

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">
<!--通过这个配置文件,完成mybatis与数据库的连接  -->
<configuration>
    <environments default="development">
        <environment id="development">
            <!-- 配置事务管理 ,采用JDBC管理事务-->
            <transactionManager type="JDBC"/>
            <!-- POOLED是mybatis的 数据源 -->
            <!-- JNDI是基于tomcat的数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/demo"/>
                <property name="username" value="demo"/>
                <property name="password" value="demo"/>
            </dataSource>
        </environment>
    </environments>
    <!-- pojo的映射文件UserMapper引入到配入到配置文件中 -->
    <mappers>
        <!-- resource要写成路径 -->
        <mapper resource="/mybatis/mapper/demo.xml"/><!-- 项目中的xml文件 -->
        <mapper url="file:///D:/tmp/mybatis/mybatis/mapper/demo.xml"/><!-- 本地磁盘的xml文件 -->
        <mapper url="http://www.gongstring.com/mybatis/demo.xml"/><!-- 远程URL的xml文件 -->
    </mappers>

</configuration>

demo.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="demo" >

    <select id="findByPatientNo" resultType="java.util.Map">
        select * from base_patient where s_code = #{sCode} 
		<if test="patientNo != null">
		and d_code = #{patientNo}
		</if>
    </select>

</mapper>

java调用代码


        Map<String,Object> params = new HashMap<>();
        params.put("sCode","system");
//            params.put("patientNo","111");

        String resource = "D:\\tmp\\mybatis\\mybatis\\mybatis-config.xml";
        try (InputStream inputStream = new FileInputStream(resource)){
            Configuration configuration = new Configuration();
            
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(inputStream);
            datas = factory.openSession().selectList("demo.findBySql",params);
            System.out.println(JSON.toJSONString(datas));

        }catch (Exception e){
            e.printStackTrace();
        }

源码分析

在Mybatis的SqlSessionFactory启动时,会先读取mybatis-config.xml配置文件进行初始化。mappers标签里面配置的xml文件,在XMLConfigBuilder.parseConfiguration(XNode root)方法中进行加载,而mybatis底层提供了几种xml加载方式,支持项目中的xml读取,以及URL的方式。

private void parseConfiguration(XNode root) {
    try {
      propertiesElement(root.evalNode("properties")); //issue #117 read properties first
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      settingsElement(root.evalNode("settings"));
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers")); //加载Mappers中的配置文件
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

mapperElement方法:

private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) { 
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);///////////// 读取本地类路径下面的xml
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);///////////// 读取URL资源中的xml
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

Resources.getUrlAsStream(url)方法:

public static InputStream getUrlAsStream(String urlString) throws IOException {
    URL url = new URL(urlString); ////// 说明支持多种文件读取方式
    URLConnection conn = url.openConnection();
    return conn.getInputStream();
  }
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部