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

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就执行完成了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值