串台了06还没看,不小心先看了07 不过问题不大,06讲的是数据源池化,也是挺重要的,下次再补上.
之前的05中,先是简单的实现了selectOne,把数据源连接查询什么的都写在里面了,那就没办法复用了,所以这一章就把那些可重复利用的代码择出来.
Executor
将这些查询数据库常用的步骤整合起来,后面再慢慢补充其他
package com.linnine.mybatis.executor;
/**
* sql执行器 接口
* @author linnine09
* @create 2022/8/3 10:48
*/
public interface Executor {
ResultHandler NO_RESULT_HANDLER = null;
/**
* 默认查询
* @param ms
* @param parameter
* @param resultHandler
* @param boundSql
* @param <E>
* @return
*/
<E> List<E> query(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql);
/**
* 获取事务
* @return
*/
Transaction getTransaction();
/**
* 提交事务
* @param required
* @throws SQLException
*/
void commit(boolean required) throws SQLException;
/**
* 回滚
* @param required
* @throws SQLException
*/
void rollback(boolean required) throws SQLException;
/**
* 关闭事务
* @param forceRollback
*/
void close(boolean forceRollback) throws SQLException;
}
BaseExecutor
将一些通用的过程在这个基类抽象类中实现
package com.linnine.mybatis.executor;
/**
* 执行器 抽象基类
* @author linnine09
* @create 2022/8/3 11:00
*/
public abstract class BaseExecutor implements Executor{
protected Configuration configuration;
protected Transaction transaction;
protected Executor wrapper;
private boolean closed;
public BaseExecutor(Configuration configuration, Transaction transaction) {
this.configuration = configuration;
this.transaction = transaction;
this.wrapper=this;
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql){
if (closed){
throw new RuntimeException("Executor was closed.");
}
return doQuery(ms,parameter,resultHandler,boundSql);
}
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql);
@Override
public void commit(boolean required) throws SQLException {
if (closed){
throw new RuntimeException("Executor was closed.");
}
if (required){
transaction.commit();
}
}
@Override
public Transaction getTransaction() {
return this.transaction;
}
@Override
public void rollback(boolean required) throws SQLException {
if (closed){
throw new RuntimeException("Executor was closed.");
}
if (required){
transaction.rollback();
}
}
@Override
public void close(boolean forceRollback) throws SQLException {
if (closed){
throw new RuntimeException("Executor was closed.");
}
if (forceRollback){
transaction.close();
}
}
}
SimpleExecutor
整合基本的查询步骤
package com.linnine.mybatis.executor;
/**
* @author linnine09
* @create 2022/8/3 11:10
*/
public class SimpleExecutor extends BaseExecutor{
public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}
@Override
protected <E> List<E> doQuery(MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql) {
Configuration configuration = ms.getConfiguration();
//这个类在下面
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, resultHandler, boundSql);
try {
Connection connection = transaction.getConnection();
Statement statement = handler.prepare(connection);
handler.parameterize(statement);
return handler.query(statement,resultHandler);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
}
StatementHandler
处理一下sql语句
package com.linnine.mybatis.executor.statement;
/**
* 语句处理器
* @author linnine09
* @create 2022/8/3 11:27
*/
public interface StatementHandler {
/**
* 准备语句
* @param connection
* @return
* @throws SQLException
*/
Statement prepare(Connection connection) throws SQLException;
/**
* 参数化
* @param statement
* @throws SQLException
*/
void parameterize(Statement statement) throws SQLException;
/**
* 执行查询
* @param statement
* @param resultHandler
* @param <E>
* @return
* @throws SQLException
*/
<E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;
}
BaseStatementHandler
还是一个基类抽象类 实现一些通用的
package com.linnine.mybatis.executor.statement;
/**
* 语句处理 基础抽象类
* @author linnine09
* @create 2022/8/3 11:33
*/
public abstract class BaseStatementHandler implements StatementHandler {
protected final Configuration configuration;
protected final Executor executor;
protected final MappedStatement mappedStatement;
protected final Object parameterObject;
protected final ResultSetHandler resultSetHandler;
protected BoundSql boundSql;
public BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.parameterObject = parameterObject;
this.resultSetHandler = configuration.newResultSetHandler(executor,mappedStatement,boundSql);
this.boundSql = boundSql;
}
@Override
public Statement prepare(Connection connection) throws SQLException {
Statement statement = instantiateStatement(connection);
//设置超时时间
statement.setQueryTimeout(350);
statement.setFetchSize(10000);
return statement;
}
/**
* 实例化
* @param connection
* @return
* @throws SQLException
*/
protected abstract Statement instantiateStatement(Connection connection) throws SQLException;
}
PreparedStatementHandler
补充一些预处理的实现细节
package com.linnine.mybatis.executor.statement;
/**
* 语句预处理类
* @author linnine09
* @create 2022/8/3 11:41
*/
public class PreparedStatementHandler extends BaseStatementHandler{
public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameterObject, resultHandler, boundSql);
}
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
String sql = boundSql.getSql();
return connection.prepareStatement(sql);
}
@Override
public void parameterize(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.setLong(1, Long.parseLong(((Object[]) parameterObject)[0].toString()));
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
}
ResultSetHandler
将结果集映射成出参类集合
package com.linnine.mybatis.executor.reultset;
/**
* @author linnine09
* @create 2022/8/3 11:23
*/
public interface ResultSetHandler {
/**
* 将结果集映射成出参类集合
* @param statement
* @param <E>
* @return
* @throws SQLException
*/
<E> List<E> handleResultSets(Statement statement) throws SQLException;
}
ResultHandler
暂时没看到干嘛用的
package com.linnine.mybatis.session;
/**
* 结果处理器
* @author linnine09
* @create 2022/8/3 11:36
*/
public interface ResultHandler {
void handleResult();
}
DefaultResultSetHandler
处理结果集的实现类 从DefaultSqlSession那边搬过来的
package com.linnine.mybatis.executor.reultset;
/**
* 处理结果集
* @author linnine09
* @create 2022/8/3 11:55
*/
public class DefaultResultSetHandler implements ResultSetHandler{
private final BoundSql boundSql;
public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, BoundSql boundSql) {
this.boundSql = boundSql;
}
/**
* 将返回的结果映射成对象
* @param statement
* @param <E>
* @return
* @throws SQLException
*/
@Override
public <E> List<E> handleResultSets(Statement statement) throws SQLException {
ResultSet resultSet = statement.getResultSet();
try {
return resultSet2Obj(resultSet,Class.forName(boundSql.getResultType()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
private <T> List<T> resultSet2Obj(ResultSet resultSet, Class<?> clazz) {
List<T> list = new ArrayList<>();
try {
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
while (resultSet.next()){
T obj = (T) clazz.newInstance();
for (int i = 1; i < columnCount; i++) {
Object value = resultSet.getObject(i);
String columnName = metaData.getColumnName(i);
String setMethod ="set"+columnName.substring(0,1).toUpperCase()+ columnName.substring(1);
Method method;
if (value instanceof Timestamp){
method = clazz.getMethod(setMethod, Date.class);
}else {
method = clazz.getMethod(setMethod,value.getClass());
}
method.invoke(obj,value);
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
DefaultSqlSession
这下里面就少了很多东西了,直接加入一个执行器,执行一下就好了
DefaultSqlSessionFactory
这里主要通过配置去获取一个执行器
package com.linnine.mybatis.session;
/**
* @author linnine09
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory{
private Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration =configuration;
}
@Override
public SqlSession openSqlSession() {
final Environment environment = configuration.getEnvironment();
TransactionFactory transactionFactory = environment.getTransactionFactory();
Transaction tx=transactionFactory.newTransaction(environment.getDataSource(),TransactionIsolationLevel.READ_COMMITTED,false);
Executor executor = configuration.newExecutor(tx);
return new DefaultSqlSession(configuration,executor);
}
}
Configuration
补充了获取三个实现类的方法
package com.linnine.mybatis.session;
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, ResultHandler resultHandler, BoundSql boundSql){
return new PreparedStatementHandler(executor,mappedStatement,parameter,resultHandler,boundSql);
}
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, BoundSql boundSql) {
return new DefaultResultSetHandler(executor,mappedStatement,boundSql);
}
public Executor newExecutor(Transaction tx) {
return new SimpleExecutor(this,tx);
}
测试类还是上次05那个测试类 ,运行没什么大毛病