Skip to content

Commit

Permalink
添加查询结果集resultType的处理
Browse files Browse the repository at this point in the history
  • Loading branch information
FuriousPws002 committed Apr 12, 2024
1 parent 001fe00 commit 144c93f
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 8 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
[1.注册Mapper接口](https://github.com/FuriousPws002/mini-mybatis/wiki/1.%E6%B3%A8%E5%86%8CMapper%E6%8E%A5%E5%8F%A3 "Markdown") <br>
[2.解析xml中静态sql的mapper](https://github.com/FuriousPws002/mini-mybatis/wiki/2.%E8%A7%A3%E6%9E%90xml%E4%B8%AD%E9%9D%99%E6%80%81sql%E7%9A%84mapper "Markdown") <br>
[3.执行静态sql](https://github.com/FuriousPws002/mini-mybatis/wiki/3.%E6%89%A7%E8%A1%8C%E9%9D%99%E6%80%81sql "Markdown") <br>
[4.参数绑定](https://github.com/FuriousPws002/mini-mybatis/wiki/4.%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A "Markdown") <br>
[4.参数绑定](https://github.com/FuriousPws002/mini-mybatis/wiki/4.%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A "Markdown") <br>
[5.resultType结果集处理](https://github.com/FuriousPws002/mini-mybatis/wiki/5.resultType%E7%BB%93%E6%9E%9C%E9%9B%86%E5%A4%84%E7%90%86 "Markdown") <br>
15 changes: 14 additions & 1 deletion src/main/java/org/apache/ibatis/binding/MapperMethod.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apache.ibatis.binding;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Objects;

import org.apache.ibatis.mapping.MappedStatement;
Expand All @@ -23,18 +24,28 @@ public MapperMethod(Class<?> mapperInterface, Method method, Configuration confi
}

public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
Object result = null;
switch (command.getType()) {
case INSERT: {
result = sqlSession.insert(command.getName(), method.convertArgsToSqlCommandParam(args));
break;
}
case SELECT: {
if (method.returnsMany) {
result = executeForMany(sqlSession, args);
}
break;
}
default:
throw new BindingException(command.getType() + " not support");
}
return result;
}

private <T> Object executeForMany(SqlSession sqlSession, Object[] args) {
return sqlSession.selectList(command.getName(), method.convertArgsToSqlCommandParam(args));
}

public static class SqlCommand {

private final String name;
Expand Down Expand Up @@ -63,9 +74,11 @@ public SqlCommandType getType() {
public static class MethodSignature {

private final ParamNameResolver paramNameResolver;
private final boolean returnsMany;

public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
this.paramNameResolver = new ParamNameResolver(method);
returnsMany = Collection.class.isAssignableFrom(method.getReturnType());
}

public Object convertArgsToSqlCommandParam(Object[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private void configurationElement(XNode context) {
if (Objects.isNull(namespace) || namespace.isEmpty()) {
throw new BuilderException("mapper namespace can not be empty");
}
buildStatementFromContext(context.evalNodes("insert"));
buildStatementFromContext(context.evalNodes("insert|select"));
} catch (Exception e) {
throw new BuilderException("parse mapper xml error", e);
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/apache/ibatis/executor/Executor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apache.ibatis.executor;

import java.sql.SQLException;
import java.util.List;

import org.apache.ibatis.mapping.MappedStatement;

Expand All @@ -10,4 +11,6 @@
public interface Executor {

int update(MappedStatement ms, Object parameter) throws SQLException;

<T> List<T> query(MappedStatement ms, Object parameter) throws SQLException;
}
13 changes: 13 additions & 0 deletions src/main/java/org/apache/ibatis/executor/SimpleExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Objects;

import org.apache.ibatis.executor.statement.StatementHandler;
Expand Down Expand Up @@ -36,6 +37,18 @@ public int update(MappedStatement ms, Object parameter) throws SQLException {
}
}

@Override
public <T> List<T> query(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, null);
stmt = prepareStatement(handler);
return handler.query(stmt);
} finally {
StatementUtil.closeStatement(stmt);
}
}

private Statement prepareStatement(StatementHandler handler) throws SQLException {
Statement stmt;
Connection connection = configuration.getDataSource().getConnection();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package org.apache.ibatis.executor.resultset;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;

/**
* @author furious 2024/4/12
*/
public class DefaultResultSetHandler implements ResultSetHandler {

private final Configuration configuration;
private final MappedStatement mappedStatement;
private final TypeHandlerRegistry typeHandlerRegistry;

public DefaultResultSetHandler(MappedStatement mappedStatement) {
this.configuration = mappedStatement.getConfiguration();
this.mappedStatement = mappedStatement;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
}

@Override
public <T> List<T> handleResultSets(Statement stmt) throws SQLException {
final List<Object> multipleResults = new ArrayList<>();
ResultSet rs = stmt.getResultSet();
if (Objects.isNull(rs)) {
return Collections.emptyList();
}
ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);
ResultMap resultMap = mappedStatement.getResultMap();
handleResultSet(rsw, resultMap, multipleResults);
return (List<T>) multipleResults;
}

private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults) throws SQLException {
try {
handleRowValues(rsw, resultMap, multipleResults);
} finally {
closeResultSet(rsw.getResultSet());
}
}

private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults) throws SQLException {
handleRowValuesForSimpleResultMap(rsw, resultMap, multipleResults);
}

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults) throws SQLException {
ResultSet resultSet = rsw.getResultSet();
while (!resultSet.isClosed() && resultSet.next()) {
Object rowValue = getRowValue(rsw, resultMap);
multipleResults.add(rowValue);
}
}

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
Object rowValue = createResultObject(resultMap);
applyAutomaticMappings(rsw, rowValue);
return rowValue;
}

private boolean applyAutomaticMappings(ResultSetWrapper rsw, Object rowValue) throws SQLException {
List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, rowValue);
boolean foundValues = false;
if (!autoMapping.isEmpty()) {
for (UnMappedColumnAutoMapping mapping : autoMapping) {
final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
if (value != null) {
foundValues = true;
}
try {
FieldUtils.writeField(rowValue, mapping.property, value, true);
} catch (IllegalAccessException e) {
ExceptionUtils.rethrow(e);
}
}
}
return foundValues;
}

private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, Object rowValue) {
List<UnMappedColumnAutoMapping> autoMapping = new ArrayList<>();
List<String> columnLabels = rsw.getColumnLabels();
for (String columnLabel : columnLabels) {
Field field = FieldUtils.getDeclaredField(rowValue.getClass(), columnLabel, true);
String property = Objects.isNull(field) ? null : columnLabel;
if (Objects.nonNull(property)) {
Class<?> propertyType = field.getType();
if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propertyType);
autoMapping.add(new UnMappedColumnAutoMapping(columnLabel, property, typeHandler));
}
}
}
return autoMapping;
}

