mybatis

时间:2019-11-27
本文章向大家介绍mybatis,主要包括mybatis使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

基于JDBC的。

public class JDBCDemo {
    public static void main(String[] args) throws SQLException {
    // System.out.println(get(1));
        System.out.println(insert(new Test(null, 66, "jdbc insert")));
    }

    public static int insert(Test test) throws SQLException {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/gp?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", "root", "123456");
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement("INSERT INTO test VALUES (?,?,?)");
            if (null != test.getId()) {
                preparedStatement.setInt(1, test.getId());
            } else {
                preparedStatement.setNull(1, INTEGER);
            }
            preparedStatement.setInt(2, test.getNums());
            preparedStatement.setString(3, test.getName());
            connection.commit();
            return preparedStatement.executeUpdate();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    public static Test get(int id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        Test test = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/gp?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", "root", "123456");
            preparedStatement = connection.prepareStatement("SELECT * FROM aa WHERE id = ?");
            preparedStatement.setInt(1, id);
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                test = new Test();
                test.setId(rs.getInt(1));
                test.setNums(rs.getInt(2));
                test.setName(rs.getString(3));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != connection) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return test;
    }
}
public static void main(String[] args) throws FileNotFoundException {
        SqlSession sqlSession = getSqlSession();   //SqlSession是一个管道,跟db的一个会话,
        try { 
            System.out.println(getOne(sqlSession, 1)); 
        }  inally {
            sqlSession.commit();  
            sqlSession.close(); //SqlSession要关闭,相当于是jdbc的connection,连接到DB上,如果是线程池就要归还。
        }
    }
public static SqlSession getSqlSession() throws FileNotFoundException {
        //配置文件
        InputStream configFile = new FileInputStream(
                "E:\\BaiduNetdiskDownload\\01、mybatis源码分析加实战视频教程\\gupaoedu-mybatis\\gupaoedu-mybatis\\src\\main\\java\\com\\gupaoedu\\mybatis\\demo\\mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configFile);
        //加载配置文件得到SqlSessionFactory
        return sqlSessionFactory.openSession();
    }
public static Test getOne(SqlSession sqlSession, int id) throws SQLException {
        TestMapper testMapper = sqlSession.getMapper(TestMapper.class);    //org.apache.ibatis.session.defaults.DefaultSqlSession
        long start = System.currentTimeMillis();
        Test test = testMapper.selectByPrimaryKey(id);    //委托给Mapper去执行,
        System.out.println("cost:" + (System.currentTimeMillis() - start));
        return test;
    }
public interface TestMapper { 
    Test selectByPrimaryKey(Integer id); 
}

public class Test {
    private Integer id;
    private String name;
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="SLF4J"/>
        <!--<setting name="cacheEnabled" value="true" />-->
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/upgrade?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="xml/TestMapper.xml"/>
    </mappers>
</configuration>
public class DefaultSqlSession implements SqlSession {
  private Configuration configuration;   //配置文件,
  private Executor executor;   //操作数据库的,
}
new SqlSessionFactoryBuilder().build(configFile);

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);   //E:\BaiduNetdiskDownload\01、mybatis\gupaoedu-mybatis\gupaoedu-mybatis\src\main\java\com\gupaoedu\mybatis\demo\mybatis-config.xml,返回
      return build(parser.parse());
    }  finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } 
    }
  }
public Configuration parse() { //解析mybatis-config.xml,生成configuration,把TestMapper接口和TestMapper.xml映射起来了,
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));   //解析mybatis-config.xml的<configuration>标签,
    return configuration;
  }
private void parseConfiguration(XNode root) {   //root = mybatis-config.xml的内容,
    try { 
      propertiesElement(root.evalNode("properties")); //<properties>标签,
      Properties settings = settingsAsProperties(root.evalNode("settings"));    //<settings>标签,
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));   //插件,
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings); 
      environmentsElement(root.evalNode("environments"));   //<environments标签
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));   //<mappers>标签,<mapper resource="xml/TestMapper.xml"/>
    }  
  }
