欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis原理(2)-执行流程 1 BoundSql生成

程序员文章站 2022-04-22 08:00:30
...
MyBatis执行两种方式:
1.

SqlSession openSession = sqlSessionFactory.openSession();
Dept d = new Dept();
d.setId(1506720);
Object dept = openSession.selectOne("dao.DeptDAO1.select",d);
System.out.println(dept);

2.
DeptMapper mapper = openSession.getMapper(DeptMapper.class);
Dept dept2= mapper.select(d);
System.out.println(dept2);


方式1:
1.DefaultSqlSessionFactory

@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

public ExecutorType getDefaultExecutorType() {
return defaultExecutorType;
}
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

public enum ExecutorType {
SIMPLE, REUSE, BATCH
}

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//XMLConfigBuilder#environmentsElement加载
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//新建一个事务
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}


Configuration#newExecutor 生成相应的Executor


public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//缓存
if (cacheEnabled) {
//后面统一分析Executor集合和其子类,这里将SimpleExecutor包装为一个
//CachingExecutor
executor = new CachingExecutor(executor);
}
//调用拦截器链中注册的拦截器(如果拦截类型是Executor),每个拦截器会对当前
//Executor进行动态代理,如果有n个拦截器拦截Executor,会生成对Executor的n层代理,
//后面再进行详细分析
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}

SqlSession构造完毕后执行selectOne方法:
  @Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}

@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}


RowBounds //TODO
继续调用重载的selectList

@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
//包装参数为StrictMap
private Object wrapCollection(final Object object) {
if (object instanceof Collection) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("collection", object);
if (object instanceof List) {
map.put("list", object);
}
return map;
} else if (object != null && object.getClass().isArray()) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("array", object);
return map;
}
return object;
}


DefaultSqlSession //TODO
执行Executor的query方法:
 @Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//获取带?号的sql和参数映射
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

MapperStatement#getBoundSql

public BoundSql getBoundSql(Object parameterObject) {
//调用SqlSource的getBoundSql,这里的sqlSource是DymicSqlSource的一个实例
//见前一篇文章XMLScriptBuilder#parseScriptNode
// sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//如果参数映射为空才考虑使用ParameterMap
//ParameterMap在mapper解析 insert update select 等标签时生成
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
}

//检查ParameterMap是否有嵌套的ResultMap
// check for nested result maps in parameter mappings (issue #30)
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}

return boundSql;
}



//SqlSource一共有四个子类:ProviderSqlSource,DynamicSqlSource、RawSqlSource、StaticSqlSource
public class DynamicSqlSource implements SqlSource {

private final Configuration configuration;
private final SqlNode rootSqlNode;

public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
this.configuration = configuration;
this.rootSqlNode = rootSqlNode;
}

@Override
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
}

}

DynamicContext:

public class DynamicContext {

public static final String PARAMETER_OBJECT_KEY = "_parameter";
public static final String DATABASE_ID_KEY = "_databaseId";

static {
//初始化OgnlRuntime使用ContextAccessor作为访问器
OgnlRuntime.setPropertyAccessor(ContextMap.class, new ContextAccessor());
}

private final ContextMap bindings;
private final StringBuilder sqlBuilder = new StringBuilder();
private int uniqueNumber = 0;
//如果当前参数是实体对象或者List的子类等其他对象,反正不是Map

public DynamicContext(Configuration configuration, Object parameterObject) {
//当前参数不是map的实例
if (parameterObject != null && !(parameterObject instanceof Map)) {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
bindings = new ContextMap(metaObject);
} else {
//为空或者是Map
bindings = new ContextMap(null);
}
//将对象参数放入 key为_parameter的map中
bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
}

public Map<String, Object> getBindings() {
return bindings;
}

public void bind(String name, Object value) {
bindings.put(name, value);
}

public void appendSql(String sql) {
sqlBuilder.append(sql);
sqlBuilder.append(" ");
}

public String getSql() {
return sqlBuilder.toString().trim();
}

public int getUniqueNumber() {
return uniqueNumber++;
}

static class ContextMap extends HashMap<String, Object> {
private static final long serialVersionUID = 2977601501966151582L;

private MetaObject parameterMetaObject;
public ContextMap(MetaObject parameterMetaObject) {
this.parameterMetaObject = parameterMetaObject;
}

@Override
public Object get(Object key) {
String strKey = (String) key;
if (super.containsKey(strKey)) {
return super.get(strKey);
}

if (parameterMetaObject != null) {
// issue #61 do not modify the context when reading
return parameterMetaObject.getValue(strKey);
}

return null;
}
}

static class ContextAccessor implements PropertyAccessor {

@Override
public Object getProperty(Map context, Object target, Object name)
throws OgnlException {
Map map = (Map) target;
//直接获取contextMap中的keyvalue或者获取MetaObject中的getValue
Object result = map.get(name);
if (map.containsKey(name) || result != null) {
return result;
}
//如参数对象本身是个map,直接获取
Object parameterObject = map.get(PARAMETER_OBJECT_KEY);
if (parameterObject instanceof Map) {
return ((Map)parameterObject).get(name);
}

return null;
}

@Override
public void setProperty(Map context, Object target, Object name, Object value)
throws OgnlException {
Map<Object, Object> map = (Map<Object, Object>) target;
map.put(name, value);
}

@Override
public String getSourceAccessor(OgnlContext arg0, Object arg1, Object arg2) {
return null;
}

@Override
public String getSourceSetter(OgnlContext arg0, Object arg1, Object arg2) {
return null;
}
}
}

