手写一个MyBatis框架




MyBatis框架分析


  • MyBatis框架结构图:手写一个MyBatis框架_mybatis
  • MyBatis框架组件调用关系图:手写一个MyBatis框架_sql_02
  • MyBatis框架运行时序图:手写一个MyBatis框架_sql_03

手写简单的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);
}
}