//解析TestMapper.xml,把TestMapper接口和TestMapper.xml映射起来了,
private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) { 
        } else {
          String resource = child.getStringAttribute("resource");   //xml/TestMapper.xml
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          }  
        }
      }
    }
  }
//解析TestMapper.xml,把TestMapper接口和TestMapper.xml映射起来了,
private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) { 
        } else {
          String resource = child.getStringAttribute("resource");   //xml/TestMapper.xml
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          }  
        }
      }
    }
  }
private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");   //com.gupaoedu.mybatis.mapper.TestMapper 
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));   //解析parameterMap标签,
      resultMapElements(context.evalNodes("/mapper/resultMap"));   //解析resultMap标签,
      sqlElement(context.evalNodes("/mapper/sql"));   //解析sql标签,
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));  //解析select|insert|update|delete标签,
    }  
  }
public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);   //config解析了mybatis-config.xml,TestMapper,TestMapper.xml
  }

public SqlSession openSession() {  //拿到SqlSession,
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();  //org.apache.ibatis.mapping.Environment
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);    //org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);  //org.apache.ibatis.executor.CachingExecutor
      return new DefaultSqlSession(configuration, executor, autoCommit);
    }   finally {
      ErrorContext.instance().reset();
    }
  }
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 = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
sqlSession.getMapper(TestMapper.class);    //拿到Mapper

public <T> T getMapper(Class<T> type) {
    return configuration.<T>getMapper(type, this);   //org.apache.ibatis.session.Configuration,interface com.gupaoedu.mybatis.mapper.TestMapper,org.apache.ibatis.session.defaults.DefaultSqlSession
  }

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);   //org.apache.ibatis.binding.MapperRegistry,interface com.gupaoedu.mybatis.mapper.TestMapper,org.apache.ibatis.session.defaults.DefaultSqlSession
  }
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); //{interface com.gupaoedu.mybatis.mapper.TestMapper=org.apache.ibatis.binding.MapperProxyFactory,type = interface com.gupaoedu.mybatis.mapper.TestMapper。返回org.apache.ibatis.binding.MapperProxyFactory就是Mapper的代理工厂。
    try {
      return mapperProxyFactory.newInstance(sqlSession);    //org.apache.ibatis.session.defaults.DefaultSqlSession
    } 
  }
public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);//Mapper的代理,org.apache.ibatis.session.defaults.DefaultSqlSession,interface com.gupaoedu.mybatis.mapper.TestMapper,
    return newInstance(mapperProxy);  //org.apache.ibatis.binding.MapperProxy
  }
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);    //AppClassLoader,interface com.gupaoedu.mybatis.mapper.TestMapper,org.apache.ibatis.binding.MapperProxy,返回org.apache.ibatis.binding.MapperProxy里面的 h 的mapperInterface = interface com.gupaoedu.mybatis.mapper.TestMapper,sqlSession = org.apache.ibatis.session.defaults.DefaultSqlSession,DefaultSqlSession里面有TestMapper.xml的内容。
  }
//jdk的动态代理
public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,  InvocationHandler h)  {
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        } 
        Class<?> cl = getProxyClass0(loader, intfs); 
        return cons.newInstance(new Object[]{h});
        }  
    }
testMapper.selectByPrimaryKey(id);    //委托给Mapper去执行, 拿到Mapper之后就要操作数据库了。
 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    final MapperMethod mapperMethod = cachedMapperMethod(method);    //public  TestMapper.selectByPrimaryKey(java.lang.Integer),
    return mapperMethod.execute(sqlSession, args);
  }
private MapperMethod cachedMapperMethod(Method method) {
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());   //interface com.gupaoedu.mybatis.mapper.TestMapper,public  TestMapper.selectByPrimaryKey(java.lang.Integer),org.apache.ibatis.session.Configuration里面有TestMapper.xml的内容,
      methodCache.put(method, mapperMethod);
    }
    return mapperMethod;  //org.apache.ibatis.binding.MapperMethod
  }
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new SqlCommand(config, mapperInterface, method);   //org.apache.ibatis.session.Configuration,interface com.gupaoedu.mybatis.mapper.TestMapper,public  TestMapper.selectByPrimaryKey(java.lang.Integer)
    this.method = new MethodSignature(config, mapperInterface, method);   //public TestMapper.selectByPrimaryKey(java.lang.Integer)
  }
