使用 dom4j 技术解析 mapper.xml 映射配置文件

263 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 22 天,点击查看活动详情

上期课程中,使用 dom4j 技术完成对 sql-mapper-config.xml 核心配置文件解析,并利用解析出来的信息创建了一个数据源对象,同时把这个数据源对象设置到 configuration 中。本期课程中,采用 dom4j 技术对 mapper.xml 配置文件进行解析。

如何解析 mapper.xml 配置文件,具体步骤:

  • 获取到 mapper.xml 映射配置文件的路径。
  • 将 mapper.xml 加载成字节输入流。
  • 使用 dom4j 技术解析配置文件。

加载映射配置文件

那么,mapper.xml 映射配置文件的路径存放在哪里的?我们在编写使用端程序时,是不是将 mapper.xml 的路径存放在 sql-mapper-config.xml 核心配置文件中,使用 mapper 标签 的 resource 属性存了一份 mapper.xml 映射配置文件路径。

上期课程中,我们已经使用 dom4j 技术对 sql-mapper-config.xml 核心配置文件进行解析,并获得它的根标签。现在我们通过根标签就可以获取到 mapper 标签,并且拿到 List 集合的返回值。在这个 List 集合中,每一个 mapper 标签都是 Element,并且 Element 代表一个 mapper 标签。

获取到 mapper 标签之后,接着使用 for 循环遍历这个 List 集合,取出每个 mapper 对应的标签,原因是一个项目中有多个模块,而每个模块都对应一个映射配置文件。mapper 标签可能有多个,比如 UserMapper.xml、ProductMapper.xml。

我们真正要获取就是 mapper 标签的 resource 属性的值,那么如何去获取到 resource 属性的值呢?可以根据键值对(K-V)方式获取到它的值,其实,这个就是我们要获取的映射配置文件的路径。

获取到映射配置文件的路径之后,接着把它加载成字节输入流。

public class XMLConfigBuider {
        // ...
        // mapper.xml 解析
        List<Element> mapperLis = rootElement.selectNodes("//mapper");


        for (Element mapperElement : mapperLis) {
            //获取 mapper.xml 映射配置文件的路径
            String mapperPath = mapperElement.attributeValue("resource");


            // 加载映射配置文件,将加载成字节输入流
            InputStream resourceAsStream = Resource.getResourceAsStream(mapperPath);


            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);


            xmlMapperBuilder.parse(resourceAsStream);
        }
        return null;
    }
}

有了前面基础,现在再使用 dom4j 技术解析映射配置文件易如反掌。它的步骤和原理与解析核心配置文件基本一致,只不过解析的标签不一样。

创建 XMLMapperBuilder 类

对于解析映射配置文件的过程,可以再封装一个方法进行解析。创建一个 XMLMapperBuilder 类,用于解析映射配置文件。

在创建 XMLMapperBuilder 对象的时候,思考一下,需要不要传递参数。

使用 dom4j 解析映射配置文件的信息时,并将映射配置文件中 mapper 标签下的每个子标签解析并封装成一个 MapperStatement 实体对象,假设映射配置文件中的 mapper 标签下有多个子标签,在解析过程要封装成多个 MapperStatement 实体对象,最终将所有的封装到 Configuration 实体对象中的 Map 集合上。也就意味在去调用 XMLMapperBuilder 中方法进行 dom4j 技术解析时,应该要传递一个参数,并且这个参数必须是最终能将映射配置文件的信息封装到 Configuration 实体对象中 Map 集合上,所有要传的参数是这个 configuration 实体对象。

具体代码实现如下:

public class XMLMapperBuilder {
    private  Configuration configuration;
    public XMLMapperBuilder(Configuration configuration) {
        this.configuration=configuration;


    }
    public void parse(InputStream inputStream) throws DocumentException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        String namespace = rootElement.attributeValue("namespace");


        List<Element> elementList = rootElement.selectNodes("//select");
        for (Element element : elementList) {
            String id = element.attributeValue("id");
            String resultType = element.attributeValue("resultType");
            String parameterType = element.attributeValue("parameterType");
            //String sql = element.attributeValue("sql");
            String sqlText = element.getTextTrim();


            MapperStatement mapperStatement = new MapperStatement();
            mapperStatement.setId(id);
            mapperStatement.setResultType(resultType);
            mapperStatement.setParameterType(parameterType);
            mapperStatement.setSql(sqlText);
            String key=namespace+"."+id;
            configuration.getMapperStatementMap().put(key,mapperStatement);
        }


    }
}

到本期课程,我们完成 SQL 配置信息以及数据库配置信息的封装,并将所有的信息封装到 configuration 实体对象中,接着把 configuration 对象一直向下传递,直到传递到最终底层执行原生 JDBC 代码中。

小结

本期课程主要完成功能是实现映射配置文件加载以及创建解析配置文件类,在这个类的方法中完成映射配置文件的解析。最终将解析出来的信息封装到 Configuration 实体对象中的 Map 集合中。