五、⼿写MyBatis框架(掌握原理)
5.1 dom4j解析XML⽂件
模块名:parse-xml-by-dom
4
j(普通的Java Maven模块)
第⼀步:引⼊dom
4
j的依赖
<packaging>jar</packaging>
<dependencies>
<!-- dom4j的依赖 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<!--jaxen依赖-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
第⼆步:编写配置⽂件Mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="powernodeDB">
<environment id="powernodeDB">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/powernode"/>
<property name="username" value="root"/>
<property name="password" value="r38153"/>
</dataSource>
</environment>
<!-- 这是Mybatis的另一个环境,连接的数据库是mybatis -->
<environment id="mybatisDB">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="r38153"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载前面编写的SQL语句的文件 -->
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
第三步:解析mybatis-config.xml
@Test
public void testParseMyBatisConfigXML() throws Exception {
//创建SAXReader对象
SAXReader reader = new SAXReader();
//获取输入流
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
//读XML文件,返回document对象,document对象是文档对象,代表了整个XML文件
Document document = reader.read(is);
//获取文档当中的根标签
// Element rootElt = document.getRootElement();
// String rootEltName = rootElt.getName();
//System.out.println("根节点的名字:"+rootEltName); //根节点的名字:configuration
//获取default默认的环境id
//xpath是做标签路径匹配的,能够让我们快速定位XML文件中的元素
//以下的xpath代表了:从根下开始找configuration标签,然后找configuration标签下的子标签environments
String xpath = "/configuration/environments";
Element environments = (Element) document.selectSingleNode(xpath); //Element 是Node类的子类,方法更多,使用更便捷
//获取属性的值
String defaultEnvironmentId = environments.attributeValue("default");
System.out.println("默认环境的id:" + defaultEnvironmentId); //默认环境的id:powernodeDB
//获取具体的环境environment
xpath = "/configuration/environments/environment[@id='" + defaultEnvironmentId + "']";
Element environment = (Element) document.selectSingleNode(xpath);
//获取属性的值
String id = environment.attributeValue("id");
System.out.println(id); //powernodeDB
//获取environment节点下的transactionManager节点 (element()方法用来获取孩子节点)
Element transactionManager = environment.element("transactionManager");
String transactionType = transactionManager.attributeValue("type");
System.out.println("事物管理器类型:"+transactionType); //事物管理器类型:JDBC
//获取datasource节点
Element dataSource = environment.element("dataSource");
String dataSourceType = dataSource.attributeValue("type");
System.out.println("数据源的类型:"+dataSourceType); //数据资源的类型:POOLED
//获取dataSource节点下的所有子节点
List<Element> propertyElts = dataSource.elements();
propertyElts.forEach(propertyElt ->{
String name = propertyElt.attributeValue("name");
String value = propertyElt.attributeValue("value");
System.out.println(name + ":" + value);//username:root password:r38153
});
//获取所有的mapper标签
//不想从跟下开始获取,你想从任意位置开始,获取所有的某个标签,xpath该这样写
xpath="//mapper";
List<Node> mappers = document.selectNodes(xpath);
mappers.forEach(mapper ->{
Element mapperElt = (Element) mapper;
String resource = mapperElt.attributeValue("resource");
System.out.println(resource); //CarMapper.xml
});
}
第四步:编写配置⽂件Carmapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="car">
<insert id="insertCar">
insert into t_car values (null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>
<select id="selectById" resultType="com.powenode.mybatis.bean.Car">
select
id,car_num as carNum,brand,guide_price as guidePrice,
produce_time as produceTime,car_type as carType
from
t_car
where
id=#{id}
</select>
</mapper>
第五步:解析Carmapper.xml
@Test
public void testParseSqlMapperXML() throws Exception{
//创建SAXReader对象
SAXReader reader = new SAXReader();
//获取输入流
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("CarMapper.xml");
//读XML文件,返回document对象,document对象是文档对象,代表了整个XML文件
Document document = reader.read(is);
//获取namespace
String xpath="/mapper";
Element mapper = (Element) document.selectSingleNode(xpath);
String namespace = mapper.attributeValue("namespace");
System.out.println(namespace); //car
//获取mapper节点下的所有的子节点
List<Element> elements = mapper.elements();
elements.forEach(element -> {
//获取sqlId
String id = element.attributeValue("id");
System.out.println(id);
// insertCar
// selectById
//获取resultType
String resultType = element.attributeValue("resultType"); //没有这个属性的话,会返回"null"
System.out.println(resultType);
//null
//com.powenode.mybatis.bean.Car
//获取标签中的sql语句(表示获取标签中的文本内容,而且去除前后空白)
String sql = element.getTextTrim();
System.out.println(sql);
//insert into t_car values (null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
//select id,car_num as carNum,brand,guide_price as guidePrice, produce_time as produceTime,car_type as carType from t_car where id=#{id}
//想直接转成insert into t_car values (null,?,?,?,?,?)
String newSql = sql.replaceAll("#\\{[0-9A-Za-z_$]*}", "?");
System.out.println(newSql); //insert into t_car values (null,?,?,?,?,?)
});
}