public Object execute(SqlSession sqlSession, Object[] args) {   //org.apache.ibatis.session.defaults.DefaultSqlSession,[1],
    Object result;
    switch (command.getType()) { 
      case SELECT:   {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);    //name = com.gupaoedu.mybatis.mapper.TestMapper.selectByPrimaryKey,1,
        }
        break; 
    return result;
  }
DefaultSqlSession类:
public <T> T selectOne(String statement, Object parameter) { 
    List<T> list = this.<T>selectList(statement, parameter);   //statement = com.gupaoedu.mybatis.mapper.TestMapper.selectByPrimaryKey,
    if (list.size() == 1) {
      return list.get(0);
    }   
  }
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);    //org.apache.ibatis.executor.CachingExecutor,带缓存的Executor,CachingExecutor里面有Executor delegate;就是委托。
    } 
  }
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);    //select  id,  name from aa where id = ?
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);    //缓存的key  =  -551692175:2852254523:com.gupaoedu.mybatis.mapper.TestMapper.selectByPrimaryKey:0:2147483647:select  id,    name from aa  where id = ?:1:development
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {
    Cache cache = ms.getCache(); 
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { 
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();   // configuration 是 xml/TestMapper.xml的内容, 返回ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);     //org.apache.ibatis.executor.statement.RoutingStatementHandler
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
  }
protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = transaction.getConnection(); //ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    }  
  }
public Connection getConnection() throws SQLException {
    if (connection == null) {
      openConnection();
    }
    return connection; //ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
  }
protected void openConnection() throws SQLException { 
    connection = dataSource.getConnection(); //ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
    if (level != null) {
      connection.setTransactionIsolation(level.getLevel());
    }
    setDesiredAutoCommit(autoCommmit);
  }
public Connection getConnection() throws SQLException {
    return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();   //PooledConnection里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},,
  }
conn = new PooledConnection(dataSource.getConnection(), this);

public Connection getConnection() throws SQLException {
    return doGetConnection(username, password);
  }

private Connection doGetConnection(Properties properties) throws SQLException {
    initializeDriver();
    Connection connection = DriverManager.getConnection(url, properties);    //ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
    configureConnection(connection);
    return connection;
  }
DriverManager类的方法(java.sql包):前面都是mybatis的包,现在是jdk的包。
public static Connection getConnection(String url,
        java.util.Properties info)  {
        return (getConnection(url, info, Reflection.getCallerClass()));
    }

Connection con = aDriver.driver.connect(url, info);
private synchronized void initializeDriver() throws SQLException {
    if (!registeredDrivers.containsKey(driver)) {
      Class<?> driverType;
      try {
        if (driverClassLoader != null) {
          driverType = Class.forName(driver, true, driverClassLoader);   //com.mysql.cj.jdbc.Driver
        } else {
          driverType = Resources.classForName(driver);
        } 
        Driver driverInstance = (Driver)driverType.newInstance();
        DriverManager.registerDriver(new DriverProxy(driverInstance));
        registeredDrivers.put(driver, driverInstance);   //{com.mysql.cj.jdbc.Driver=com.mysql.cj.jdbc.Driver@1cbb87f3}
      }  
    }
  }
mysql-connector的包,就是驱动包。
public java.sql.Connection connect(String url, Properties info) throws SQLException {
        try {
            ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info); 
            switch (conStr.getType()) { 
                default:
                    return com.mysql.cj.jdbc.ConnectionImpl.getInstance(conStr.getMainHost());   //Host  =  com.mysql.cj.conf.HostInfo@6f10d5b6 :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
            }
        }  
    }
