手写一个MyBatis框架
MyBatis框架分析
- MyBatis框架结构图:
- MyBatis框架组件调用关系图:
- MyBatis框架运行时序图:
手写简单的MyBatis框架
- 根据框架组件调用关系图开发Mybatis框架代码
- 一个组件实体就对应一个实体类
Configuration
public class Configuration {
public <T> T getMapper(Class<T> clazz, SqlSession sqlSession) {
return <T> Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, new MapperProxy(sqlSession));
}
}
SqlSession
public class SqlSession {
private Configuration configuration;
private Executor executor;
/**
* 通过构造函数建立Configuration以及Executor和SqlSession的关系
*/
public SqlSession(Configuration configuration, Executor executor) {
this.configuration = configuration;
this.executor = executor;
}
/**
* getMapper
* @param clazz
*/
public <T> getMapper(class<T> calzz) {
return configuration.getMapper(calzz, this);
}
/**
* selectOne
*
* @param statement SQL语句
* @param parameter SQL参数
* @return <T> T 查询结果
*/
public <T> T selectOne(String statement, String parameter) {
return executor.query(statement, parameter);
}
}
Executor
public interface Executor {
<T> T query(String statement, String parameter);
}
ExecutorImpl
public class ExecutorImpl implements Executor {
@Override
public <T> T query(String statement, String parameter) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db?useUnicode=true&characterEncoding=utf-8");
String sql = String.format(statement, Integer.parseInt(parameter));
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.hasNext()) {
test = new Test();
test.setId(rs.getInt(1));
test.setNum(rs.getInt(2));
test.setName(rs.getString(3));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return (T)test;
}
}
手写完整的MyBatis框架
- 简单的MyBatis框架中的Executor采用JDBC实现,采用了硬编码的方式,一次只能操作一张表:
... while (rs.hasNext()) { test = new Test(); test.setId(rs.getInt(1)); test.setNum(rs.getInt(2)); test.setName(rs.getString(3)); } ...
Executor
ExecutorImpl
public class ExecutorImpl implements Executor {
private Configuration configuration;
public ExecutorImpl(Configuration configuration) {
this.configuration = configuration;
}
public Configuration getConfiguration() {
return configuration;
}
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
public <E> E query(MapperRegistry.MapperData, Object parameter) throws Exception {
/*
* 初始化 StatementHandler -> ParameterHandler -> ResultHandler
*/
StatementHandler handler = new StatementHandler(configuration);
return (E) handler.query(mapperData, parameter);
}
}