Mybatis学习之自定义持久层框架(三) 自定义持久层框架:读取并解析配置文件

前言

前两篇文章分别讲解了JDBC和Mybatis的基本知识,以及自定义持久层框架的设计思路,从这篇文章开始,我们正式来实现一个持久层框架。

新建一个项目

首先我们新建一个maven项目,将其命名为IPersistence,创建以下目录结构:

完成目录创建工作后,我们首先在pom.xml文件中引入相关依赖:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.hardy</groupId>
 8     <artifactId>IPersistence</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <properties>
12         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
14         <java.version>1.8</java.version>
15         <maven.compiler.source>1.8</maven.compiler.source>
16         <maven.compiler.target>1.8</maven.compiler.target>
17     </properties>
18 
19     <dependencies>
20         <dependency>
21             <groupId>mysql</groupId>
22             <artifactId>mysql-connector-java</artifactId>
23             <version>8.0.19</version>
24         </dependency>
25         <dependency>
26             <groupId>c3p0</groupId>
27             <artifactId>c3p0</artifactId>
28             <version>0.9.1.2</version>
29         </dependency>
30         <dependency>
31             <groupId>log4j</groupId>
32             <artifactId>log4j</artifactId>
33             <version>1.2.16</version>
34         </dependency>
35         <dependency>
36             <groupId>junit</groupId>
37             <artifactId>junit</artifactId>
38             <version>4.12</version>
39         </dependency>
40         <dependency>
41             <groupId>dom4j</groupId>
42             <artifactId>dom4j</artifactId>
43             <version>1.6.1</version>
44         </dependency>
45         <dependency>
46             <groupId>jaxen</groupId>
47             <artifactId>jaxen</artifactId>
48             <version>1.1.6</version>
49         </dependency>
50     </dependencies>
51 
52 </project>

下面,就可以开始正式的编码工作了。

读取配置文件

前面讲到了,第一步是要读取数据库配置的相关信息,以流的形式将其存放在内存中。那么首先我们就要在上图“io”包下创建一个Resources类,编写如下代码:

 1 package com.hardy.io;
 2 
 3 import java.io.InputStream;
 4 
 5 public class Resources {
 6 
 7     // 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中
 8     public static InputStream getResourceAsStream(String path) {
 9         InputStream resourceAsStream = Resources.class.getClassLoader().getResourceAsStream(path);
10         return resourceAsStream;
11     }
12 }

这个类的调用方法十分简单,直接传递配置文件的路径名作为参数即可。

解析配置文件

创建容器对象

上面读取完配置文件的信息后,仅仅是将其以输入流的形式存放在内存中,而我们在项目开发过程中,需要调用到这些配置信息中的很多不同属性,如果每次都从内存中读取数据流,是很不方便的。

这里我们将配置文件分为核心配置文件(提供存放数据库核心配置的信息)和映射配置文件(提供sql配置信息(包括sql语句、参数类型和返回类型))。因此,我们可以在“pojo”包下创建两个容器对象类,分别命名为Configuration(存放核心配置信息)和MappedStatement(存放映射配置信息),编写如下代码:

 1 package com.hardy.pojo;
 2 
 3 import javax.sql.DataSource;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 
 7 /*
 8     Configuration:
 9     核心配置类,存放数据库基本信息
10     即sqlMapConfig.xml解析出来的内容
11     */
12 public class Configuration {
13 
14     private DataSource dataSource;
15 
16     /*
17         key: statementId value: 封装好的mappedStatement对象
18         */
19     Map<String, MappedStatement> mappedStatementMap = new HashMap<>();
20 
21     public DataSource getDataSource() {
22         return dataSource;
23     }
24 
25     public void setDataSource(DataSource dataSource) {
26         this.dataSource = dataSource;
27     }
28 
29     public Map<String, MappedStatement> getMappedStatementMap() {
30         return mappedStatementMap;
31     }
32 
33     public void setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) {
34         this.mappedStatementMap = mappedStatementMap;
35     }
36 
37 }
 1 package com.hardy.pojo;
 2 
 3 // Mapper.xml文件中一个select标签对应一个MappedStatement对象
 4 
 5 /*
 6     映射配置类:
 7     存放sql语句、statement类型、输入参数java类型、输出参数java类型
 8     即Mapper.xml解析出来的内容
 9     */
10 public class MappedStatement {
11 
12     // id标识
13     private String id;
14 
15     // sql语句
16     private String sql;
17 
18     // 输入参数值类型
19     private String parameterType;
20 
21     // 返回结果集类型
22     private String resultType;
23 
24     public String getId() {
25         return id;
26     }
27 
28     public void setId(String id) {
29         this.id = id;
30     }
31 
32     public String getSql() {
33         return sql;
34     }
35 
36     public void setSql(String sql) {
37         this.sql = sql;
38     }
39 
40     public String getParameterType() {
41         return parameterType;
42     }
43 
44     public void setParameterType(String parameterType) {
45         this.parameterType = parameterType;
46     }
47 
48     public String getResultType() {
49         return resultType;
50     }
51 
52     public void setResultType(String resultType) {
53         this.resultType = resultType;
54     }
55 
56 }

创建配置文件解析类