public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) { 
        String connStringCacheKey = buildConnectionStringCacheKey(connString, info);   //jdbc:mysql://127.0.0.1:3306/upgrade?useUnicode=true;characterEncoding=UTF-8;allowMultiQueries=true;useSSL=false??{user=root, password=123456}  
        if (connectionString == null) { 
            try { 
                if (connectionString == null) {
                    ConnectionUrlParser connStrParser = ConnectionUrlParser.parseConnectionString(connString);   //com.mysql.cj.conf.ConnectionUrlParser@508dec2b :: {scheme: "jdbc:mysql:", authority: "127.0.0.1:3306", path: "upgrade", query: "useUnicode=true;characterEncoding=UTF-8;allowMultiQueries=true;useSSL=false", parsedHosts: null, parsedProperties: null} 

                    switch (Type.fromValue(connStrParser.getScheme(), connStrParser.getHosts().size())) {
                        case SINGLE_CONNECTION:
                            connectionString = (ConnectionUrl) Util.getInstance("com.mysql.cj.conf.url.SingleConnectionUrl",
                                    new Class<?>[] { ConnectionUrlParser.class, Properties.class }, new Object[] { connStrParser, info }, null);   //com.mysql.cj.conf.url.SingleConnectionUrl :: {type: "SINGLE_CONNECTION", hosts: [com.mysql.cj.conf.HostInfo :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}}], database: "upgrade", properties: {user=root, password=, useSSL=false}, propertiesTransformer: null}
                            break;
                    }
                    connectionUrlCache.put(connStringCacheKey, connectionString);   //connectionUrlCache = {} jdbc:mysql://localhost:3306/upgrade?useSSL=false??{user=root, password=}  =  {com.mysql.cj.conf.url.SingleConnectionUrl} "com.mysql.cj.conf.url.SingleConnectionUrl :: {type: "SINGLE_CONNECTION", hosts: [com.mysql.cj.conf.HostInfo :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}}], database: "upgrade", properties: {user=root, password=, useSSL=false}, propertiesTransformer: null}"
                }
            } 
        }
        return connectionString;   //com.mysql.cj.conf.url.SingleConnectionUrl :: {type: "SINGLE_CONNECTION", hosts: [com.mysql.cj.conf.HostInfo :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}}], database: "upgrade", properties: {user=root, password=, useSSL=false}, propertiesTransformer: null}
    }
public static JdbcConnection getInstance(HostInfo hostInfo) throws SQLException {
        return new ConnectionImpl(hostInfo);   //hostInfo  =  com.mysql.cj.conf.HostInfo@6f10d5b6 :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}}
    }

public ConnectionImpl(HostInfo hostInfo) throws SQLException {
        try {
            this.origHostInfo = hostInfo;   //com.mysql.cj.conf.HostInfo@6f10d5b6 :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}}
            this.origHostToConnectTo = hostInfo.getHost();  //localhost
            this.origPortToConnectTo = hostInfo.getPort();   //3306
            this.database = hostInfo.getDatabase();   //upgrade
            this.user = StringUtils.isNullOrEmpty(hostInfo.getUser()) ? "" : hostInfo.getUser();    //root
            this.password = StringUtils.isNullOrEmpty(hostInfo.getPassword()) ? "" : hostInfo.getPassword();    //“”
            this.props = hostInfo.exposeAsProperties();    // {HOST=localhost, user=root, password=, DBNAME=upgrade, PORT=3306, useSSL=false}
            this.pointOfOrigin = this.useUsageAdvisor.getValue() ? LogUtils.findCallingClassAndMethod(new Throwable()) : "";
        }  
        try {
            createNewIO(false);
            unSafeQueryInterceptors();
            NonRegisteringDriver.trackConnection(this);
        }  
    }
public PooledConnection(Connection connection, PooledDataSource dataSource) {
    this.hashCode = connection.hashCode();
    this.realConnection = connection;      //ConnectionImpl里面有数据库的连接信息com.mysql.cj.conf.HostInfo@305ffe9e :: {host: "localhost", port: 3306, user: root, password: , hostProperties: {DBNAME=upgrade, useSSL=false}},
    this.dataSource = dataSource;
    this.createdTimestamp = System.currentTimeMillis();
    this.lastUsedTimestamp = System.currentTimeMillis();
    this.valid = true;
    this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
  }
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;    //缓存
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      } 
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { 
        clearLocalCache();
      }
    }
    return list;
  }

原文地址:https://www.cnblogs.com/yaowen/p/11945127.html