Java专题十四:JDBC

Posted 黄先生的日志

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java专题十四:JDBC相关的知识,希望对你有一定的参考价值。

Java专题十四:JDBC

14.1.JDBC框架

14.2.JDBCAPI

java.sql.Driver

  • Connection connect(String url, java.util.Properties info)

java.sql.DriverManager

  • static Connection getConnection(String url, String user, String password)

java.sql.Connection

  • Statement createStatement()

  • PreparedStatement prepareStatement(String sql)

  • CallableStatement prepareCall(String sql)

java.sql.Statement

  • ResultSet executeQuery(String sql)

  • int executeUpdate(String sql)

  • boolean execute(String sql)

java.sql.PreparedStatement

  • ResultSet executeQuery()

  • int executeUpdate()

  • boolean execute()

  • void setInt(int parameterIndex, int x)

  • void setString(int parameterIndex, String x)

java.sql.ResultSet

  • boolean next()

  • String getString(int columnIndex)

  • String getString(int columnLabel)

例,从user表中查询name为张三的用户信息:

String url = "jdbc:mysql://localhost:3306/mail_manager?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true";
String user = "root";
String password = "root";
Connection conn = null;
try {
    Class.forName("com.mysql.jdbc.Driver");
    conn = DriverManager.getConnection(url, username, password);
    PreparedStatement ps = conn.prepareStatement("select name, email from user where name=?");
    ps.setString(1, "张三");
    ResultSet rs = ps.executeQuery();
    while(rs.next()){
        String username = rs.getString("name");
        String email = rs.getString("email");
        System.out.println(username);
        System.out.println(email);
    }
}catch (ClassNotFoundException ignored){

}

14.3.JDBC Driver

com.mysql.jdbc.NonRegisteringDriver

// com.mysql.jdbc.NonRegisteringDriver
public Connection connect(String url, Properties info) {
    // ...
    com.mysql.jdbc.Connection newConn = ConnectionImpl.getInstance(this.host(props), this.port(props), props, this.database(props), url);
    // ...
}

protected static Connection getInstance(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException {
    return (Connection)(!Util.isJdbc4() ? new ConnectionImpl(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url) : (Connection)Util.handleNewInstance(JDBC_4_CONNECTION_CTOR, new Object[]{hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url}, (ExceptionInterceptor)null));
}

com.mysql.jdbc.ConnectionImpl

// com.mysql.jdbc.ConnectionImpl
public ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException {
    // ...
    this.createNewIO(false);
    // ...
}

public void createNewIO(boolean isForReconnect) throws SQLException {
    synchronized(this.getConnectionMutex()) {
        Properties mergedProps = this.exposeAsProperties(this.props);
        if (!this.getHighAvailability()) {
            this.connectOneTryOnly(isForReconnect, mergedProps);
        } else {
            this.connectWithRetries(isForReconnect, mergedProps);
        }
    }
}

private void connectOneTryOnly(boolean isForReconnect, Properties mergedProps) throws SQLException {
    // ...
    this.coreConnect(mergedProps);
     // ...
}

private void coreConnect(Properties mergedProps) throws SQLException, IOException {
    // ...
    this.io = new MysqlIO(newHost, newPort, mergedProps, this.getSocketFactoryClassName(), this.getProxy(), this.getSocketTimeout(), this.largeRowSizeThreshold.getValueAsInt());
    this.io.doHandshake(this.user, this.password, this.database);
    // ...
}

com.mysql.jdbc.MysqlIO
通过Socket与MysqlServer通信,通过mysqlInput与mysqlOutput传输数据

// com.mysql.jdbc.MysqlIO
public MysqlIO(String host, int port, Properties props, String socketFactoryClassName, MySQLConnection conn, int socketTimeout, int useBufferRowSizeThreshold) throws IOException, SQLException {
    // ...
    this.mysqlConnection = this.socketFactory.connect(this.host, this.port, props);
       
    this.mysqlConnection = this.socketFactory.beforeHandshake();
    if (this.connection.getUseReadAheadInput()) {
        this.mysqlInput = new ReadAheadInputStream(this.mysqlConnection.getInputStream(), 16384, this.connection.getTraceProtocol(), this.connection.getLog());
    } else if (this.connection.useUnbufferedInput()) {
        this.mysqlInput = this.mysqlConnection.getInputStream();
    } else {
        this.mysqlInput = new BufferedInputStream(this.mysqlConnection.getInputStream(), 16384);
    }

    this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection.getOutputStream(), 16384);
    // ...
}

