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项目,做了一些必要的准备工作,然后完成了读取数据库配置信息及解析数据库配置信息的编码工作。
到这里,我们就可以调用我们自定义的工具来读取和解析数据库配置信息了,下一篇文章会讲解如何调用这些工具。
出处:https://www.cnblogs.com/blayn/
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?