Configuration#newMetaObject


public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}

MetaObject:

public class MetaObject {

private final Object originalObject;
private final ObjectWrapper objectWrapper;
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;

if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
// 首次进入执行BeanWapper
this.objectWrapper = new BeanWrapper(this, object);
}
}

public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}

public ObjectFactory getObjectFactory() {
return objectFactory;
}

public ObjectWrapperFactory getObjectWrapperFactory() {
return objectWrapperFactory;
}

public ReflectorFactory getReflectorFactory() {
return reflectorFactory;
}

public Object getOriginalObject() {
return originalObject;
}

public String findProperty(String propName, boolean useCamelCaseMapping) {
return objectWrapper.findProperty(propName, useCamelCaseMapping);
}

public String[] getGetterNames() {
return objectWrapper.getGetterNames();
}

public String[] getSetterNames() {
return objectWrapper.getSetterNames();
}

public Class<?> getSetterType(String name) {
return objectWrapper.getSetterType(name);
}

public Class<?> getGetterType(String name) {
return objectWrapper.getGetterType(name);
}

public boolean hasSetter(String name) {
return objectWrapper.hasSetter(name);
}

public boolean hasGetter(String name) {
return objectWrapper.hasGetter(name);
}

public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
return metaValue.getValue(prop.getChildren());
}
} else {
return objectWrapper.get(prop);
}
}

public void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null && prop.getChildren() != null) {
// don't instantiate child path if value is null
return;
} else {
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
metaValue.setValue(prop.getChildren(), value);
} else {
objectWrapper.set(prop, value);
}
}

public MetaObject metaObjectForProperty(String name) {
Object value = getValue(name);
return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}

public ObjectWrapper getObjectWrapper() {
return objectWrapper;
}

public boolean isCollection() {
return objectWrapper.isCollection();
}

public void add(Object element) {
objectWrapper.add(element);
}

public <E> void addAll(List<E> list) {
objectWrapper.addAll(list);
}

}



BeanWrapper://TODO

ublic class BeanWrapper extends BaseWrapper {

private final Object object;
private final MetaClass metaClass;

public BeanWrapper(MetaObject metaObject, Object object) {
super(metaObject);
this.object = object;
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
}

@Override
public Object get(PropertyTokenizer prop) {
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
return getBeanProperty(prop, object);
}
}

@Override
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
setBeanProperty(prop, object, value);
}
}

@Override
public String findProperty(String name, boolean useCamelCaseMapping) {
return metaClass.findProperty(name, useCamelCaseMapping);
}

@Override
public String[] getGetterNames() {
return metaClass.getGetterNames();
}

@Override
public String[] getSetterNames() {
return metaClass.getSetterNames();
}

@Override
public Class<?> getSetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.getSetterType(name);
} else {
return metaValue.getSetterType(prop.getChildren());
}
} else {
return metaClass.getSetterType(name);
}
}

@Override
public Class<?> getGetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.getGetterType(name);
} else {
return metaValue.getGetterType(prop.getChildren());
}
} else {
return metaClass.getGetterType(name);
}
}

@Override
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (metaClass.hasSetter(prop.getIndexedName())) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.hasSetter(name);
} else {
return metaValue.hasSetter(prop.getChildren());
}
} else {
return false;
}
} else {
return metaClass.hasSetter(name);
}
}

@Override
public boolean hasGetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (metaClass.hasGetter(prop.getIndexedName())) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.hasGetter(name);
} else {
return metaValue.hasGetter(prop.getChildren());
}
} else {
return false;
}
} else {
return metaClass.hasGetter(name);
}
}