上面创建了存放配置文件信息的两个容器对象,但配置文件信息不会自动存放到容器对象中,因此我们还需要编写两个配置文件信息的解析类,可以在“config”包下分别创建XMLConfigBuilder和XMLMapperBuilder,编写以下代码:

 1 package com.hardy.config;
 2 
 3 import com.hardy.io.Resources;
 4 import com.hardy.pojo.Configuration;
 5 import com.mchange.v2.c3p0.ComboPooledDataSource;
 6 import org.dom4j.Document;
 7 import org.dom4j.DocumentException;
 8 import org.dom4j.Element;
 9 import org.dom4j.io.SAXReader;
10 
11 import java.beans.PropertyVetoException;
12 import java.io.InputStream;
13 import java.util.List;
14 import java.util.Properties;
15 
16 public class XMLConfigBuilder {
17 
18     private Configuration configuration;
19 
20     public XMLConfigBuilder(Configuration configuration) {
21         this.configuration = new Configuration();
22     }
23 
24     /*
25     该方法就是使用dom4j对配置文件进行解析,封装成Configuration
26     */
27     public Configuration parseConfiguration(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException {
28 
29         // 1、解析sqlMapConfig.xml
30         /*
31         * 这里需要注意一下:Document和Element等类用的都是org.dom4j库中的类,而不是javax.swing的
32         * 若编译器自动导入了javax.swing,需要手动删除,否则会报错
33         * */
34         Document document = new SAXReader().read(inputStream);
35         //<configuation>
36         Element rootElement = document.getRootElement();
37         List<Element> propertyElements =
38                 rootElement.selectNodes("//property");
39         Properties properties = new Properties();
40         for (Element propertyElement : propertyElements) {
41             String name = propertyElement.attributeValue("name");
42             String value = propertyElement.attributeValue("value");
43             properties.setProperty(name,value);
44         }
45         // 连接池
46         ComboPooledDataSource comboPooledDataSource = new
47                 ComboPooledDataSource();
48         comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
49         comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
50         comboPooledDataSource.setUser(properties.getProperty("username"));
51         comboPooledDataSource.setPassword(properties.getProperty("password"));
52 
53         // 填充configuration
54         configuration.setDataSource(comboPooledDataSource);
55 
56         // 2、解析UserMapper.xml:拿到路径——获取字节输入流——使用dom4j进行解析
57         List<Element> mapperElements = rootElement.selectNodes("//mapper");
58         XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
59         for (Element element : mapperElements) {
60             String mapperPath = element.attributeValue("resource");
61             InputStream resourceAsStream = Resources.getResourceAsStream(mapperPath);
62             xmlMapperBuilder.parse(resourceAsStream);
63         }
64 
65         return configuration;
66     }
67 }
 1 package com.hardy.config;
 2 
 3 import com.hardy.pojo.Configuration;
 4 import com.hardy.pojo.MappedStatement;
 5 import com.hardy.pojo.SqlOperationEnum;
 6 import org.dom4j.Document;
 7 import org.dom4j.DocumentException;
 8 import org.dom4j.Element;
 9 import org.dom4j.io.SAXReader;
10 
11 import java.io.InputStream;
12 import java.util.List;
13 
14 public class XMLMapperBuilder {
15 
16     private Configuration configuration;
17 
18     public XMLMapperBuilder(Configuration configuration) {
19         this.configuration = configuration;
20     }
21 
22     // 解析mapper.xml文件
23     public void parse(InputStream inputStream) throws DocumentException {
24         Document document = new SAXReader().read(inputStream);
25         Element rootElement = document.getRootElement();
26 
27         String namespace = rootElement.attributeValue("namespace");
28 
29         List<Element> elementList = rootElement.elements();
30         for (Element element : elementList) {
31             // id的值
32             String id = element.attributeValue("id");
33             // 输入参数类型
34             String parameterType = element.attributeValue("parameterType");
35             // 返回结果集类型
36             String resultType = element.attributeValue("resultType");
37             // sql语句
38             String sqlText = element.getTextTrim();
39 
40             // 封装mappedStatement
41             MappedStatement mappedStatement = new MappedStatement();
42             mappedStatement.setId(id);
43             mappedStatement.setParameterType(parameterType);
44             mappedStatement.setResultType(resultType);
45             mappedStatement.setSql(sqlText);
46 
47             // 获取sql操作名,并将其转换为大写
48             String elementName = element.getName();
49             mappedStatement.setSqlOperationEnum(SqlOperationEnum.valueOf(elementName.toUpperCase()));
50 
51             // statementId
52             String key = namespace + "." + id;
53 
54             //填充configuration
55             configuration.getMappedStatementMap().put(key, mappedStatement);
56 
57         }
58     }
59 
60 }

总结

本篇文章中,我们创建了IPersistence项目,做了一些必要的准备工作,然后完成了读取数据库配置信息及解析数据库配置信息的编码工作。

到这里,我们就可以调用我们自定义的工具来读取和解析数据库配置信息了,下一篇文章会讲解如何调用这些工具。

作者:blayn
出处:https://www.cnblogs.com/blayn/
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
原文地址:https://www.cnblogs.com/blayn/p/12829872.html