手写mybatis
包结构
执行流程
第一步定义User实体类和UserMapper接口
User实体类
package com.tedu;
public class User {
int id;
String username;
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
UserMapper接口
package com.tedu;
import java.util.List;
public interface UserMapper {
public List findAll();
}
第二步创建配置文件UserMapper.xml和mybatis-config.xml配置文件
UserMapper.xml
mybatis-config.xml
第三步定义存放sql语句的实体类SqlMapper
package org.mybais.configuration;
//UserMapper.xml
public class SqlMapper {
String id;
String resultType;
String sql;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public SqlMapper(String id, String resultType, String sql) {
super();
this.id = id;
this.resultType = resultType;
this.sql = sql;
}
@Override
public String toString() {
return "SqlMapper [id=" + id + ", resultType=" + resultType + ", sql=" + sql + "]";
}
}
第四步定义存放连接数据源的信息的实体类Configuration
package org.mybais.configuration;
//mybatis-config.xml
import java.util.HashMap;
public class Configuration {
String url;
String driver;
String username;
String password;
HashMap sqlMappers;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
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;
}
public HashMap getSqlMappers() {
return sqlMappers;
}
public void setSqlMappers(HashMap sqlMappers) {
this.sqlMappers = sqlMappers;
}
@Override
public String toString() {
return "Configuration [url=" + url + ", driver=" + driver + ", username=" + username + ", password=" + password
+ ", sqlMappers=" + sqlMappers + "]";
}
}
第五步创建XmlConfigParser类
解析xml中的信息,将数据源的信息还有sql语句的信息封装在对象中
package org.mybais.configuration;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
//解析mybatis-config.xml和mapper.xml
public class XmlConfigParser {
public static Configuration configuration=new Configuration();
public void parser(InputStream inputStream) throws Throwable{
SAXReader saxReader=new SAXReader();
Document document=saxReader.read(inputStream);
List propertyElments=document.selectNodes("//property");
for (Element element:propertyElments) {
String valueOfName=element.attributeValue("name");
String value=element.attributeValue("value");
System.out.println(valueOfName+":"+value);
switch (valueOfName) {
case "driver":
configuration.setDriver(value);
break;
case "url":
configuration.setUrl(value);
break;
case "username":
configuration.setUsername(value);
break;
case "password":
configuration.setPassword(value);
break;
default:
break;
}
}
System.out.println(configuration);
//解析所有的mapper.xml
List mapperElements=document.selectNodes("//mapper");
for (Element element:mapperElements) {
String mapperFileName=element.attributeValue("resource");
System.out.println("mapperFileName="+mapperFileName);
parseMapper(mapperFileName);
}
System.out.println(configuration);
}
private void parseMapper(String mapperFileName) throws Throwable {
ClassLoader classLoader=XmlConfigParser.class.getClassLoader();
InputStream inputStream=classLoader.getResourceAsStream(mapperFileName);
SAXReader saxReader=new SAXReader();
Document document=saxReader.read(inputStream);
HashMap sqlMappers=new HashMap<>();
configuration.setSqlMappers(sqlMappers);
List selectElements=document.selectNodes("//select");
for (Element element:selectElements) {
String id=element.attributeValue("id");
String resultType=element.attributeValue("resultType");
String sql=element.getText();
SqlMapper sqlMapper=new SqlMapper(id, resultType, sql);
sqlMappers.put(id, sqlMapper);
}
}
}
第六步定义sqlsession来调用代理类对象
package org.mybais.executor;
import java.lang.reflect.Proxy;
public class SqlSession {
public Object getMapper(Class clazz) {
ClassLoader classLoader=clazz.getClassLoader();
Class[] interfaces= {clazz};
MapperProxy mapperProxy=new MapperProxy();
return Proxy.newProxyInstance(classLoader, interfaces, mapperProxy);
}
}
第七步定义代理类对象来执行数据库连接并获取执行结果
package org.mybais.executor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import org.mybais.configuration.Configuration;
import org.mybais.configuration.SqlMapper;
import org.mybais.configuration.XmlConfigParser;
public class MapperProxy implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke");
String methodName=method.getName();
System.out.println("methodName="+methodName);
//从XmlConfigParser.configuration得到url,driver,username,password
//1,创建连接
Configuration configuration=XmlConfigParser.configuration;
String driver=configuration.getDriver();
Class.forName(driver);
Connection connection=DriverManager.getConnection
(configuration.getUrl(),
configuration.getUsername(),
configuration.getPassword());
System.out.println(connection);
//2,读取数据库
//2.1 得到id
String interfaceName=method.getDeclaringClass().getName();
String id=interfaceName+"."+methodName;
System.out.println("id="+id);
//2.2 从configuration.hashmap中根据id得到 sqlMapper
SqlMapper sqlMapper=configuration.getSqlMappers().get(id);
//2.3 得到 sql
String sql=sqlMapper.getSql();
System.out.println("sql="+sql);
PreparedStatement preparedStatement=connection.prepareStatement(sql);
ResultSet resultSet=preparedStatement.executeQuery();
//3,读到表的列名id,username
List
第八步编写测试类,调用sqlSession对象去访问数据库
package com.tedu;
import java.beans.XMLDecoder;
import java.io.InputStream;
import java.util.List;
import org.mybais.configuration.XmlConfigParser;
import org.mybais.executor.SqlSession;
public class TestMybatis {
public static void main(String[] args) throws Throwable {
ClassLoader classLoader = TestMybatis.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("mybatis-config.xml");
XmlConfigParser xmlConfigParser = new XmlConfigParser();
xmlConfigParser.parser(inputStream);
SqlSession session=new SqlSession();
Object proxy=session.getMapper(UserMapper.class);
UserMapper userMapper=(UserMapper) proxy;
List list =userMapper.findAll();
System.out.println("main----------");
System.out.println(list);
}
}