com.mysql.jdbc.PreparedStatement
通过发送和接受Packet完成数据库查询

// com.mysql.jdbc.PreparedStatement
public ResultSet executeQuery() throws SQLException {
    synchronized(this.checkClosed().getConnectionMutex()) {
        // ...
        Buffer sendPacket = this.fillSendPacket();
        // ...
        this.results = this.executeInternal(this.maxRows, sendPacket, this.createStreamingResultSet(), true, metadataFromCache, false);
        // ...
        return this.results;
    }
}

protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly, Field[] metadataFromCache, boolean isBatch) throws SQLException {
    synchronized(this.checkClosed().getConnectionMutex()) {
        // ...
        ResultSetInternalMethods rs;
        rs = locallyScopedConnection.execSQL(this, (String)null, maxRowsToRetrieve, sendPacket, this.resultSetType, this.resultSetConcurrency, createStreamingResultSet, this.currentCatalog, metadataFromCache, isBatch);
        // ...          
    }
}

com.mysql.jdbc.ConnectionImpl

// com.mysql.jdbc.ConnectionImpl
public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Field[] cachedMetadata, boolean isBatch) throws SQLException {
    synchronized(this.getConnectionMutex()) {
        // ...
        ResultSetInternalMethods var36 = this.io.sqlQueryDirect(callingStatement, (String)null, (String)null, packet, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata);
        // ...
    }
}

com.mysql.jdbc.MysqlIO
通过Socket与MysqlServer通信,通过mysqlInput与mysqlOutput传输数据

// com.mysql.jdbc.MysqlIO
final ResultSetInternalMethods sqlQueryDirect(StatementImpl callingStatement, String query, String characterEncoding, Buffer queryPacket, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Field[] cachedMetadata) throws Exception {
    // ...
    this.sendPacket.writeByte((byte)3);
    
    if (characterEncoding != null) {
        if (this.platformDbCharsetMatches) {
            this.sendPacket.writeStringNoNull(query, characterEncoding, this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), this.connection);
        } else if (StringUtils.startsWithIgnoreCaseAndWs(query, "LOAD DATA")) {
            this.sendPacket.writeBytesNoNull(StringUtils.getBytes(query));
        } else {
            this.sendPacket.writeStringNoNull(query, characterEncoding, this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), this.connection);
        }
    } else {
        this.sendPacket.writeStringNoNull(query);
    }
 
    Buffer resultPacket = this.sendCommand(3, (String)null, queryPacket, false, (String)null, 0);
    // ...
}

final Buffer sendCommand(int command, String extraData, Buffer queryPacket, boolean skipCheck, String extraDataCharEncoding, int timeoutMillis) throws SQLException {
    // ...
    this.send(this.sendPacket, this.sendPacket.getPosition());
    // ...
}

private final void send(Buffer packet, int packetLen) throws SQLException {
    // ...
    Buffer packetToSend = packet;
    packet.setPosition(0);
    packet.writeLongInt(packetLen - 4);
    packet.writeByte(this.packetSequence);
    // ...
    this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);
    this.mysqlOutput.flush();
    // ...      
}

14.4.Mysql Server

参考https://dev.mysql.com/doc/internals/en/mysql-server.html#mysqld_stmt_fetch

以上是关于Java专题十四:JDBC的主要内容,如果未能解决你的问题,请参考以下文章

部分代码片段

Spring入门第二十四课

《寒假算法集训》(专题十四)深度优先搜索

打怪升级之小白的大数据之旅(三十四)<JDBC的数据库连接与基本操作>

python 并发专题(十四):asyncio 实战

python 并发专题(十四):asyncio 实战