mybatis config.xml里標簽可以放置多個environment,這裡可以切換test和develop數據源 databaseIdProvider提供多種資料庫,在xml映射文件里選擇databaseId即可使用對應的資料庫 Oracle的自增是使用Sequence實現的,若要獲取插入數 ...
- mybatis-config.xml里
標簽可以放置多個environment,這裡可以切換test和develop數據源 - databaseIdProvider提供多種資料庫,在xml映射文件里選擇databaseId即可使用對應的資料庫
- Oracle的自增是使用Sequence實現的,若要獲取插入數據的主鍵,在xml映射里寫上selectKey標簽,select seq.nextval from dual;
- 哪些地方不能使用占位符?比如分表時表名,orderby,desc
@Mapkey("id")指定返回類型為map時,將id作為key
1. mybatis參數綁定的過程
我們寫一個UserMapper介面,Mybatis會為改介面創建一個MapperProxy對象。
1.1 MapperRegistry
在繼續之前,先來瞭解一下MapperRegistry。
- MapperRegistry是mapper的註冊類,提供了註冊一個包下麵的所有Mapper介面。內部維護了一個
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
map以mapper介面類為key,value是介面類對應的代理工廠。
void addMapper(Class<T> type)
方法簡單的將type放進knownMappers裡面。不過,這裡面還有
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
這樣一個解析操作,暫不做分析。
<T> T getMapper(Class<T> type, SqlSession sqlSession)
該方法是本類最重要的一個方法了,獲取Mapper介面的代理對象也正是從該方法獲取的。
該方法實現就是,knownMappers.get(type)得到代理對象工廠mapperProxyFactory,返回的是mapperProxyFactory.newInstance(sqlSession)
。
進入該方法發現過程也比較簡單,構造了一個MapperProxy對象
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
再進去看
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
發現這就是標準的JDK面向介面的動態代理啊。要問對應的InvocationHandler在哪裡?mapperProxy就是啦。
至此,Mybatis如何獲取Mapper介面的代理對象已經解決。
再梳理一下整個流程:
sqlsession.getMapper->configuration.getMapper->mapperRegistry.getMapper->獲取Mapper代理對象
1.2
創建好MapperProxy對象之後,調用Mapper.xx方法時就會走MapperProxy的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {//如果方法是在Object裡面的,放行
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);//緩存method方法
return mapperMethod.execute(sqlSession, args); // 執行
}
發現關鍵點在於mapperMethod.execute(sqlSession, args)
方法