概述
|
|
Insert One Or More Than One?
关于XMLStatementBuilder
从下面的代码中我们可以看到当声明了useGenerateKeys属性则会使用Jdbc3KeyGenerator,而申明了selectKey元素则会使用SelectKeyGenerator。
|
|
Jdbc3KeyGenerator AND SelectKeyGenerator
|
|
|
|
Did Not Work?
|
|
总结
|
|
流程图
关键类
MapperProxy
Mybatis 所有Mapper接口的代理类
|
|
MapperMethod
Mapper接口方法动态代理执行的分装类
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697public class MapperMethod {private final SqlCommand command;private final MethodSignature method;public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {this.command = new SqlCommand(config, mapperInterface, method);this.method = new MethodSignature(config, mapperInterface, method);}public Object execute(SqlSession sqlSession, Object[] args) {Object result;switch (command.getType()) {case INSERT: {//STEP 2Object param = method.convertArgsToSqlCommandParam(args);//如果是插入方法,这返回插入的条数//STEP 5result = rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT:if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else if (method.returnsCursor()) {result = executeForCursor(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);}break;case FLUSH:result = sqlSession.flushStatements();break;default:throw new BindingException("Unknown execution method for: " + command.getName());}if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {throw new BindingException("Mapper method '" + command.getName()+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");}return result;}public static class MethodSignature {private final boolean returnsMany;private final boolean returnsMap;private final boolean returnsVoid;private final boolean returnsCursor;private final Class<?> returnType;private final String mapKey;private final Integer resultHandlerIndex;private final Integer rowBoundsIndex;private final ParamNameResolver paramNameResolver;public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);if (resolvedReturnType instanceof Class<?>) {this.returnType = (Class<?>) resolvedReturnType;} else if (resolvedReturnType instanceof ParameterizedType) {this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();} else {this.returnType = method.getReturnType();}this.returnsVoid = void.class.equals(this.returnType);this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());this.returnsCursor = Cursor.class.equals(this.returnType);this.mapKey = getMapKey(method);this.returnsMap = (this.mapKey != null);this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);this.paramNameResolver = new ParamNameResolver(configuration, method);}public Object convertArgsToSqlCommandParam(Object[] args) {// STEP 3 获取参数return paramNameResolver.getNamedParams(args);}}}ParamNameResolver
Mybatis中在中MethodSignature中用于根据方法来确定参数名
12345678910111213141516171819202122232425262728293031public class ParamNameResolver {private static final String GENERIC_NAME_PREFIX = "param";public Object getNamedParams(Object[] args) {final int paramCount = names.size();if (args == null || paramCount == 0) {//如果参数个数为0,则直接返回nullreturn null;} else if (!hasParamAnnotation && paramCount == 1) {//如果参数个数为1并且没有添加Param注解,则直接返回入参//STEP 4return args[names.firstKey()];} else {final Map<String, Object> param = new ParamMap<Object>();int i = 0;for (Map.Entry<Integer, String> entry : names.entrySet()) {param.put(entry.getValue(), args[entry.getKey()]);// add generic param names (param1, param2, ...)final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);// ensure not to overwrite parameter named with @Paramif (!names.containsValue(genericParamName)) {param.put(genericParamName, args[entry.getKey()]);}i++;}return param;}}}
SqlSessionTemplate
mybatis的SqlSession在spring中的实现类
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061public class SqlSessionTemplate implements SqlSession, DisposableBean {private final SqlSessionFactory sqlSessionFactory;private final ExecutorType executorType;private final SqlSession sqlSessionProxy;private final PersistenceExceptionTranslator exceptionTranslator;/*** {@inheritDoc}*/@Overridepublic int insert(String statement, Object parameter) {//带参数的插入方法执行类//STEP 6return this.sqlSessionProxy.insert(statement, parameter);}/*** 在执行mybatis中的SqlSession类方法之前的拦截器类,主要操作是从spring的事务管理器中获取适合的* sqlsession,同时*/private class SqlSessionInterceptor implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,SqlSessionTemplate.this.executorType,SqlSessionTemplate.this.exceptionTranslator);try {//STEP 7Object result = method.invoke(sqlSession, args);if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {// force commit even on non-dirty sessions because some databases require// a commit/rollback before calling close()sqlSession.commit(true);}return result;} catch (Throwable t) {Throwable unwrapped = unwrapThrowable(t);if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {// release the connection to avoid a deadlock if the translator is no loaded. See issue #22closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);sqlSession = null;Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);if (translated != null) {unwrapped = translated;}}throw unwrapped;} finally {if (sqlSession != null) {closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);}}}}}
DefaultSqlSession
mybatis中sqlsession接口的默认实现类
|
|
CachingExecutor
mybatis中具体sql的执行类
|
|
BaseExecutor
mybatis的Executor接口的基础实现类
|
|
- ReuseExecutor
|
|
RoutingStatementHandler
mybatis中各种StatementHandler的路由类
|
|
PreparedStatementHandler
mybatis中prepare类型的statement处理实现类
|
|
SelectKeyGenerator
自增主键生成之后的处理类
|
|
Jdbc3KeyGenerator
默认自增主键生成类
|
|
MetaObject
元数据对象
|
|
BeanWrapper
普通对象包装类
|
|
MapWrapper
Map对象包装类
|
|