目录
2.4 定义建造SqlSessionFactory的建造者类
(1)使用读取配置文件的方式并且只定义接口,不使用接口的实现类
(2)使用读取配置文件的方式并且只定义接口,使用接口的实现类
1.自定义mybatis的预先分析
通过上一篇中最后实现类的编写我们可以发现:mybatis在使用代理mapper的方式实现增删改查时做的事:
- 1.创建代理对象
- 2.在代理对象中调用selectList方法
查询所有分析图:
创建代理对象的分析图:
2.代码实现
自定义的mybatis的结构:
由于下面要用到dom4j和jaxen,pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.edu.cqu</groupId>
<artifactId>MybatisDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- mybatis的驱动jar包的坐标 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 单元测试的jar包的坐标 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
</project>
2.1 使用类加载器读取配置文件返回流
package cn.cqu.mybatis.io;
import java.io.InputStream;
/**
* 使用类加载器读取配置文件的类
*/
public class Resources {
public static InputStream getResourceAsStream(String filePath){
/**
* 1.拿到当前类的字节码
* 2.获取字节码的类加载器
* 3.根据类加载器来读取配置
*/
return Resources.class.getClassLoader().getResourceAsStream(filePath);
}
}
2.2 封装从主配置文件中读取的信息的配置类
package cn.cqu.mybatis.cfg;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义mybatis的配置类
*/
public class Configuration {
//连接数据库的信息
private String driver;
private String url;
private String username;
private String password;
/**
* 从mapper配置文件中读到的信息被封装之后的键值对,
*
* key:Mapper标签中namespace对应的全限定类名(映射的类)+点+select标签的id(映射的方法)
* value:封装sql语句和映射的实体类全限定类名的Mapper对象
*/
private Map<String,Mapper> mappers = new HashMap<>();
public Map<String, Mapper> getMappers() {
return mappers;
}
public void setMappers(Map<String, Mapper> mappers) {
this.mappers.putAll(mappers); //此处需要使用追加的方式
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.3 封装从Mapper配置文件中读取出来的信息的类
package cn.cqu.mybatis.cfg;
/**
* 用于封装执行的sql语句和结果类型的全限定类名
*/
public class Mapper {
//Sql语句
private String queryString;
//映射的实体类全限定类名
private String resultType;
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
}
2.4 解析配置文件或注解的类
package cn.cqu.mybatis.utiils;
import cn.cqu.mybatis.annotations.Select;
import cn.cqu.mybatis.cfg.Configuration;
import cn.cqu.mybatis.cfg.Mapper;
import cn.cqu.mybatis.io.Resources;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用于解析配置文件,并把解析后的信息封装为Configuration对象
*/
public class XMLConfigBuilder {
/**
* 解析主配置文件,把里面的内容填充到DefaultSqlSession所需要的地方
* 使用的技术:
* dom4j+xpath
*/
public static Configuration loadConfiguration(InputStream config){
try{
//定义封装连接信息的配置对象(mybatis的配置对象)
Configuration cfg = new Configuration();
//1.获取SAXReader对象
SAXReader reader = new SAXReader();
//2.根据字节输入流获取Document对象
Document document = reader.read(config);
//3.获取根节点
Element root = document.getRootElement();
//4.使用xpath中选择指定节点的方式,获取所有property节点
List<Element> propertyElements = root.selectNodes("//property");
//5.遍历节点
for(Element propertyElement : propertyElements){
//判断节点是连接数据库的哪部分信息
//取出name属性的值
String name = propertyElement.attributeValue("name");
if("driver".equals(name)){
//表示驱动
//获取property标签value属性的值
String driver = propertyElement.attributeValue("value");
cfg.setDriver(driver);
}
if("url".equals(name)){
//表示连接字符串
//获取property标签value属性的值
String url = propertyElement.attributeValue("