@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
MetaObject metaValue;
Class<?> type = getSetterType(prop.getName());
try {
Object newObject = objectFactory.create(type);
metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());
set(prop, newObject);
} catch (Exception e) {
throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
}
return metaValue;
}

private Object getBeanProperty(PropertyTokenizer prop, Object object) {
try {
Invoker method = metaClass.getGetInvoker(prop.getName());
try {
return method.invoke(object, NO_ARGUMENTS);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (RuntimeException e) {
throw e;
} catch (Throwable t) {
throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t);
}
}

private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
try {
Invoker method = metaClass.getSetInvoker(prop.getName());
Object[] params = {value};
try {
method.invoke(object, params);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (Throwable t) {
throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass() + "' with value '" + value + "' Cause: " + t.toString(), t);
}
}

@Override
public boolean isCollection() {
return false;
}

@Override
public void add(Object element) {
throw new UnsupportedOperationException();
}

@Override
public <E> void addAll(List<E> list) {
throw new UnsupportedOperationException();
}

}



MetaClass:参考启动流程2

BaseWrapper://TODO

public abstract class BaseWrapper implements ObjectWrapper {

protected static final Object[] NO_ARGUMENTS = new Object[0];
protected final MetaObject metaObject;

protected BaseWrapper(MetaObject metaObject) {
this.metaObject = metaObject;
}

protected Object resolveCollection(PropertyTokenizer prop, Object object) {
if ("".equals(prop.getName())) {
return object;
} else {
return metaObject.getValue(prop.getName());
}
}

protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
if (collection instanceof Map) {
return ((Map) collection).get(prop.getIndex());
} else {
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
return ((List) collection).get(i);
} else if (collection instanceof Object[]) {
return ((Object[]) collection)[i];
} else if (collection instanceof char[]) {
return ((char[]) collection)[i];
} else if (collection instanceof boolean[]) {
return ((boolean[]) collection)[i];
} else if (collection instanceof byte[]) {
return ((byte[]) collection)[i];
} else if (collection instanceof double[]) {
return ((double[]) collection)[i];
} else if (collection instanceof float[]) {
return ((float[]) collection)[i];
} else if (collection instanceof int[]) {
return ((int[]) collection)[i];
} else if (collection instanceof long[]) {
return ((long[]) collection)[i];
} else if (collection instanceof short[]) {
return ((short[]) collection)[i];
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}

protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
if (collection instanceof Map) {
((Map) collection).put(prop.getIndex(), value);
} else {
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
((List) collection).set(i, value);
} else if (collection instanceof Object[]) {
((Object[]) collection)[i] = value;
} else if (collection instanceof char[]) {
((char[]) collection)[i] = (Character) value;
} else if (collection instanceof boolean[]) {
((boolean[]) collection)[i] = (Boolean) value;
} else if (collection instanceof byte[]) {
((byte[]) collection)[i] = (Byte) value;
} else if (collection instanceof double[]) {
((double[]) collection)[i] = (Double) value;
} else if (collection instanceof float[]) {
((float[]) collection)[i] = (Float) value;
} else if (collection instanceof int[]) {
((int[]) collection)[i] = (Integer) value;
} else if (collection instanceof long[]) {
((long[]) collection)[i] = (Long) value;
} else if (collection instanceof short[]) {
((short[]) collection)[i] = (Short) value;
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}

}

分析一下调用链:
1.Configuration传入:
object, objectFactory, objectWrapperFactory, reflectorFactory
object为参数对象ObjectFactory即对象工厂,通过反射创建对象,
objectWrapperFactory是DefaultObjectWrapperFactory,其为空实现,实现了ObjectWrapperFactory,先不说明有什么作用,
reflectorFactory则非常重要,包含了Reflector的缓存,Reflector则是封装了一个类型的getter setter和相应实现了InvokcationHandler接口的Invoker,用来设置相应的属性值。
2。MetaObject 构造相应的Wrapper实现,构造几种BeanWrapper时都传入了this即MetaObject,MetaObject有两个作用:供抽象父类BaseWrapper调用MetaObject方法和获取MetaObject的reflectorFactory,通过reflectorFactory可以构造MetaClass,MetaClass则是Relector的封装。查看BeanWrapper的get方法调用了getBeanProperty而这个方法继续调用了metaClass.getGetInvoker即reflector的getGetInvoker。而MetaObject的getValue方法则调用了objectWrapper的get方法。
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
return metaValue.getValue(prop.getChildren());
}
} else {
return objectWrapper.get(prop);
}
}

总结一下:为什么要将一个简单的Invoker对象封装如此多层呢?有什么具体的作用呢?
只要通过MetaOject的getValue方法就可以将任何对象封装成像一个Map医院使用。

