自己动手写一个持久层框架 (2)

UserMapper.xml

<mapper namespace="user"> <!--sql的唯一标识:namespace.id来组成 :statementId--> <select resultType="com.dxh.pojo.User"> select * from user </select> <select resultType="com.dxh.pojo.User" paramterType="com.dxh.pojo.User"> select * from user where id = #{id} and username = #{userName} </select> </mapper>

Q:
为什么要有namespace和id ?
A:
当一个*Mapper.xml中有多条sql时,无法区分具体是哪一条所以增加 id
如果有UserMapper.xml和ProductMapper.xml,假设他们的查询的id都为”selectList“,那么将无法区分具体是查询user还是查询product的。
所以增加 namespace
namespace.id 组成sql的唯一标识,也称为statementId

sqlMapConfig.xml

<configuration> <!--数据库配置信息 --> <dataSource> <property value="com.mysql.jdbc.Driver"></property> <property value="jdbc:mysql:///zdy_mybatis"></property> <property value="root"></property> <property value="root"></property> </dataSource> <!--存放mapper.xml全路径--> <mapper resource="UserMapper.xml"></mapper> </configuration> 4. 开始编写持久层框架 自定义持久层框架(工程):

本质就是对JDBC代码进行了封装

加载配置文件:根据配置文件的路径加载配置文件成字节输入流,存储内存中

创建Resources类 方法:getResourceAsStream(String path)

创建两个javaBean:(容器对象):存放的就是配置文件解析出来的内容

Configuration:核心配置类:存放sqlMapConfig.xml解析出来的内容

MappedStatement:映射配置类:存放mapper.xml解析出来的内容

解析配置文件:使用dom4j

创建类:SqlSessionFactoryBuilder 方法:build(InputStream in) 这个流就是刚才存在内存中的

使用dom4j解析配置文件,将解析出来的内容封装到容器对象中

创建SqlSessionFactory对象;生产sqlSession:会话对象(工厂模式 降低耦合,根据不同需求生产不同状态的对象)

创建sqlSessionFactory接口及实现类DefaultSqlSessionFactory

openSession(); 生产sqlSession

创建SqlSession接口及实现类DefaultSession

定义对数据库的CRUD操作

创建Executor接口及实现类SimpleExecutor实现类

query(Configuration con,MappedStatement ms,Object ...param);执行JDBC代码,Object ...param具体的参数值,可变参;

我们之前已经对持久层框架进行了分析,需要做6部分组成,如下:

1. 加载配置文件

我们要把用户端的配置文件成字节输入流并存到内存中:

新建Resource类,提供一个static InputStream getResourceAsStream(String path)方法,并返回inputstream

package com.dxh.io; import java.io.InputStream; public class Resource { //根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中 public static InputStream getResourceAsStream(String path){ InputStream resourceAsStream = Resource.class.getClassLoader().getResourceAsStream(path); return resourceAsStream; } } 2. 创建JavaBean(容器对象)

之前我们说到,要把解析出来的配置文件封装成对象。

MappedStatement (存放SQL信息)

Configuration (存放数据库配置信息)

// MappedStatement,我们存放SQL的信息 package com.dxh.pojo; public class MappedStatement { // id标识 private String id; //返回值类型 private String resultType; //参数值类型 private String paramterType; //sql语句 private String sql; getset省略... }

这里我们把封装好的MappedStatement对象也放在Configuration中,同时我们不存放数据库的url、username...了,直接存放DataSource

package com.dxh.pojo; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; public class Configuration { private DataSource dataSource; /** * key statementId (就是namespace.id) * value:封装好的MappedStatement对象 */ Map<String,MappedStatement> mappedStatementMap = new HashMap<>(); getset省略... } 3.解析xml文件

这一步我们解析两个xml文件sqlMapConfig.xml、mapper.xml

我们首先把解析的过程封装起来:新建XMLConfigBuild.java

package com.dxh.config; import com.dxh.io.Resource; import com.dxh.pojo.Configuration; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.beans.PropertyVetoException; import java.io.InputStream; import java.util.List; import java.util.Properties; public class XMLConfigBuild { private Configuration configuration; public XMLConfigBuild() { this.configuration = new Configuration(); } /** * 该方法就是将配置文件进行解析(dom4j),封装Configuration */ public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException { Document document = new SAXReader().read(inputStream); //<configuration> Element rootElement = document.getRootElement(); List<Element> list = rootElement.selectNodes("//property"); Properties properties = new Properties(); for (Element element : list) { String name = element.attributeValue("name"); String value = element.attributeValue("value"); properties.setProperty(name,value); } //C3P0连接池 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass(properties.getProperty("driverClass")); comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl")); comboPooledDataSource.setUser(properties.getProperty("username")); comboPooledDataSource.setPassword(properties.getProperty("password")); configuration.setDataSource(comboPooledDataSource); //mapper.xml解析 :拿到路径--字节输入流---dom4j解析 List<Element> mapperList = rootElement.selectNodes("//mapper"); for (Element element : mapperList) { //拿到路径 String mapperPath = element.attributeValue("resource"); //字节输入流 InputStream resourceAsStream = Resource.getResourceAsStream(mapperPath); //dom4j解析 // 因为解析完成后的MappedStatement要放在Configuration里,所以传入一个configuration进去 XMLMapperBuild xmlMapperBuild = new XMLMapperBuild(configuration); xmlMapperBuild.parse(resourceAsStream); } return configuration; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjfwx.html