• MyBatis 解析运行原理


    提供一个接口

    package com.ming.MyBatis;
    
    
    import com.ming.MyBatis.POJO.Role;
    import com.ming.MyBatis.POJO.Student;
    import com.ming.MyBatis.POJO.StudentCard;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    import java.util.Map;
    
    public interface RoleMapper {
        /**
         * @param id
         * @return
         */
        public Role getRole(int id);
    
        /**
         * 查询Map
         * @param params
         * @return
         */
        public List<Role> findRoleByteMap(Map<String, String> params);
    
    
        /**
         * @param roleName
         * @param note
         * @return
         */
        public List<Role> findRoleByteMap1(@Param("roleName") String roleName, @Param("note") String note);
    
        public List<StudentCard> findStudentSelfCardByStudentId(@Param("studentId") int studentId);
    
        public List<Student> getStudent(@Param("uid")int uid);
    }
    
    

    接口如何生成对象,采用jdk的动态代理技术,生成对象

    CGLB

    使用CGLB动态代理可以实现在不提供接口的时候,生成对象

    构建SqlSessionFactory过程

    在源代码中是

    sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties);
    

    通过new 出一个 SqlSessionFactoryBuilder对象,然后调用build方法.

    进入 SqlSessionFactoryBuilder

    /**
     *    Copyright 2009-2019 the original author or authors.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */
    package org.apache.ibatis.session;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Reader;
    import java.util.Properties;
    
    import org.apache.ibatis.builder.xml.XMLConfigBuilder;
    import org.apache.ibatis.exceptions.ExceptionFactory;
    import org.apache.ibatis.executor.ErrorContext;
    import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
    
    /**
     * Builds {@link SqlSession} instances.
     *
     * @author Clinton Begin
     */
    public class SqlSessionFactoryBuilder {
    
      public SqlSessionFactory build(Reader reader) {
        return build(reader, null, null);
      }
    
      public SqlSessionFactory build(Reader reader, String environment) {
        return build(reader, environment, null);
      }
    
      public SqlSessionFactory build(Reader reader, Properties properties) {
        return build(reader, null, properties);
      }
    
      public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
          return build(parser.parse());
        } catch (Exception e) {
          throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
          ErrorContext.instance().reset();
          try {
            reader.close();
          } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
          }
        }
      }
    
      public SqlSessionFactory build(InputStream inputStream) {
        return build(inputStream, null, null);
      }
    
      public SqlSessionFactory build(InputStream inputStream, String environment) {
        return build(inputStream, environment, null);
      }
    
      public SqlSessionFactory build(InputStream inputStream, Properties properties) {
        return build(inputStream, null, properties);
      }
    
      public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
          return build(parser.parse());
        } catch (Exception e) {
          throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
          ErrorContext.instance().reset();
          try {
            inputStream.close();
          } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
          }
        }
      }
    
      public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
      }
    
    }
    
    

    重写的方法
    通过这一句配置文件读入

    XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
    

    所有的都将会调用该方法

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
          return build(parser.parse());
        } catch (Exception e) {
          throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
          ErrorContext.instance().reset();
          try {
            inputStream.close();
          } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
          }
        }
      }
    

    这一段中

    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    

    这一句
    XML配置读入进入

    由于返回的是XMLConfigBuilder对象 所以是使用该对象去创建SqlSessionFactory对象

    其中SqlSessionFactory为接口

    /**
     *    Copyright 2009-2019 the original author or authors.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */
    package org.apache.ibatis.session;
    
    import java.sql.Connection;
    
    /**
     * Creates an {@link SqlSession} out of a connection or a DataSource
     *
     * @author Clinton Begin
     */
    public interface SqlSessionFactory {
    
      SqlSession openSession();
    
      SqlSession openSession(boolean autoCommit);
    
      SqlSession openSession(Connection connection);
    
      SqlSession openSession(TransactionIsolationLevel level);
    
      SqlSession openSession(ExecutorType execType);
    
      SqlSession openSession(ExecutorType execType, boolean autoCommit);
    
      SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
    
      SqlSession openSession(ExecutorType execType, Connection connection);
    
      Configuration getConfiguration();
    
    }
    

    其中根据源码可以看到XMLConfigBuilder对象继承于BaseBuilder, BaseBuilder为抽象类 其中的BaseBuilder 继承 XMLConfigBuilder

    所以,这两句成立

    private volatile static SqlSessionFactory sqlSessionFactory = null;
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties);
    

    最后就有了SqlSessionFactory实现类

    这种创建为Builder创建

    进入XMLConfigBuilder 可以看到第115行

          // read it after objectFactory and objectWrapperFactory issue #631
          environmentsElement(root.evalNode("environments"));
    

    可以看到读入配置文件environments节点

    其中还可以看到

      private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
        super(new Configuration());
        ErrorContext.instance().resource("SQL Mapper Configuration");
        this.configuration.setVariables(props);
        this.parsed = false;
        this.environment = environment;
        this.parser = parser;
      }
    

    使用的是super 所以进入 Configuration()对象
    可以看到这是所有的配置文件

    
      public Configuration() {
        typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
        typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
    
        typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
        typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
        typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
    
        typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
        typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
        typeAliasRegistry.registerAlias("LRU", LruCache.class);
        typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
        typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
    
        typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
    
        typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
        typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
    
        typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
        typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
        typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
        typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
        typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
        typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
        typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
    
        typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
        typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
    
        languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
        languageRegistry.register(RawLanguageDriver.class);
      }
    
    

    配置文件信息将会在这个类中保存

    该类中的方法MappedStatement 为获取映射器的节点

      public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
        if (validateIncompleteStatements) {
          buildAllStatements();
        }
        return mappedStatements.get(id);
      }
    
    public final class MappedStatement {
    
      private String resource;
      private Configuration configuration;
      private String id;
      private Integer fetchSize;
      private Integer timeout;
      private StatementType statementType;
      private ResultSetType resultSetType;
      private SqlSource sqlSource;
      private Cache cache;
      private ParameterMap parameterMap;
      private List<ResultMap> resultMaps;
      private boolean flushCacheRequired;
      private boolean useCache;
      private boolean resultOrdered;
      private SqlCommandType sqlCommandType;
      private KeyGenerator keyGenerator;
      private String[] keyProperties;
      private String[] keyColumns;
      private boolean hasNestedResultMaps;
      private String databaseId;
      private Log statementLog;
      private LanguageDriver lang;
      private String[] resultSets;
    

    这里进入的是映射器的节点信息

    在插件中可以通过MappedStatement类,来获取到映射器的节点,即,获取到映射器的信息.在Tomcat编译成为class文件的时候,会写死在class文件中..

    其中MappedStatement为final类型

    在映射类的第43行有一个重要的属性

      private SqlSource sqlSource;
    

    进入该接口

    public interface SqlSource {
    
      BoundSql getBoundSql(Object parameterObject);
    
    }
    

    其接口有方法

      BoundSql getBoundSql(Object 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<>();
        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有三个属性,

        this.sql = sql;
        this.parameterMappings = parameterMappings;
        // 传递进入的参数 根据Param注解
        this.parameterObject = parameterObject;
        this.additionalParameters = new HashMap<>();
        this.metaParameters = configuration.newMetaObject(additionalParameters);
    

    SqlSession运行

    SqlSession通过动态代理的方式运行

    首先 SqlSessionFactory sqlSessionFactory 是SqlSessionFactory接口
    SqlSession类如下

    /**
     *    Copyright 2009-2019 the original author or authors.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */
    package org.apache.ibatis.session;
    
    import java.sql.Connection;
    
    /**
     * Creates an {@link SqlSession} out of a connection or a DataSource
     *
     * @author Clinton Begin
     */
    public interface SqlSessionFactory {
    
      SqlSession openSession();
    
      SqlSession openSession(boolean autoCommit);
    
      SqlSession openSession(Connection connection);
    
      SqlSession openSession(TransactionIsolationLevel level);
    
      SqlSession openSession(ExecutorType execType);
    
      SqlSession openSession(ExecutorType execType, boolean autoCommit);
    
      SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
    
      SqlSession openSession(ExecutorType execType, Connection connection);
    
      Configuration getConfiguration();
    
    }
    

    首先try里面的第四行

                sqlSession = SqlSessionFactoryUtil.openSqlSesion();
                roleMapper = sqlSession.getMapper(RoleMapper.class);
                students = roleMapper.getStudent(1);
                students1 = roleMapper.getStudent(1);
                sqlSession.commit();
    

    进入getMapper

    /**
     *    Copyright 2009-2019 the original author or authors.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */
    package org.apache.ibatis.session;
    
    import java.io.Closeable;
    import java.sql.Connection;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.ibatis.cursor.Cursor;
    import org.apache.ibatis.executor.BatchResult;
    
    /**
     * The primary Java interface for working with MyBatis.
     * Through this interface you can execute commands, get mappers and manage transactions.
     *
     * @author Clinton Begin
     */
    public interface SqlSession extends Closeable {
    
      /**
       * Retrieve a single row mapped from the statement key.
       * @param <T> the returned object type
       * @param statement
       * @return Mapped object
       */
      <T> T selectOne(String statement);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter.
       * @param <T> the returned object type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return Mapped object
       */
      <T> T selectOne(String statement, Object parameter);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement, Object parameter);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter,
       * within the specified row bounds.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param rowBounds  Bounds to limit object retrieval
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id")
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param mapKey The property to use as key for each value in the list.
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, String mapKey);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param mapKey The property to use as key for each value in the list.
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param mapKey The property to use as key for each value in the list.
       * @param rowBounds  Bounds to limit object retrieval
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement, Object parameter);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param rowBounds  Bounds to limit object retrieval
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter
       * using a {@code ResultHandler}.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, Object parameter, ResultHandler handler);
    
      /**
       * Retrieve a single row mapped from the statement
       * using a {@code ResultHandler}.
       * @param statement Unique identifier matching the statement to use.
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, ResultHandler handler);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter
       * using a {@code ResultHandler} and {@code RowBounds}.
       * @param statement Unique identifier matching the statement to use.
       * @param rowBounds RowBound instance to limit the query results
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
    
      /**
       * Execute an insert statement.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the insert.
       */
      int insert(String statement);
    
      /**
       * Execute an insert statement with the given parameter object. Any generated
       * autoincrement values or selectKey entries will modify the given parameter
       * object properties. Only the number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the insert.
       */
      int insert(String statement, Object parameter);
    
      /**
       * Execute an update statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the update.
       */
      int update(String statement);
    
      /**
       * Execute an update statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the update.
       */
      int update(String statement, Object parameter);
    
      /**
       * Execute a delete statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the delete.
       */
      int delete(String statement);
    
      /**
       * Execute a delete statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the delete.
       */
      int delete(String statement, Object parameter);
    
      /**
       * Flushes batch statements and commits database connection.
       * Note that database connection will not be committed if no updates/deletes/inserts were called.
       * To force the commit call {@link SqlSession#commit(boolean)}
       */
      void commit();
    
      /**
       * Flushes batch statements and commits database connection.
       * @param force forces connection commit
       */
      void commit(boolean force);
    
      /**
       * Discards pending batch statements and rolls database connection back.
       * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
       * To force the rollback call {@link SqlSession#rollback(boolean)}
       */
      void rollback();
    
      /**
       * Discards pending batch statements and rolls database connection back.
       * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
       * @param force forces connection rollback
       */
      void rollback(boolean force);
    
      /**
       * Flushes batch statements.
       * @return BatchResult list of updated records
       * @since 3.0.6
       */
      List<BatchResult> flushStatements();
    
      /**
       * Closes the session.
       */
      @Override
      void close();
    
      /**
       * Clears local session cache.
       */
      void clearCache();
    
      /**
       * Retrieves current configuration.
       * @return Configuration
       */
      Configuration getConfiguration();
    
      /**
       * Retrieves a mapper.
       * @param <T> the mapper type
       * @param type Mapper interface class
       * @return a mapper bound to this SqlSession
       */
      <T> T getMapper(Class<T> type);
    
      /**
       * Retrieves inner database connection.
       * @return Connection
       */
      Connection getConnection();
    }
    

    这是一个接口
    其中DefaultSqlSession为旧版本,新版本使用的是SqlSessionManager
    进入SqlSessionManager

      @Override
      public <T> T getMapper(Class<T> type) {
        return getConfiguration().getMapper(type, this);
      }
    

    可以看到使用getConfiguration().getMapper(type, this);
    getConfiguration()为获取配置信息,mapperRegistry为映射配置类的映射注册表,进入getMapper

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
          throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        }
        try {
          return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
          throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
      }
    

    如下

     @SuppressWarnings("unchecked")
      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
          throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
        }
        try {
          return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
          throw new BindingException("Error getting mapper instance. Cause: " + e, e);
        }
      }
    

    然后进入代理工厂类

    public class MapperProxyFactory<T> {
    
      private final Class<T> mapperInterface;
      private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();
    
      public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
      }
    
      public Class<T> getMapperInterface() {
        return mapperInterface;
      }
    
      public Map<Method, MapperMethod> getMethodCache() {
        return methodCache;
      }
    
      @SuppressWarnings("unchecked")
      protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
      }
    
      public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
      }
    
    }
    

    有这么一句

      @SuppressWarnings("unchecked")
      protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
      }
    

    调用的是这一句

      public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
      }
    
    

    在MapperProxy中有如下几个

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          if (Object.class.equals(method.getDeclaringClass())) {
            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);
        return mapperMethod.execute(sqlSession, args);
      }
    

    通过动态代理生成该对象
    然后接着查看execute源码

     public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        switch (command.getType()) {
          case INSERT: {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = 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);
              if (method.returnsOptional()
                  && (result == null || !method.getReturnType().equals(result.getClass()))) {
                result = Optional.ofNullable(result);
              }
            }
            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;
      }
    

    这里就能看到sql啦

    接着任意进入一个

    private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
        List<E> result;
        Object param = method.convertArgsToSqlCommandParam(args);
        if (method.hasRowBounds()) {
          RowBounds rowBounds = method.extractRowBounds(args);
          result = sqlSession.selectList(command.getName(), param, rowBounds);
        } else {
          result = sqlSession.selectList(command.getName(), param);
        }
        // issue #510 Collections & arrays support
        if (!method.getReturnType().isAssignableFrom(result.getClass())) {
          if (method.getReturnType().isArray()) {
            return convertToArray(result);
          } else {
            return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
          }
        }
        return result;
      }
    

    不想看了.....反正就是最后调用sqlsession的

    
    /**
     * The primary Java interface for working with MyBatis.
     * Through this interface you can execute commands, get mappers and manage transactions.
     *
     * @author Clinton Begin
     */
    public interface SqlSession extends Closeable {
    
      /**
       * Retrieve a single row mapped from the statement key.
       * @param <T> the returned object type
       * @param statement
       * @return Mapped object
       */
      <T> T selectOne(String statement);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter.
       * @param <T> the returned object type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return Mapped object
       */
      <T> T selectOne(String statement, Object parameter);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement, Object parameter);
    
      /**
       * Retrieve a list of mapped objects from the statement key and parameter,
       * within the specified row bounds.
       * @param <E> the returned list element type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param rowBounds  Bounds to limit object retrieval
       * @return List of mapped object
       */
      <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id")
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param mapKey The property to use as key for each value in the list.
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, String mapKey);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param mapKey The property to use as key for each value in the list.
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
    
      /**
       * The selectMap is a special case in that it is designed to convert a list
       * of results into a Map based on one of the properties in the resulting
       * objects.
       * @param <K> the returned Map keys type
       * @param <V> the returned Map values type
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param mapKey The property to use as key for each value in the list.
       * @param rowBounds  Bounds to limit object retrieval
       * @return Map containing key pair data.
       */
      <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement, Object parameter);
    
      /**
       * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.
       * @param <T> the returned cursor element type.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param rowBounds  Bounds to limit object retrieval
       * @return Cursor of mapped objects
       */
      <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter
       * using a {@code ResultHandler}.
       * @param statement Unique identifier matching the statement to use.
       * @param parameter A parameter object to pass to the statement.
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, Object parameter, ResultHandler handler);
    
      /**
       * Retrieve a single row mapped from the statement
       * using a {@code ResultHandler}.
       * @param statement Unique identifier matching the statement to use.
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, ResultHandler handler);
    
      /**
       * Retrieve a single row mapped from the statement key and parameter
       * using a {@code ResultHandler} and {@code RowBounds}.
       * @param statement Unique identifier matching the statement to use.
       * @param rowBounds RowBound instance to limit the query results
       * @param handler ResultHandler that will handle each retrieved row
       */
      void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
    
      /**
       * Execute an insert statement.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the insert.
       */
      int insert(String statement);
    
      /**
       * Execute an insert statement with the given parameter object. Any generated
       * autoincrement values or selectKey entries will modify the given parameter
       * object properties. Only the number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the insert.
       */
      int insert(String statement, Object parameter);
    
      /**
       * Execute an update statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the update.
       */
      int update(String statement);
    
      /**
       * Execute an update statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the update.
       */
      int update(String statement, Object parameter);
    
      /**
       * Execute a delete statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @return int The number of rows affected by the delete.
       */
      int delete(String statement);
    
      /**
       * Execute a delete statement. The number of rows affected will be returned.
       * @param statement Unique identifier matching the statement to execute.
       * @param parameter A parameter object to pass to the statement.
       * @return int The number of rows affected by the delete.
       */
      int delete(String statement, Object parameter);
    
      /**
       * Flushes batch statements and commits database connection.
       * Note that database connection will not be committed if no updates/deletes/inserts were called.
       * To force the commit call {@link SqlSession#commit(boolean)}
       */
      void commit();
    
      /**
       * Flushes batch statements and commits database connection.
       * @param force forces connection commit
       */
      void commit(boolean force);
    
      /**
       * Discards pending batch statements and rolls database connection back.
       * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
       * To force the rollback call {@link SqlSession#rollback(boolean)}
       */
      void rollback();
    
      /**
       * Discards pending batch statements and rolls database connection back.
       * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
       * @param force forces connection rollback
       */
      void rollback(boolean force);
    
      /**
       * Flushes batch statements.
       * @return BatchResult list of updated records
       * @since 3.0.6
       */
      List<BatchResult> flushStatements();
    
      /**
       * Closes the session.
       */
      @Override
      void close();
    
      /**
       * Clears local session cache.
       */
      void clearCache();
    
      /**
       * Retrieves current configuration.
       * @return Configuration
       */
      Configuration getConfiguration();
    
      /**
       * Retrieves a mapper.
       * @param <T> the mapper type
       * @param type Mapper interface class
       * @return a mapper bound to this SqlSession
       */
      <T> T getMapper(Class<T> type);
    
      /**
       * Retrieves inner database connection.
       * @return Connection
       */
      Connection getConnection();
    }
    

    映射器的本质是动态代理对象

    最后都是调用sqlsession接口的定义的方法完成和数据库的交互

    在无知的道路上缓步前行
  • 相关阅读:
    Qt编程之qrc文件的链接
    Visual Studio中的lib的链接顺序
    c++语言中的遍历
    转载:使用 OpenCV 识别 QRCode
    GreenOpenPaint的实现(四)放大缩小处理滚动事件
    GreenOpenPaint的实现(六)图片的保存和打开
    GreenOpenPaint的实现(五)矩形框
    GreenOpenPaint的实现(三)添加标尺
    GreenOpenPaint的实现(二)打开显示图片
    GreenOpenPaint的实现(一)基本框架
  • 原文地址:https://www.cnblogs.com/melovemingming/p/10764768.html
Copyright © 2020-2023  润新知