天哪!手动编写mybatis雏形竟然这么简单 (2)

创建SqlMapConfig.xml 和Mapper.xml
SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?> <configuration> <property value="com.mysql.jdbc.Driver"></property> <property value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false"></property> <property value="root"></property> <property value="123456"></property> <mapper resource="UserMapper.xml"> </mapper> </configuration>

可以看到我们xml 中就配置了数据库的连接信息,以及mapper 一个索引。mybatis中的SqlMapConfig.xml 中还包含其他的标签,只是丰富了功能而已,所以我们只用最主要的。

mapper.xml
是每个类的sql 都会生成一个对应的mapper.xml 。我们这里就用User 类来说吧,所以我们就创建一个UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <mapper namespace="cn.quellanan.dao.UserDao"> <select resultType="cn.quellanan.pojo.User"> select * from user </select> <select resultType="cn.quellanan.pojo.User" paramType="cn.quellanan.pojo.User"> select * from user where username=#{username} </select> </mapper>

可以看到有点mybatis 里面文件的味道,有namespace表示命名空间,id 唯一标识,resultType 返回结果集的类型,paramType 参数的类型。
我们使用端先创建到这,主要是两个配置文件,我们接下来看看框架端是怎么实现的。

加油哈哈。

在这里插入图片描述

框架端实现

框架端,我们按照上面的设计思路一步一步来。

获取配置

怎么样获取配置文件呢?我们可以使用JDK自带自带的类Resources加载器来获取文件。我们创建一个自定义Resource类来封装一下:

import java.io.InputStream; public class Resources { public static InputStream getResources(String path){ //使用系统自带的类Resources加载器来获取文件。 return Resources.class.getClassLoader().getResourceAsStream(path); } }

这样通过传入路径,就可以获取到对应的文件流啦。

解析配置文件

上面获取到了SqlMapConfig.xml 配置文件,我们现在来解析它。
不过在此之前,我们需要做一点准备工作,就是解析的内存放到什么地方?
所以我们来创建两个实体类Mapper 和Configuration。

Mapper
Mapper 实体类用来存放使用端写的mapper.xml 文件的内容,我们前面说了里面有.id、sql、resultType 和paramType .所以我们创建的Mapper实体如下:

public class Mapper { private String id; private Class<?> resultType; private Class<?> parmType; private String sql; //getter()和setter()方法 }

这里我们为什么不添加namespace 的值呢?
聪明的你肯定发现了,因为mapper里面这些属性表明每个sql 都对应一个mapper,而namespace 是一个命名空间,算是sql 的上一层,所以在mapper中暂时使用不到,就没有添加了。

Configuration
Configuration 实体用来保存SqlMapConfig 中的信息。所以需要保存数据库连接,我们这里直接用JDK提供的 DataSource。还有一个就是mapper 的信息。每个mapper 有自己的标识,所以这里采用hashMap来存储。如下:

public class Configuration { private DataSource dataSource; HashMap <String,Mapper> mapperMap=new HashMap<>(); //getter()和setter方法 } XmlMapperBuilder

做好了上面的准备工作,我们先来解析mapper 吧。我们创建一个XmlMapperBuilder 类来解析。通过dom4j 的工具类来解析XML 文件。我这里用的dom4j 依赖为:

<dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.3</version> </dependency>

思路:
1、获取文件流,转成document。
2、获取根节点,也就是mapper。获取根节点的namespace属性值
3、获取select 节点,获取其id,sql,resultType,paramType
4、将select 节点的属性封装到Mapper 实体类中。
5、同理获取update/insert/delete 节点的属性值封装到Mapper 中
6、通过namespace.id 生成key 值将mapper对象保存到Configuration实体中的HashMap 中。
7、返回 Configuration实体
代码如下:

public class XmlMapperBuilder { private Configuration configuration; public XmlMapperBuilder(Configuration configuration){ this.configuration=configuration; } public Configuration loadXmlMapper(InputStream in) throws DocumentException, ClassNotFoundException { Document document=new SAXReader().read(in); Element rootElement=document.getRootElement(); String namespace=rootElement.attributeValue("namespace"); List<Node> list=rootElement.selectNodes("//select"); for (int i = 0; i < list.size(); i++) { Mapper mapper=new Mapper(); Element element= (Element) list.get(i); String id=element.attributeValue("id"); mapper.setId(id); String paramType = element.attributeValue("paramType"); if(paramType!=null && !paramType.isEmpty()){ mapper.setParmType(Class.forName(paramType)); } String resultType = element.attributeValue("resultType"); if (resultType != null && !resultType.isEmpty()) { mapper.setResultType(Class.forName(resultType)); } mapper.setSql(element.getTextTrim()); String key=namespace+"."+id; configuration.getMapperMap().put(key,mapper); } return configuration; } }

上面我只解析了select 标签。大家可以解析对应insert/delete/uupdate 标签,操作都是一样的。

XmlConfigBuilder

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

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