DynamicContext的作用:DynamicContext 包含实例变量ContextMap和sqlBuilder,ContextMap中有传入如parameterObject和DatabaseId。还有什么用?//TODO

继续执行DynamicSqlSource#getBoundSql
这里的rootSqlNode是解析流程(3)中的MixedSqlNode的实例,MixedSqlNode中contents存储了所有解析后的动态和静态的SqlNode的实现。所有MixedSqlNode的apply方法仅仅是执行contents中的SqlNode的apply方法,apply方法只有一个入参DynamicContext

rootSqlNode.apply(context);

如果sqlNode是StaticTextSqlNode,调用 context.appendSql(text);将静态sql文本加在context的sqlBuilder尾部

public class MixedSqlNode implements SqlNode {
private final List<SqlNode> contents;

public MixedSqlNode(List<SqlNode> contents) {
this.contents = contents;
}

@Override
public boolean apply(DynamicContext context) {
//最终都会执行StaticTextSqlNode的apply方法,将sql拼接在Dynamic中的sqlBuilder中
for (SqlNode sqlNode : contents) {
sqlNode.apply(context);
}
return true;
}
}


如果是IfSqlNode调用Ogln解析器解析使用binds赋值的test表达式成功则添加否则不添加。


public class IfSqlNode implements SqlNode {
private final ExpressionEvaluator evaluator;
private final String test;
//IfSqlNode也包含contents,可能是MixedSqlNode,StaticTextSqlNode
private final SqlNode contents;

public IfSqlNode(SqlNode contents, String test) {
this.test = test;
this.contents = contents;
this.evaluator = new ExpressionEvaluator();
}

@Override
public boolean apply(DynamicContext context) {
//判断test表达式值,这里通过DynamicContext.ContextAccessor的getProperty方法调用ContextMap中的get方法继而调用MetaObject的getValue最终获取到传入对象的属性值。
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}


继续执行
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());


执行到这里可以发现SqlNode的主要作用就动态的拼接sql语句,产出sql语句,而DynamicContext的作用就是产出sql(待#{}表达式)和将入参封装为Map(contextMap)对象。

SqlSourceBuilder和内部类都继承了BaseBuilder表明自己是个解析器并且获得了 typeAliasRegistry、typeHandlerRegistry两个属性 和一些基本的方法。

protected final TypeHandlerRegistry typeHandlerRegistry;

public class SqlSourceBuilder extends BaseBuilder {

private static final String parameterProperties = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";

public SqlSourceBuilder(Configuration configuration) {
super(configuration);
}

public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
//通过构造一个ParameterMappingTokenHandler和GenericTokenParser解析 originalSql并将originalSql中的#{}替换为?
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {

private List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
private Class<?> parameterType;
private MetaObject metaParameters;

public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
super(configuration);
this.parameterType = parameterType;
//这里在进行newMetaObject的时候additionalParameters已经是一个ContextMap对象
//所以返回的metaParameters中的ObjectWrapper是一个不择不扣的MapWapper
//也就是说最后任何对象都会被转换成一个MappWapper
this.metaParameters = configuration.newMetaObject(additionalParameters);
}

public List<ParameterMapping> getParameterMappings() {
return parameterMappings;
}

@Override
public String handleToken(String content) {
//生成ParameterMapping
parameterMappings.add(buildParameterMapping(content));
return "?";
}

private ParameterMapping buildParameterMapping(String content) {
//ParameterExpression.parse方法会解析content中是否还有其他表达式,
//最终生成 propertiesMap property->#{}中包含的值 如 property->id
//和其他表达式或者jdbc和ojdbc之间的映射
Map<String, String> propertiesMap = parseParameterMapping(content);
String property = propertiesMap.get("property");
Class<?> propertyType;
if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
propertyType = metaParameters.getGetterType(property);
} else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
propertyType = parameterType;
} else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
propertyType = java.sql.ResultSet.class;
} else if (property == null || Map.class.isAssignableFrom(parameterType)) {
propertyType = Object.class;
} else {
//这里通过寻找参数类型中是否有对应的属性,有则propertyType被设置为相应的类型
MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
if (metaClass.hasGetter(property)) {
propertyType = metaClass.getGetterType(property);
} else {
propertyType = Object.class;
}
}
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
Class<?> javaType = propertyType;
String typeHandlerAlias = null;
//检查是否有Java类型和jdbc类型的映射
for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("javaType".equals(name)) {
javaType = resolveClass(value);
builder.javaType(javaType);
} else if ("jdbcType".equals(name)) {
builder.jdbcType(resolveJdbcType(value));
} else if ("mode".equals(name)) {
builder.mode(resolveParameterMode(value));
} else if ("numericScale".equals(name)) {
builder.numericScale(Integer.valueOf(value));
} else if ("resultMap".equals(name)) {
builder.resultMapId(value);
} else if ("typeHandler".equals(name)) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
throw new BuilderException("Expression based parameters are not supported yet");
} else {
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties);
}
}
if (typeHandlerAlias != null) {
//有则为parameterMapping设置相应的类型处理器
builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
}
//构建ParameterMapping
return builder.build();
}