private Object createResultObject(ResultMap resultMap) throws SQLException {
try {
return resultMap.getType().newInstance();
} catch (Exception e) {
throw new SQLException("create return type fail " + e);
}
}

private void closeResultSet(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException ignored) {
}
}

/**
* 数据库中列和对象中属性映射
*/
private static class UnMappedColumnAutoMapping {
private final String column;
private final String property;
private final TypeHandler<?> typeHandler;

public UnMappedColumnAutoMapping(String column, String property, TypeHandler<?> typeHandler) {
this.column = column;
this.property = property;
this.typeHandler = typeHandler;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;

/**
Expand All @@ -35,4 +32,11 @@ public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLExc
}
}

public ResultSet getResultSet() {
return resultSet;
}

public List<String> getColumnLabels() {
return columnLabels;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Objects;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
Expand All @@ -22,6 +24,7 @@ public class PrepareStatementHandler implements StatementHandler {
protected final MappedStatement mappedStatement;
protected BoundSql boundSql;
protected final ParameterHandler parameterHandler;
protected final ResultSetHandler resultSetHandler;

public PrepareStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
Expand All @@ -32,6 +35,7 @@ public PrepareStatementHandler(Executor executor, MappedStatement mappedStatemen
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(mappedStatement);
}

@Override
Expand All @@ -50,4 +54,11 @@ public int update(Statement statement) throws SQLException {
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}

@Override
public <T> List<T> query(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

/**
* @author furious 2024/4/8
Expand All @@ -14,4 +15,6 @@ public interface StatementHandler {
int update(Statement statement) throws SQLException;

void parameterize(Statement statement) throws SQLException;

<T> List<T> query(Statement statement) throws SQLException;
}
4 changes: 4 additions & 0 deletions src/main/java/org/apache/ibatis/mapping/MappedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public BoundSql getBoundSql(Object parameterObject) {
return new BoundSql(boundSql.getSql(),boundSql.getParameterMappings(),parameterObject);
}

public ResultMap getResultMap() {
return resultMap;
}

public static class Builder {
private MappedStatement mappedStatement = new MappedStatement();

Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/apache/ibatis/session/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.PrepareStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
Expand Down Expand Up @@ -85,6 +87,10 @@ public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Obj
return languageDriver.createParameterHandler(mappedStatement, parameterObject, boundSql);
}

public ResultSetHandler newResultSetHandler(MappedStatement mappedStatement) {
return new DefaultResultSetHandler(mappedStatement);
}

public TypeHandlerRegistry getTypeHandlerRegistry() {
return typeHandlerRegistry;
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/apache/ibatis/session/SqlSession.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apache.ibatis.session;

import java.io.Closeable;
import java.util.List;

/**
* @author furious 2024/3/29
Expand All @@ -14,4 +15,6 @@ public interface SqlSession extends Closeable {
int insert(String statement, Object parameter);

int update(String statement, Object parameter);

<T> List<T> selectList(String statement, Object parameter);
}
Loading

0 comments on commit 144c93f

Please sign in to comment.