mybatisソース解析(四)-mapperメソッド呼び出しプロセス
16939 ワード
mybatisソースコード解析(一)-冒頭mybatisソースコード解析(二)-ロードプロセスmybatisソースコード解析(三)-SqlSession.selectOne類似メソッド呼び出しプロシージャmybatisソース解析(4)-mapperメソッド呼び出しプロシージャmybatisソース解析(5)-mybatisがどのように実装するトランザクション制御mybatisソース解析(6)-spring-txと協力してトランザクションを実装する原理mybatisソース解析(7)-mybatis一級キャッシュがspringに遭遇した場合
転載は出典を明記してください.http://blog.csdn.net/bingospunky/article/details/79220894本文は馬彬彬のブログから
前のブログでは、SqlSessionの実行手順について説明しています.しかし、mybatisを使用する場合、一般的にMapperを使用して添削を行います.この文章では、Mapperの方法がどのように実行されているかを示します.Mapperを用いた添削改査は2つのステップに分けられ,第1ステップではまずMapperオブジェクトを取得し,第2部ではMapperメソッドを呼び出す.我々が呼び出したメソッドに対応するxxxMapper.xmlの内容は次のとおりです.
Code 1
取得Mapper
取得Mapperの主なコードは次のとおりです.
Code 2 org.apache.ibatis.binding.MapperProxyFactory
このコードはMapperProxyFactoryのもので、MapperProxyFactoryの役割はMapperを生成し、1つのMapperが1つのMapperProxyFactoryに対応することです.コードから、私たちが取得したオブジェクトはJdbcProxyによって生成され、エージェントオブジェクトに必要な3つのパラメータが表示されます.1つ目は説明しません.2つ目は私たちが取得するMappeインタフェースです.3番目のパラメータmapperProxyは重要です.それはコールバックです.Mapperインタフェースのメソッドを呼び出すと、mapperProxyのメソッドがコールバックされます.mapperProxyでコールバックメソッドを実装し、データベースを操作する必要があります.mapperProxyについては、クエリー・プロシージャの実行について詳しく説明します.
マッパーを呼び出す方法
取得したMapperオブジェクトはJdbcProxyオブジェクトであるため、メソッドを呼び出すとコールバックインタフェースのメソッドが呼び出されます.コールバックインタフェースのコードは次のとおりです.
Code 3 org.apache.ibatis.binding.MapperProxy
9行目はMethodでMapperMethodを取得し、10行目はMapperMethodを呼び出す.executeメソッドは、後で本物のsqlを実行します.MapperMethodを取得する場合、最初に取得する場合は、MapperMethodを構築する必要があります.次に、MapperMethodを構築し、MapperMethodを実行します.executeの2つの部分について説明します.
MapperMethodの作成
MapperMethodを構築するコードは次のとおりです.
Code 4 org.apache.ibatis.binding.MapperMethod
MapperMethod.SqlCommandは比較的簡単で、このMapperメソッドに対応するMappedStatementのIdとそのメソッドに対応するSqlCommandTypeを含み、SqlCommandTypeにはUNKNOWN,INSERT,UPDATE,DELETE,SELECT,FLUSHのいくつかの値がある.ここで、このMapperメソッドに対応するMappedStatementがない場合、org.apache.ibatis.annotations.Flush注記タグの場合、異常が放出されます.これはよく理解できます.xxxMapperです.xmlには対応する構成がなく,この方法はすべて実行できない.
MapperMethod.MethodSignatureは少し面倒で、MapperMethodを構築します.MethodSignatureのコードは次のとおりです.
Code 5 org.apache.ibatis.binding.MapperMethod.MethodSignature
2行目でMapperを取得するメソッドの戻り値のタイプ.4行目は、配列やCollectionインタフェースが集合であるなど、戻りタイプが集合であるかどうかを取得します.この値は後で分析されます.7行目は、この方法のパラメータにorgが含むか否かを判断する.apache.ibatis.annotations.Param注記、この値は実パラメータの処理に影響します.8行目は、パラメータのRowBoundsタイプの位置を取得します.パラメータに複数のRowBoundsタイプのパラメータが含まれている場合は、例外も放出されます.9行目は8行目と同様にResultHandlerタイプパラメータの位置を取得します.10行目はすごいSortedMapを生成します
MapperMethodを実行します.execute
MapperMethod.executeのコードは次のとおりです.
Code 6 org.apache.ibatis.binding.MapperMethod
コードは異なる状況に対して異なる処理を行うことができず、すべての状況をinsert、delete、update、select、flustに分け、selectでは、戻り値をどのように処理するかによって、それぞれカスタムResultHandler処理、戻りオブジェクトセット、戻りMap、単一オブジェクトを返す.次にflustの状況については議論しません.23行目に見えるorgが呼び出された.apache.ibatis.session.SqlSession.selectOneメソッドはデータベースを操作します.orgについてapache.ibatis.session.SqlSession.selectOneメソッドの類似メソッドがどのように実行されるかは、前のブログを参照してください.他の場合、彼らはorgを呼び出した.apache.ibatis.session.SqlSessionの方法は、2つの点があります:1、適切なorgを選択します.apache.ibatis.session.SqlSessionメソッドが呼び出されます.2.Mapperメソッドが伝達するパラメータをorgに変換する.apache.ibatis.session.SqlSession対応メソッドでサポートされているパラメータ.知ってるよapache.ibatis.session.SqlSessionのパラメータは1つだけで、単一のオブジェクトであるか、集合であるか、Mapであるか、二私たちがMapperメソッドを呼び出したときに渡されたのは複数のパラメータであり、JdbcProxyでは配列形式で保存されているので、パラメータの変換を行います.パラメータ変換呼び出しは、次のようなコードを持つメソッドです.
Code 7 org.apache.ibatis.binding.MapperMethod
5行目、パラメータが1つしかない場合、パラメータにorgがない.apache.ibatis.annotations.Param注記では,配列の配列の最初の値を返し,Mapperメソッドを呼び出す最初の値でもある.他の場合はMapに戻ります.Mapを構築する際には,本ブログで前述したSortedMapを用いた.SortedMapの各位置について、この位置のkeyはシーケンス番号であり、valueはorgである.apache.ibatis.annotations.Param注記の値(シーケンス番号の文字列形式でない場合)は、キー値ペアの形式に変換する必要があります.キー値ペアのkeyはxxxMapperである必要があります.xmlの値を取るkeyはorgであるべきである.apache.ibatis.annotations.Param注記の値(シーケンス番号の文字列形式でない場合)は、ちょうどSortedMapのvalueです.キー値ペアのvalueは,我々がMapperメソッドを呼び出して伝達したパラメータの対応する位置の値であるべきである.11行目のコードはこのようにします.
最後に
濃縮:
Mapperメソッドの実行手順:JdbcProxyプロキシオブジェクトであるMapperオブジェクトを取得します.エージェントオブジェクトコールバックインタフェースでは、Methodに従ってorgが実行する.apache.ibatis.session.SqlSession対応の方法は,同時にパラメータの変換を完了する必要がある.
転載は出典を明記してください.http://blog.csdn.net/bingospunky/article/details/79220894本文は馬彬彬のブログから
前のブログでは、SqlSessionの実行手順について説明しています.しかし、mybatisを使用する場合、一般的にMapperを使用して添削を行います.この文章では、Mapperの方法がどのように実行されているかを示します.Mapperを用いた添削改査は2つのステップに分けられ,第1ステップではまずMapperオブジェクトを取得し,第2部ではMapperメソッドを呼び出す.我々が呼び出したメソッドに対応するxxxMapper.xmlの内容は次のとおりです.
Code 1
<select id="selectById" resultMap="baseResultMap">
select
"baseColumnList"/>
from
table1
where id = #{id}
select>
取得Mapper
取得Mapperの主なコードは次のとおりです.
Code 2 org.apache.ibatis.binding.MapperProxyFactory
public T newInstance(SqlSession sqlSession) {
MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
このコードはMapperProxyFactoryのもので、MapperProxyFactoryの役割はMapperを生成し、1つのMapperが1つのMapperProxyFactoryに対応することです.コードから、私たちが取得したオブジェクトはJdbcProxyによって生成され、エージェントオブジェクトに必要な3つのパラメータが表示されます.1つ目は説明しません.2つ目は私たちが取得するMappeインタフェースです.3番目のパラメータmapperProxyは重要です.それはコールバックです.Mapperインタフェースのメソッドを呼び出すと、mapperProxyのメソッドがコールバックされます.mapperProxyでコールバックメソッドを実装し、データベースを操作する必要があります.mapperProxyについては、クエリー・プロシージャの実行について詳しく説明します.
マッパーを呼び出す方法
取得したMapperオブジェクトはJdbcProxyオブジェクトであるため、メソッドを呼び出すとコールバックインタフェースのメソッドが呼び出されます.コールバックインタフェースのコードは次のとおりです.
Code 3 org.apache.ibatis.binding.MapperProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
} else {
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
}
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method);
if (mapperMethod == null) {
mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
this.methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
9行目はMethodでMapperMethodを取得し、10行目はMapperMethodを呼び出す.executeメソッドは、後で本物のsqlを実行します.MapperMethodを取得する場合、最初に取得する場合は、MapperMethodを構築する必要があります.次に、MapperMethodを構築し、MapperMethodを実行します.executeの2つの部分について説明します.
MapperMethodの作成
MapperMethodを構築するコードは次のとおりです.
Code 4 org.apache.ibatis.binding.MapperMethod
public MapperMethod(Class> mapperInterface, Method method, Configuration config) {
this.command = new MapperMethod.SqlCommand(config, mapperInterface, method);
this.method = new MapperMethod.MethodSignature(config, method);
}
MapperMethod.SqlCommandは比較的簡単で、このMapperメソッドに対応するMappedStatementのIdとそのメソッドに対応するSqlCommandTypeを含み、SqlCommandTypeにはUNKNOWN,INSERT,UPDATE,DELETE,SELECT,FLUSHのいくつかの値がある.ここで、このMapperメソッドに対応するMappedStatementがない場合、org.apache.ibatis.annotations.Flush注記タグの場合、異常が放出されます.これはよく理解できます.xxxMapperです.xmlには対応する構成がなく,この方法はすべて実行できない.
MapperMethod.MethodSignatureは少し面倒で、MapperMethodを構築します.MethodSignatureのコードは次のとおりです.
Code 5 org.apache.ibatis.binding.MapperMethod.MethodSignature
public MethodSignature(Configuration configuration, Method method) {
this.returnType = method.getReturnType();
this.returnsVoid = Void.TYPE.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.mapKey = this.getMapKey(method);
this.returnsMap = this.mapKey != null;
this.hasNamedParameters = this.hasNamedParams(method);
this.rowBoundsIndex = this.getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = this.getUniqueParamIndex(method, ResultHandler.class);
this.params = Collections.unmodifiableSortedMap(this.getParams(method, this.hasNamedParameters));
}
2行目でMapperを取得するメソッドの戻り値のタイプ.4行目は、配列やCollectionインタフェースが集合であるなど、戻りタイプが集合であるかどうかを取得します.この値は後で分析されます.7行目は、この方法のパラメータにorgが含むか否かを判断する.apache.ibatis.annotations.Param注記、この値は実パラメータの処理に影響します.8行目は、パラメータのRowBoundsタイプの位置を取得します.パラメータに複数のRowBoundsタイプのパラメータが含まれている場合は、例外も放出されます.9行目は8行目と同様にResultHandlerタイプパラメータの位置を取得します.10行目はすごいSortedMapを生成します
MapperMethodを実行します.execute
MapperMethod.executeのコードは次のとおりです.
Code 6 org.apache.ibatis.binding.MapperMethod
public Object execute(SqlSession sqlSession, Object[] args) {
Object param;
Object result;
if (SqlCommandType.INSERT == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
} else if (SqlCommandType.UPDATE == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
} else if (SqlCommandType.DELETE == this.command.getType()) {
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
} else if (SqlCommandType.SELECT == this.command.getType()) {
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
} else if (this.method.returnsMap()) {
result = this.executeForMap(sqlSession, args);
} else {
param = this.method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(this.command.getName(), param);
}
} else {
if (SqlCommandType.FLUSH != this.command.getType()) {
throw new BindingException("Unknown execution method for: " + this.command.getName());
}
result = sqlSession.flushStatements();
}
if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
} else {
return result;
}
}
コードは異なる状況に対して異なる処理を行うことができず、すべての状況をinsert、delete、update、select、flustに分け、selectでは、戻り値をどのように処理するかによって、それぞれカスタムResultHandler処理、戻りオブジェクトセット、戻りMap、単一オブジェクトを返す.次にflustの状況については議論しません.23行目に見えるorgが呼び出された.apache.ibatis.session.SqlSession.selectOneメソッドはデータベースを操作します.orgについてapache.ibatis.session.SqlSession.selectOneメソッドの類似メソッドがどのように実行されるかは、前のブログを参照してください.他の場合、彼らはorgを呼び出した.apache.ibatis.session.SqlSessionの方法は、2つの点があります:1、適切なorgを選択します.apache.ibatis.session.SqlSessionメソッドが呼び出されます.2.Mapperメソッドが伝達するパラメータをorgに変換する.apache.ibatis.session.SqlSession対応メソッドでサポートされているパラメータ.知ってるよapache.ibatis.session.SqlSessionのパラメータは1つだけで、単一のオブジェクトであるか、集合であるか、Mapであるか、二私たちがMapperメソッドを呼び出したときに渡されたのは複数のパラメータであり、JdbcProxyでは配列形式で保存されているので、パラメータの変換を行います.パラメータ変換呼び出しは、次のようなコードを持つメソッドです.
Code 7 org.apache.ibatis.binding.MapperMethod
public Object convertArgsToSqlCommandParam(Object[] args) {
int paramCount = this.params.size();
if (args != null && paramCount != 0) {
if (!this.hasNamedParameters && paramCount == 1) {
return args[((Integer)this.params.keySet().iterator().next()).intValue()];
} else {
Map<String, Object> param = new MapperMethod.ParamMap();
int i = 0;
for(Iterator i$ = this.params.entrySet().iterator(); i$.hasNext(); ++i) {
EntryString> entry = (Entry)i$.next();
param.put(entry.getValue(), args[((Integer)entry.getKey()).intValue()]);
String genericParamName = "param" + String.valueOf(i + 1);
if (!param.containsKey(genericParamName)) {
param.put(genericParamName, args[((Integer)entry.getKey()).intValue()]);
}
}
return param;
}
} else {
return null;
}
}
5行目、パラメータが1つしかない場合、パラメータにorgがない.apache.ibatis.annotations.Param注記では,配列の配列の最初の値を返し,Mapperメソッドを呼び出す最初の値でもある.他の場合はMapに戻ります.Mapを構築する際には,本ブログで前述したSortedMapを用いた.SortedMapの各位置について、この位置のkeyはシーケンス番号であり、valueはorgである.apache.ibatis.annotations.Param注記の値(シーケンス番号の文字列形式でない場合)は、キー値ペアの形式に変換する必要があります.キー値ペアのkeyはxxxMapperである必要があります.xmlの値を取るkeyはorgであるべきである.apache.ibatis.annotations.Param注記の値(シーケンス番号の文字列形式でない場合)は、ちょうどSortedMapのvalueです.キー値ペアのvalueは,我々がMapperメソッドを呼び出して伝達したパラメータの対応する位置の値であるべきである.11行目のコードはこのようにします.
最後に
濃縮:
Mapperメソッドの実行手順:JdbcProxyプロキシオブジェクトであるMapperオブジェクトを取得します.エージェントオブジェクトコールバックインタフェースでは、Methodに従ってorgが実行する.apache.ibatis.session.SqlSession対応の方法は,同時にパラメータの変換を完了する必要がある.