private Map<String, String> parseParameterMapping(String content) {
try {
return new ParameterExpression(content);
} catch (BuilderException ex) {
throw ex;
} catch (Exception ex) {
throw new BuilderException("Parsing error was found in mapping #{" + content + "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
}
}
}

}



ParameterMapping://TODO


继续执行SqlSourceBuilder#parse,生成StaticSqlSource,

new StaticSqlSource(configuration, sql, handler.getParameterMappings());


public class StaticSqlSource implements SqlSource {

private final String sql;
private final List<ParameterMapping> parameterMappings;
private final Configuration configuration;

public StaticSqlSource(Configuration configuration, String sql) {
this(configuration, sql, null);
}

public StaticSqlSource(Configuration configuration, String sql, List<ParameterMapping> parameterMappings) {
this.sql = sql;
this.parameterMappings = parameterMappings;
this.configuration = configuration;
}

@Override
public BoundSql getBoundSql(Object parameterObject) {
return new BoundSql(configuration, sql, parameterMappings, parameterObject);
}

}

BoundSql:

public class BoundSql {

private final String sql;
private final List<ParameterMapping> parameterMappings;
private final Object parameterObject;
private final Map<String, Object> additionalParameters;
private final MetaObject metaParameters;

public BoundSql(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Object parameterObject) {
this.sql = sql;
this.parameterMappings = parameterMappings;
this.parameterObject = parameterObject;
this.additionalParameters = new HashMap<String, Object>();
this.metaParameters = configuration.newMetaObject(additionalParameters);
}

public String getSql() {
return sql;
}

public List<ParameterMapping> getParameterMappings() {
return parameterMappings;
}

public Object getParameterObject() {
return parameterObject;
}

public boolean hasAdditionalParameter(String name) {
String paramName = new PropertyTokenizer(name).getName();
return additionalParameters.containsKey(paramName);
}

public void setAdditionalParameter(String name, Object value) {
metaParameters.setValue(name, value);
}

public Object getAdditionalParameter(String name) {
return metaParameters.getValue(name);
}
}


观察BoundSql和StaticSqlSource,发现BoundSql只比StaticSqlSource多了metaParameters的参数。
执行到这里不妨总结一下Sql解析的流程和使用到的几个核心类、接口:
在mapper解析阶段XMLScriptBuilder#parseDynamicTags生成MixedSqlNode和
parseScriptNode生成DynamicSqlSource组装生成MappedStatement,执行时传入参数并执行DynamicSqlSource中rootSqlNode最终生成静态的StaticSqlSource,静态的StaticSqlSource是已经解析成jdbc驱动可以执行的语句,进一步加上入参对象封装而成的MetaObject成了BoundSql。

SqlNode接口:表示每个sql片段,有两种实现类,动态:的有if where 等和静态的sql片段,表示不含表达式的sql语句。此接口只包含一个方法,此方法入参为DynamicContext,每次调用判断将sql追加到上下文的末尾,形成整个一个语句。各种SqlNode在XMLScriptBuilder#parseDynamicTags被创建加入一个MixedSqlNode中,MapperStatement的rootSqlNode执行apply后销亡。
ParameterMapping:包含当前#{}中包含的参数对象类型的属性名称、类型等,执行阶段被ParameterMappingTokenHandler#buildParameterMapping或者MapperBuilderAssistant#buildParameterMapping生成,并加入SqlSource
SqlSource:在动态的SqlSource包含SqlNode的实例,静态SqlSource包含解析后的sql和参数映射ParameterMapping,DynamicSqlSource在解析阶段使用,StaticSqlSource在执行阶段使用。

BoundSql:包含静态sql语句,ParameterMapping参数映射,parameterObject原生传入参数,additionalParameters额外的参数( DynamicContext中所有的值)以及metaParameters,额外参数对应的获取方法,BoundSql包含了一个sql得以执行的所有必需条件。

继续执行MapperStatement#getBoundSql
到此MapperStatement的getBoundSql就执行完成了